Ticket #67: gui-i18n.patch
File gui-i18n.patch, 247.7 KB (added by , 11 years ago) |
---|
-
new file inaries/data/mods/public/globalscripts/l10n.js
diff --git a/binaries/data/mods/public/globalscripts/l10n.js b/binaries/data/mods/public/globalscripts/l10n.js new file mode 100644 index 0000000..3796687
- + 1 var g_translations = []; 2 var g_pluralTranslations = {}; 3 var g_translationsWithContext = {}; 4 var g_pluralTranslationsWithContext = {}; 5 6 7 // Translates the specified English message into the current language. 8 // 9 // This function relies on the g_translations cache when possible. You should use this function instead of 10 // Engine.translate() whenever you can to minimize the number of C++ calls and string conversions involved. 11 function translate(message) 12 { 13 var translation = g_translations[message]; 14 if (!translation) 15 return g_translations[message] = Engine.translate(message); 16 return translation; 17 } 18 19 20 // Translates the specified English message into the current language for the specified number. 21 // 22 // This function relies on the g_pluralTranslations cache when possible. You should use this function instead of 23 // Engine.translatePlural() whenever you can to minimize the number of C++ calls and string conversions involved. 24 function translatePlural(singularMessage, pluralMessage, number) 25 { 26 var translation = g_pluralTranslations[singularMessage]; 27 if (!translation) 28 g_pluralTranslations[singularMessage] = {}; 29 30 var pluralTranslation = g_pluralTranslations[singularMessage][number]; 31 if (!pluralTranslation) 32 return g_pluralTranslations[singularMessage][number] = Engine.translateWithContext(singularMessage, pluralMessage, number); 33 34 return pluralTranslation; 35 } 36 37 38 // Translates the specified English message into the current language for the specified context. 39 // 40 // This function relies on the g_translationsWithContext cache when possible. You should use this function instead of 41 // Engine.translateWithContext() whenever you can to minimize the number of C++ calls and string conversions involved. 42 function translateWithContext(context, message) 43 { 44 var translationContext = g_translationsWithContext[context]; 45 if (!translationContext) 46 g_translationsWithContext[context] = {} 47 48 var translationWithContext = g_translationsWithContext[context][message]; 49 if (!translationWithContext) 50 return g_translationsWithContext[context][message] = Engine.translateWithContext(context, message); 51 52 return translationWithContext; 53 } 54 55 56 // Translates the specified English message into the current language for the specified context and number. 57 // 58 // This function relies on the g_pluralTranslationsWithContext cache when possible. You should use this function instead of 59 // Engine.translateWithContext() whenever you can to minimize the number of C++ calls and string conversions involved. 60 function translatePluralWithContext(context, singularMessage, pluralMessage, number) 61 { 62 var translationContext = g_pluralTranslationsWithContext[context]; 63 if (!translationContext) 64 g_pluralTranslationsWithContext[context] = {}; 65 66 var translationWithContext = g_pluralTranslationsWithContext[context][singularMessage]; 67 if (!translationWithContext) 68 g_pluralTranslationsWithContext[context][singularMessage] = {}; 69 70 var pluralTranslationWithContext = g_pluralTranslationsWithContext[context][singularMessage][number]; 71 if (!pluralTranslationWithContext) 72 return g_pluralTranslationsWithContext[context][message][number] = Engine.translateWithContext(context, singularMessage, pluralMessage, number); 73 74 return pluralTranslationWithContext; 75 } 76 77 78 // Translates any string value in the specified JavaScript object that is associated with a key included in 79 // the specified keys array. 80 function translateObjectKeys(object, keys) { 81 for (property in object) 82 { 83 if (keys.indexOf(property) > -1) 84 { 85 if (object[property] != "" && object[property] !== undefined) 86 { 87 object[property] = translate(object[property]); 88 } 89 } 90 else 91 { 92 // From http://stackoverflow.com/a/7390612/939364 93 var variableType = ({}).toString.call(object[property]).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); 94 if (variableType === "object" || variableType == "array") 95 { 96 translateObjectKeys(object[property], keys); 97 } 98 } 99 } 100 } -
new file inaries/data/mods/public/globalscripts/sprintf.js
diff --git a/binaries/data/mods/public/globalscripts/sprintf.js b/binaries/data/mods/public/globalscripts/sprintf.js new file mode 100644 index 0000000..a641ec1
- + 1 /** 2 sprintf() for JavaScript 0.7-beta1 3 http://www.diveintojavascript.com/projects/javascript-sprintf 4 5 Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com> 6 All rights reserved. 7 8 Redistribution and use in source and binary forms, with or without 9 modification, are permitted provided that the following conditions are met: 10 * Redistributions of source code must retain the above copyright 11 notice, this list of conditions and the following disclaimer. 12 * Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 * Neither the name of sprintf() for JavaScript nor the 16 names of its contributors may be used to endorse or promote products 17 derived from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY 23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 31 Changelog: 32 2010.09.06 - 0.7-beta1 33 - features: vsprintf, support for named placeholders 34 - enhancements: format cache, reduced global namespace pollution 35 36 2010.05.22 - 0.6: 37 - reverted to 0.4 and fixed the bug regarding the sign of the number 0 38 Note: 39 Thanks to Raphael Pigulla <raph (at] n3rd [dot) org> (http://www.n3rd.org/) 40 who warned me about a bug in 0.5, I discovered that the last update was 41 a regress. I appologize for that. 42 43 2010.05.09 - 0.5: 44 - bug fix: 0 is now preceeded with a + sign 45 - bug fix: the sign was not at the right position on padded results (Kamal Abdali) 46 - switched from GPL to BSD license 47 48 2007.10.21 - 0.4: 49 - unit test and patch (David Baird) 50 51 2007.09.17 - 0.3: 52 - bug fix: no longer throws exception on empty paramenters (Hans Pufal) 53 54 2007.09.11 - 0.2: 55 - feature: added argument swapping 56 57 2007.04.03 - 0.1: 58 - initial release 59 **/ 60 61 var sprintf = (function() { 62 function get_type(variable) { 63 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); 64 } 65 function str_repeat(input, multiplier) { 66 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} 67 return output.join(''); 68 } 69 70 var str_format = function() { 71 if (!str_format.cache.hasOwnProperty(arguments[0])) { 72 str_format.cache[arguments[0]] = str_format.parse(arguments[0]); 73 } 74 return str_format.format.call(null, str_format.cache[arguments[0]], arguments); 75 }; 76 77 str_format.format = function(parse_tree, argv) { 78 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; 79 for (i = 0; i < tree_length; i++) { 80 node_type = get_type(parse_tree[i]); 81 if (node_type === 'string') { 82 output.push(parse_tree[i]); 83 } 84 else if (node_type === 'array') { 85 match = parse_tree[i]; // convenience purposes only 86 if (match[2]) { // keyword argument 87 arg = argv[cursor]; 88 for (k = 0; k < match[2].length; k++) { 89 if (!arg.hasOwnProperty(match[2][k])) { 90 throw(sprintf(Engine.translate('[sprintf] property "%s" does not exist'), match[2][k])); 91 } 92 arg = arg[match[2][k]]; 93 } 94 } 95 else if (match[1]) { // positional argument (explicit) 96 arg = argv[match[1]]; 97 } 98 else { // positional argument (implicit) 99 arg = argv[cursor++]; 100 } 101 102 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { 103 throw(sprintf(Engine.translate('[sprintf] expecting number but found %s'), get_type(arg))); 104 } 105 switch (match[8]) { 106 case 'b': arg = arg.toString(2); break; 107 case 'c': arg = String.fromCharCode(arg); break; 108 case 'd': arg = parseInt(arg, 10); break; 109 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; 110 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; 111 case 'o': arg = arg.toString(8); break; 112 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; 113 case 'u': arg = Math.abs(arg); break; 114 case 'x': arg = arg.toString(16); break; 115 case 'X': arg = arg.toString(16).toUpperCase(); break; 116 } 117 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); 118 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; 119 pad_length = match[6] - String(arg).length; 120 pad = match[6] ? str_repeat(pad_character, pad_length) : ''; 121 output.push(match[5] ? arg + pad : pad + arg); 122 } 123 } 124 return output.join(''); 125 }; 126 127 str_format.cache = {}; 128 129 str_format.parse = function(fmt) { 130 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; 131 while (_fmt) { 132 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { 133 parse_tree.push(match[0]); 134 } 135 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { 136 parse_tree.push('%'); 137 } 138 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { 139 if (match[2]) { 140 arg_names |= 1; 141 var field_list = [], replacement_field = match[2], field_match = []; 142 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { 143 field_list.push(field_match[1]); 144 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { 145 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { 146 field_list.push(field_match[1]); 147 } 148 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { 149 field_list.push(field_match[1]); 150 } 151 else { 152 throw(Engine.translate('[sprintf] huh?')); 153 } 154 } 155 } 156 else { 157 throw(Engine.translate('[sprintf] huh?')); 158 } 159 match[2] = field_list; 160 } 161 else { 162 arg_names |= 2; 163 } 164 if (arg_names === 3) { 165 throw(Engine.translate('[sprintf] mixing positional and named placeholders is not (yet) supported')); 166 } 167 parse_tree.push(match); 168 } 169 else { 170 throw(Engine.translate('[sprintf] huh?')); 171 } 172 _fmt = _fmt.substring(match[0].length); 173 } 174 return parse_tree; 175 }; 176 177 return str_format; 178 })(); 179 180 var vsprintf = function(fmt, argv) { 181 argv.unshift(fmt); 182 return sprintf.apply(null, argv); 183 }; -
binaries/data/mods/public/gui/aiconfig/aiconfig.js
diff --git a/binaries/data/mods/public/gui/aiconfig/aiconfig.js b/binaries/data/mods/public/gui/aiconfig/aiconfig.js index 76e6e20..1ce0a98 100644
a b function init(settings) 5 5 { 6 6 g_Callback = settings.callback; 7 7 8 translateObjectKeys(settings.ais, ["name", "description"]); 8 9 g_AIs = [ 9 {id: "", data: {name: "None", description: "AI will be disabled for this player."}}10 {id: "", data: {name: translateWithContext("ai", "None"), description: translate("AI will be disabled for this player.")}} 10 11 ].concat(settings.ais); 11 12 12 13 var aiSelection = getGUIObjectByName("aiSelection"); 13 aiSelection.list = [ ai.data.namefor each (ai in g_AIs) ];14 aiSelection.list = [ translate(ai.data.name) for each (ai in g_AIs) ]; 14 15 15 16 var selected = 0; 16 17 for (var i = 0; i < g_AIs.length; ++i) … … function init(settings) 24 25 aiSelection.selected = selected; 25 26 26 27 var aiDiff = getGUIObjectByName("aiDifficulty"); 27 aiDiff.list = [ "Sandbox", "Easy", "Medium", "Hard", "Very Hard"];28 aiDiff.list = [translate("Sandbox"), translate("Easy"), translate("Medium"), translate("Hard"), translate("Very Hard")]; 28 29 aiDiff.selected = settings.difficulty; 29 30 } 30 31 -
binaries/data/mods/public/gui/aiconfig/aiconfig.xml
diff --git a/binaries/data/mods/public/gui/aiconfig/aiconfig.xml b/binaries/data/mods/public/gui/aiconfig/aiconfig.xml index 19cf728..50b31b8 100644
a b 9 9 10 10 <object type="image" style="StoneDialog" size="50%-200 40%-140 50%+200 40%+180"> 11 11 12 <object style="TitleText" type="text" size="50%-128 -16 50%+128 16">AI Configuration</object> 12 <object style="TitleText" type="text" size="50%-128 -16 50%+128 16"> 13 <translatableAttribute id="caption">AI Configuration</translatableAttribute> 14 </object> 13 15 14 16 <object size="50%-128 30 50%+128 80"> 15 17 <object type="text" style="RightLabelText" size="-10 0 90 50%"> 16 AI Player18 <translatableAttribute id="caption">AI Player</translatableAttribute> 17 19 </object> 18 20 19 21 <object name="aiSelection" type="dropdown" style="StoneDropDown" size="50%-24 0 50%+136 28"> … … 21 23 </object> 22 24 23 25 <object type="text" style="RightLabelText" size="-10 35 90 50%+35"> 24 AI Difficulty26 <translatableAttribute id="caption">AI Difficulty</translatableAttribute> 25 27 </object> 26 28 27 29 <object name="aiDifficulty" type="dropdown" style="StoneDropDown" size="50%-24 35 50%+136 63"> … … 37 39 </object> 38 40 39 41 <object type="button" style="StoneButton" size="50%-144 100%-60 50%-16 100%-32"> 40 OK42 <translatableAttribute id="caption">OK</translatableAttribute> 41 43 <action on="Press">returnAI();</action> 42 44 </object> 43 45 44 46 <object type="button" style="StoneButton" size="50%+16 100%-60 50%+144 100%-32"> 45 Cancel47 <translatableAttribute id="caption">Cancel</translatableAttribute> 46 48 <action on="Press">Engine.PopGuiPage();</action> 47 49 </object> 48 50 </object> -
binaries/data/mods/public/gui/civinfo/civinfo.js
diff --git a/binaries/data/mods/public/gui/civinfo/civinfo.js b/binaries/data/mods/public/gui/civinfo/civinfo.js index d283cd8..0ef9168 100644
a b function selectCiv(code) 82 82 var civInfo = g_CivData[code]; 83 83 84 84 if(!civInfo) 85 error( "Error loading civ data for \""+code+"\"");85 error(sprintf(translateWithContext("civinfo", "Error loading civ data for \"%(code)s\""), { code: code })); 86 86 87 87 // Update civ gameplay display 88 getGUIObjectByName("civGameplayHeading").caption = heading(civInfo.Name+" Gameplay", 16); 89 88 getGUIObjectByName("civGameplayHeading").caption = heading(sprintf(translateWithContext("civinfo", "%(civilization)s Gameplay"), { civilization: civInfo.Name }), 16); 90 89 91 90 // Bonuses 92 var bonusCaption = heading( "Civilization Bonus"+(civInfo.CivBonuses.length == 1 ? "" : "es"), 12) + '\n';91 var bonusCaption = heading(translatePluralWithContext("civinfo", "Civilization Bonus", "Civilization Bonuses", civInfo.CivBonuses.length), 12) + '\n'; 93 92 94 93 for(var i = 0; i < civInfo.CivBonuses.length; ++i) 95 94 { … … function selectCiv(code) 97 96 + civInfo.CivBonuses[i].History + '" tooltip_style="civInfoTooltip"]\n ' + civInfo.CivBonuses[i].Description + '\n[/color]'; 98 97 } 99 98 100 bonusCaption += heading( "Team Bonus"+(civInfo.TeamBonuses.length == 1 ? "" : "es"), 12) + '\n';99 bonusCaption += heading(translatePluralWithContext("civinfo", "Team Bonus", "Team Bonuses", civInfo.TeamBonuses.length), 12) + '\n'; 101 100 102 101 for(var i = 0; i < civInfo.TeamBonuses.length; ++i) 103 102 { … … function selectCiv(code) 109 108 110 109 111 110 // Special techs / buildings 112 var techCaption = heading( "Special Technologies", 12) + '\n';111 var techCaption = heading(translate("Special Technologies"), 12) + '\n'; 113 112 114 113 for(var i = 0; i < civInfo.Factions.length; ++i) 115 114 { … … function selectCiv(code) 121 120 } 122 121 } 123 122 124 techCaption += heading( "Special Building"+(civInfo.Structures.length == 1 ? "" : "s"), 12) + '\n';123 techCaption += heading(translatePluralWithContext("civinfo", "Special Building", "Special Buildings", civInfo.Structures.length), 12) + '\n'; 125 124 126 125 for(var i = 0; i < civInfo.Structures.length; ++i) 127 126 { … … function selectCiv(code) 133 132 134 133 135 134 // Heroes 136 var heroCaption = heading( "Heroes", 12) + '\n';135 var heroCaption = heading(translateWithContext("civinfo", "Heroes"), 12) + '\n'; 137 136 138 137 for(var i = 0; i < civInfo.Factions.length; ++i) 139 138 { … … function selectCiv(code) 150 149 151 150 152 151 // Update civ history display 153 getGUIObjectByName("civHistoryHeading").caption = heading( "History of the " + civInfo.Name, 16);152 getGUIObjectByName("civHistoryHeading").caption = heading(sprintf(translateWithContext("civinfo", "History of the %(civilization)s"), { civilization: civInfo.Name }), 16); 154 153 getGUIObjectByName("civHistoryText").caption = civInfo.History; 155 154 } -
binaries/data/mods/public/gui/civinfo/civinfo.xml
diff --git a/binaries/data/mods/public/gui/civinfo/civinfo.xml b/binaries/data/mods/public/gui/civinfo/civinfo.xml index 2651364..22e3762 100644
a b 12 12 13 13 <object type="image" style="StoneDialog" size="50%-466 50%-316 50%+466 50%+316"> 14 14 15 <object style="TitleText" type="text" size="50%-128 -16 50%+128 16">Civilizations</object> 15 <object style="TitleText" type="text" size="50%-128 -16 50%+128 16"> 16 <translatableAttribute id="caption">Civilizations</translatableAttribute> 17 </object> 16 18 17 19 <!-- Civ selection --> 18 20 <object size="25 10 100% 30"> … … 23 25 textcolor="white" 24 26 text_align="left" 25 27 size="50%-320 10 50%-96 48"> 26 Civilization Selection28 <translatableAttribute id="caption">Civilization Selection</translatableAttribute> 27 29 </object> 28 30 29 31 <object name="civSelection" type="dropdown" style="StoneDropDown" size="50%-96 10 50%+96 40"> … … 112 114 type="button" 113 115 style="StoneButton" 114 116 size="100%-164 100%-52 100%-24 100%-24" 115 >Close 117 > 118 <translatableAttribute id="caption">Close</translatableAttribute> 116 119 <action on="Press"> 117 120 <![CDATA[ 118 121 Engine.PopGuiPage(); … … 122 125 123 126 </object> 124 127 125 </objects> 126 No newline at end of file 128 </objects> -
binaries/data/mods/public/gui/common/functions_civinfo.js
diff --git a/binaries/data/mods/public/gui/common/functions_civinfo.js b/binaries/data/mods/public/gui/common/functions_civinfo.js index f1495d4..9fa5808 100644
a b function loadCivData() 14 14 for each (var filename in civFiles) 15 15 { // Parse data if valid file 16 16 var data = parseJSONData(filename); 17 translateObjectKeys(data, ["Name", "Description", "History", "Special"]); 17 18 civData[data.Code] = data; 18 19 } 19 20 20 21 return civData; 21 22 } 22 23 23 // ==================================================================== 24 No newline at end of file 24 // ==================================================================== -
binaries/data/mods/public/gui/common/functions_global_object.js
diff --git a/binaries/data/mods/public/gui/common/functions_global_object.js b/binaries/data/mods/public/gui/common/functions_global_object.js index a030587..b1bce13 100644
a b function messageBox (mbWidth, mbHeight, mbMessage, mbTitle, mbMode, mbButtonCapt 29 29 30 30 function updateFPS() 31 31 { 32 getGUIObjectByName("fpsCounter").caption = "FPS: " + getFPS();32 getGUIObjectByName("fpsCounter").caption = sprintf(translate("FPS: %(fps)s"), { fps: getFPS() }); 33 33 } -
binaries/data/mods/public/gui/common/functions_utility.js
diff --git a/binaries/data/mods/public/gui/common/functions_utility.js b/binaries/data/mods/public/gui/common/functions_utility.js index 1c1a049..7348833 100644
a b function getJSONFileList(pathname) 60 60 function parseJSONData(pathname) 61 61 { 62 62 var data = {}; 63 63 64 64 var rawData = readFile(pathname); 65 65 if (!rawData) 66 66 { 67 error( "Failed to read file: "+pathname);67 error(sprintf(translate("Failed to read file: %(path)s"), { path: pathname })); 68 68 } 69 69 else 70 70 { … … function parseJSONData(pathname) 73 73 // TODO: Need more info from the parser on why it failed: line number, position, etc! 74 74 data = JSON.parse(rawData); 75 75 if (!data) 76 error( "Failed to parse JSON data in: "+pathname+" (check for valid JSON data)");77 78 76 error(sprintf(translate("Failed to parse JSON data in: %(path)s (check for valid JSON data)"), { path: pathname })); 77 78 79 79 } 80 80 catch(err) 81 81 { 82 error( err.toString()+": parsing JSON data in "+pathname);82 error(sprintf(translate("%(error)s: parsing JSON data in %(path)s"), { error: err.toString(), path: pathname })); 83 83 } 84 84 } 85 85 86 86 return data; 87 87 } 88 88 … … function parseJSONFromDataFile(filename) 141 141 var path = "simulation/data/"+filename; 142 142 var rawData = readFile(path); 143 143 if (!rawData) 144 error( "Failed to read file: "+path);144 error(sprintf(translate("Failed to read file: %(path)s"), { path: path })); 145 145 146 146 try 147 147 { … … function parseJSONFromDataFile(filename) 152 152 } 153 153 catch(err) 154 154 { 155 error( err.toString()+": parsing JSON data in "+path);155 error(sprintf(translate("%(error)s: parsing JSON data in %(path)s"), { error: err.toString(), path: path })); 156 156 } 157 157 158 158 return undefined; … … function initPlayerDefaults() 167 167 168 168 var data = parseJSONFromDataFile("player_defaults.json"); 169 169 if (!data || !data.PlayerData) 170 error( "Failed to parse player defaults in player_defaults.json (check for valid JSON data)");170 error(translate("Failed to parse player defaults in player_defaults.json (check for valid JSON data)")); 171 171 else 172 { 173 translateObjectKeys(data.PlayerData, ["Name"]) 172 174 defaults = data.PlayerData; 175 } 173 176 174 177 return defaults; 175 178 } … … function initMapSizes() 187 190 188 191 var data = parseJSONFromDataFile("map_sizes.json"); 189 192 if (!data || !data.Sizes) 190 error( "Failed to parse map sizes in map_sizes.json (check for valid JSON data)");193 error(translate("Failed to parse map sizes in map_sizes.json (check for valid JSON data)")); 191 194 else 192 195 { 196 translateObjectKeys(data, ["Name", "LongName"]); 193 197 for (var i = 0; i < data.Sizes.length; ++i) 194 198 { 195 199 sizes.names.push(data.Sizes[i].LongName); … … function initGameSpeeds() 216 220 217 221 var data = parseJSONFromDataFile("game_speeds.json"); 218 222 if (!data || !data.Speeds) 219 error( "Failed to parse game speeds in game_speeds.json (check for valid JSON data)");223 error(translate("Failed to parse game speeds in game_speeds.json (check for valid JSON data)")); 220 224 else 221 225 { 226 translateObjectKeys(data, ["Name"]); 222 227 for (var i = 0; i < data.Speeds.length; ++i) 223 228 { 224 229 gameSpeeds.names.push(data.Speeds[i].Name); … … function iColorToString(color) 254 259 */ 255 260 function timeToString(time) 256 261 { 257 var hours = Math.floor(time / 1000 / 60 / 60); 258 var minutes = Math.floor(time / 1000 / 60) % 60; 259 var seconds = Math.floor(time / 1000) % 60; 260 return hours + ':' + (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds); 262 return Engine.formatMillisecondsIntoDateString(time, translate("HH:mm:ss")); 261 263 } 262 264 263 265 // ==================================================================== … … function shuffleArray(source) 289 291 result[j] = source[i]; 290 292 } 291 293 return result; 292 } 293 No newline at end of file 294 } -
binaries/data/mods/public/gui/common/functions_utility_error.js
diff --git a/binaries/data/mods/public/gui/common/functions_utility_error.js b/binaries/data/mods/public/gui/common/functions_utility_error.js index 17254b3..e5618ee 100644
a b function cancelOnError(msg) 19 19 width: 500, 20 20 height: 200, 21 21 message: '[font="serif-bold-18"]' + msg + '[/font]', 22 title: "Loading Aborted",22 title: translate("Loading Aborted"), 23 23 mode: 2 24 24 }); 25 25 } -
binaries/data/mods/public/gui/common/functions_utility_list.js
diff --git a/binaries/data/mods/public/gui/common/functions_utility_list.js b/binaries/data/mods/public/gui/common/functions_utility_list.js index 0f3050c..9f77abb 100644
a b 11 11 function removeItem (objectName, pos) 12 12 { 13 13 if (getGUIObjectByName (objectName) == null) 14 Engine.Console_Write ( "removeItem(): " + objectName + " not found.");14 Engine.Console_Write (sprintf(translate("%(functionName)s: %(object)s not found."), { functionName: "removeItem()", object: objectName })); 15 15 16 16 var list = getGUIObjectByName (objectName).list; 17 17 var selected = getGUIObjectByName (objectName).selected; … … function removeItem (objectName, pos) 41 41 function addItem (objectName, pos, value) 42 42 { 43 43 if (getGUIObjectByName (objectName) == null) 44 Engine.Console_Write ( "addItem(): " + objectName + " not found.");44 Engine.Console_Write (sprintf(translate("%(functionName)s: %(object)s not found."), { functionName: "addItem()", object: objectName })); 45 45 46 46 var list = getGUIObjectByName (objectName).list; 47 47 var selected = getGUIObjectByName (objectName).selected; … … function addItem (objectName, pos, value) 66 66 function pushItem (objectName, value) 67 67 { 68 68 if (getGUIObjectByName (objectName) == null) 69 Engine.Console_Write ( "pushItem(): " + objectName + " not found.");69 Engine.Console_Write (sprintf(translate("%(functionName)s: %(object)s not found."), { functionName: "pushItem()", object: objectName })); 70 70 71 71 var list = getGUIObjectByName (objectName).list; 72 72 list.push (value); … … function pushItem (objectName, value) 81 81 function popItem (objectName) 82 82 { 83 83 if (getGUIObjectByName (objectName) == null) 84 Engine.Console_Write ( "popItem(): " + objectName + " not found.");84 Engine.Console_Write (sprintf(translate("%(functionName)s: %(object)s not found."), { functionName: "popItem()", object: objectName })); 85 85 86 86 var selected = getGUIObjectByName (objectName).selected; 87 87 removeItem(objectName, getNumItems(objectName)-1); … … function popItem (objectName) 98 98 function getNumItems (objectName) 99 99 { 100 100 if (getGUIObjectByName (objectName) == null) 101 Engine.Console_Write ( "getNumItems(): " + objectName + " not found.");101 Engine.Console_Write (sprintf(translate("%(functionName)s: %(object)s not found."), { functionName: "getNumItems()", object: objectName })); 102 102 103 103 var list = getGUIObjectByName(objectName).list; 104 104 return list.length; … … function getNumItems (objectName) 110 110 function getItemValue (objectName, pos) 111 111 { 112 112 if (getGUIObjectByName (objectName) == null) 113 Engine.Console_Write ( "getItemValue(): " + objectName + " not found.");113 Engine.Console_Write (sprintf(translate("%(functionName)s: %(object)s not found."), { functionName: "getItemValue()", object: objectName })); 114 114 115 115 var list = getGUIObjectByName(objectName).list; 116 116 return list[pos]; … … function getItemValue (objectName, pos) 122 122 function getCurrItemValue (objectName) 123 123 { 124 124 if (getGUIObjectByName (objectName) == null) 125 Engine.Console_Write ( "getCurrItemValue(): " + objectName + " not found.");125 Engine.Console_Write (sprintf(translate("%(functionName)s: %(object)s not found."), { functionName: "getCurrItemValue()", object: objectName })); 126 126 127 127 if (getGUIObjectByName(objectName).selected == -1) 128 128 return ""; … … function getCurrItemValue (objectName) 137 137 function setCurrItemValue (objectName, string) 138 138 { 139 139 if (getGUIObjectByName(objectName) == null) { 140 Engine.Console_Write ( "setCurrItemValue(): " + objectName + " not found.");140 Engine.Console_Write (sprintf(translate("%(functionName)s: %(object)s not found."), { functionName: "setCurrItemValue()", object: objectName })); 141 141 return -1; 142 142 } 143 143 … … function setCurrItemValue (objectName, string) 157 157 } 158 158 159 159 // Return -2 if failed to find value in list. 160 Engine.Console_Write ( "Requested string '" + string + "' not found in " + objectName + "'s list.");160 Engine.Console_Write (sprintf(translate("Requested string '%(string)s' not found in %(object)s's list."), { string: string, object: objectName })); 161 161 return -2; 162 162 } 163 163 -
binaries/data/mods/public/gui/common/functions_utility_loadsave.js
diff --git a/binaries/data/mods/public/gui/common/functions_utility_loadsave.js b/binaries/data/mods/public/gui/common/functions_utility_loadsave.js index 769a667..5807acc 100644
a b function sortDecreasingDate(a, b) 3 3 return b.metadata.time - a.metadata.time; 4 4 } 5 5 6 function twoDigits(n)7 {8 return n < 10 ? "0" + n : n;9 }10 11 6 function generateLabel(metadata) 12 7 { 13 var t = new Date(metadata.time*1000); 14 15 var date = t.getFullYear()+"-"+twoDigits(1+t.getMonth())+"-"+twoDigits(t.getDate()); 16 var time = twoDigits(t.getHours())+":"+twoDigits(t.getMinutes())+":"+twoDigits(t.getSeconds()); 17 return "["+date+" "+time+"] "+metadata.initAttributes.map+(metadata.description ? " - "+metadata.description : ""); 8 var dateTimeString = Engine.formatMillisecondsIntoDateString(metadata.time, translate("yyyy-MM-dd HH:mm:ss")); 9 if (metadata.description) 10 { 11 return sprintf(translate("[%(date)s] %(map)s - %(description)s"), { date: dateTimeString, map: metadata.initAttributes.map, description: metadata.description }); 12 } 13 else 14 { 15 return sprintf(translate("[%(date)s] %(map)s"), { date: dateTimeString, map: metadata.initAttributes.map }); 16 } 18 17 } -
binaries/data/mods/public/gui/common/functions_utility_music.js
diff --git a/binaries/data/mods/public/gui/common/functions_utility_music.js b/binaries/data/mods/public/gui/common/functions_utility_music.js index f9631d8..3bc245b 100644
a b function newRandomSound(soundType, soundSubType, soundPrePath) 53 53 var soundArray = buildDirEntList(randomSoundPath, "*" + soundSubType + "*", false); 54 54 if (soundArray.length == 0) 55 55 { 56 Engine.Console_Write ( "Failed to find sounds matching '*"+soundSubType+"*'");56 Engine.Console_Write (sprintf(translate("Failed to find sounds matching '*%(subtype)s*'"), { soundSubType: subtype })); 57 57 return undefined; 58 58 } 59 59 // Get a random number within the sound's range. … … function newRandomSound(soundType, soundSubType, soundPrePath) 75 75 return new AmbientSound(randomSoundPath); 76 76 break; 77 77 case "effect": 78 Engine.Console_Write( "am loading effect '*"+randomSoundPath+"*'");78 Engine.Console_Write(sprintf(translate("am loading effect '*%(path)s*'"), { path: randomSoundPath })); 79 79 break; 80 80 default: 81 81 break; -
binaries/data/mods/public/gui/common/music.js
diff --git a/binaries/data/mods/public/gui/common/music.js b/binaries/data/mods/public/gui/common/music.js index 843f3af..d2efef9 100644
a b Music.prototype.updateState = function() 108 108 break; 109 109 110 110 default: 111 warn( "Music.updateState(): Unknown music state: " + this.currentState);111 warn(sprintf(translate("%(functionName)s: Unknown music state: %(state)s"), { functionName: "Music.updateState()", state: this.currentState })); 112 112 break; 113 113 } 114 114 } … … Music.prototype.storeTracks = function(civMusic) 131 131 132 132 if (type === undefined) 133 133 { 134 warn( "Music.storeTracks(): Unrecognized music type: " + music.Type);134 warn(sprintf(translate("%(functionName)s: Unrecognized music type: %(musicType)s"), { functionName: "Music.storeTracks()", musicType: music.Type })); 135 135 continue; 136 136 } 137 137 -
binaries/data/mods/public/gui/common/network.js
diff --git a/binaries/data/mods/public/gui/common/network.js b/binaries/data/mods/public/gui/common/network.js index 081d0f0..89b2d66 100644
a b function getDisconnectReason(id) 3 3 // Must be kept in sync with source/network/NetHost.h 4 4 switch (id) 5 5 { 6 case 0: return "Unknown reason";7 case 1: return "Unexpected shutdown";8 case 2: return "Incorrect network protocol version";9 case 3: return "Game has already started";10 default: return "[Invalid value "+id+"]";6 case 0: return translate("Unknown reason"); 7 case 1: return translate("Unexpected shutdown"); 8 case 2: return translate("Incorrect network protocol version"); 9 case 3: return translate("Game has already started"); 10 default: return sprintf(translate("[Invalid value %(id)s]"), { id: id }); 11 11 } 12 12 } 13 13 … … function reportDisconnect(reason) 16 16 var reasontext = getDisconnectReason(reason); 17 17 18 18 messageBox(400, 200, 19 "Lost connection to the server.\n\nReason: " + reasontext + ".",20 "Disconnected", 2);19 translate("Lost connection to the server.") + "\n\n" + sprintf(translate("Reason: %(reason)s."), { reason: reasontext }), 20 translate("Disconnected"), 2); 21 21 } -
binaries/data/mods/public/gui/common/timer.js
diff --git a/binaries/data/mods/public/gui/common/timer.js b/binaries/data/mods/public/gui/common/timer.js index 5391ba7..80c6a02 100644
a b function updateTimers() 45 45 t[1](); 46 46 } catch (e) { 47 47 var stack = e.stack.trimRight().replace(/^/mg, ' '); // indent the stack trace 48 error( "Error in timer: "+e+"\n"+stack+"\n");48 error(sprintf(translate("Error in timer: %(error)s"), { error: e })+"\n"+stack+"\n"); 49 49 } 50 50 delete g_Timers[id]; 51 51 } -
binaries/data/mods/public/gui/gamesetup/gamesetup.js
diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.js b/binaries/data/mods/public/gui/gamesetup/gamesetup.js index 6ce3102..2001f6b 100644
a b const DEFAULT_NETWORKED_MAP = "Acropolis 01"; 4 4 const DEFAULT_OFFLINE_MAP = "Acropolis 01"; 5 5 6 6 // TODO: Move these somewhere like simulation\data\game_types.json, Atlas needs them too 7 const VICTORY_TEXT = [ "Conquest", "None"];7 const VICTORY_TEXT = [translate("Conquest"), translateWithContext("victory", "None")]; 8 8 const VICTORY_DATA = ["conquest", "endless"]; 9 9 const VICTORY_DEFAULTIDX = 0; 10 const POPULATION_CAP = ["50", "100", "150", "200", "250", "300", "Unlimited"];10 const POPULATION_CAP = ["50", "100", "150", "200", "250", "300", translate("Unlimited")]; 11 11 const POPULATION_CAP_DATA = [50, 100, 150, 200, 250, 300, 10000]; 12 12 const POPULATION_CAP_DEFAULTIDX = 5; 13 const STARTING_RESOURCES = [ "Very Low", "Low", "Medium", "High", "Very High", "Deathmatch"];13 const STARTING_RESOURCES = [translate("Very Low"), translate("Low"), translate("Medium"), translate("High"), translate("Very High"), translate("Deathmatch")]; 14 14 const STARTING_RESOURCES_DATA = [100, 300, 500, 1000, 3000, 50000]; 15 15 const STARTING_RESOURCES_DEFAULTIDX = 1; 16 16 // Max number of players for any map … … var g_CivData = {}; 50 50 var g_MapFilters = []; 51 51 52 52 // Warn about the AI's nonexistent naval map support. 53 var g_NavalWarning = "\n\n[font=\"serif-bold-12\"][color=\"orange\"]Warning:[/color][/font] \ 54 The AI does not support naval maps and may cause severe performance issues. \ 55 Naval maps are recommended to be played with human opponents only."; 53 var g_NavalWarning = "\n\n" + sprintf( 54 translate("%(warning)s The AI does not support naval maps and may cause severe performance issues. Naval maps are recommended to be played with human opponents only."), 55 { warning: "[font=\"serif-bold-12\"][color=\"orange\"]" + translate("Warning:") + "[/color][/font]" } 56 ); 56 57 57 58 // To prevent the display locking up while we load the map metadata, 58 59 // we'll start with a 'loading' message and switch to the main screen in the … … function init(attribs) 78 79 g_IsController = false; 79 80 break; 80 81 default: 81 error( "Unexpected 'type' in gamesetup init: "+attribs.type);82 error(sprintf(translate("Unexpected 'type' in gamesetup init: %(unexpectedType)s"), { unexpectedType: attribs.type })); 82 83 } 83 84 } 84 85 … … function initMain() 107 108 108 109 // Init map types 109 110 var mapTypes = getGUIObjectByName("mapTypeSelection"); 110 mapTypes.list = [ "Scenario","Skirmish","Random"];111 mapTypes.list = [translate("Scenario"), translateWithContext("map", "Skirmish"), translateWithContext("map", "Random")]; 111 112 mapTypes.list_data = ["scenario","skirmish","random"]; 112 113 113 114 // Setup map filters - will appear in order they are added 114 addFilter(" Default", function(settings) { return settings && !keywordTestOR(settings.Keywords, ["naval", "demo", "hidden"]); });115 addFilter(" Naval Maps", function(settings) { return settings && keywordTestAND(settings.Keywords, ["naval"]); });116 addFilter(" Demo Maps", function(settings) { return settings && keywordTestAND(settings.Keywords, ["demo"]); });117 addFilter(" All Maps", function(settings) { return true; });115 addFilter("default", translate("Default"), function(settings) { return settings && !keywordTestOR(settings.Keywords, ["naval", "demo", "hidden"]); }); 116 addFilter("naval", translate("Naval Maps"), function(settings) { return settings && keywordTestAND(settings.Keywords, ["naval"]); }); 117 addFilter("demo", translate("Demo Maps"), function(settings) { return settings && keywordTestAND(settings.Keywords, ["demo"]); }); 118 addFilter("all", translate("All Maps"), function(settings) { return true; }); 118 119 119 120 // Populate map filters dropdown 120 121 var mapFilters = getGUIObjectByName("mapFilterSelection"); 121 mapFilters.list = getFilters(); 122 g_GameAttributes.mapFilter = "Default"; 122 mapFilters.list = getFilterNames(); 123 mapFilters.list_data = getFilterIds(); 124 g_GameAttributes.mapFilter = "default"; 123 125 124 126 // Setup controls for host only 125 127 if (g_IsController) … … function initMain() 287 289 288 290 // Populate team dropdowns 289 291 var team = getGUIObjectByName("playerTeam["+i+"]"); 290 team.list = [ "None", "1", "2", "3", "4"];292 team.list = [translateWithContext("team", "None"), "1", "2", "3", "4"]; 291 293 team.list_data = [-1, 0, 1, 2, 3]; 292 294 team.selected = 0; 293 295 … … function initCivNameList() 447 449 var civListCodes = [ civ.code for each (civ in civList) ]; 448 450 449 451 // Add random civ to beginning of list 450 civListNames.unshift("[color=\"orange\"] Random");452 civListNames.unshift("[color=\"orange\"]" + translateWithContext("civilization", "Random")); 451 453 civListCodes.unshift("random"); 452 454 453 455 // Update the dropdowns … … function initMapNameList() 480 482 break; 481 483 482 484 default: 483 error( "initMapNameList: Unexpected map type '"+g_GameAttributes.mapType+"'");485 error(sprintf(translate("initMapNameList: Unexpected map type '%(mapType)s'"), { mapType: g_GameAttributes.mapType })); 484 486 return; 485 487 } 486 488 … … function initMapNameList() 498 500 // Alphabetically sort the list, ignoring case 499 501 mapList.sort(sortNameIgnoreCase); 500 502 if (g_GameAttributes.mapType == "random") 501 mapList.unshift({ "name": "[color=\"orange\"] Random[/color]", "file": "random" });503 mapList.unshift({ "name": "[color=\"orange\"]" + translateWithContext("map", "Random") + "[/color]", "file": "random" }); 502 504 503 505 var mapListNames = [ map.name for each (map in mapList) ]; 504 506 var mapListFiles = [ map.file for each (map in mapList) ]; … … function loadMapData(name) 529 531 case "scenario": 530 532 case "skirmish": 531 533 g_MapData[name] = Engine.LoadMapSettings(name); 534 translateObjectKeys(g_MapData[name], ["Name", "Description"]); 532 535 break; 533 536 534 537 case "random": 535 538 if (name == "random") 536 g_MapData[name] = { settings : {"Name" : "Random", "Description" : "Randomly selects a map from the list"}};539 g_MapData[name] = { settings: { "Name": translateWithContext("map", "Random"), "Description": translate("Randomly selects a map from the list") } }; 537 540 else 541 { 538 542 g_MapData[name] = parseJSONData(name+".json"); 543 translateObjectKeys(g_MapData[name], ["Name", "Description"]); 544 } 539 545 break; 540 546 541 547 default: 542 error( "loadMapData: Unexpected map type '"+g_GameAttributes.mapType+"'");548 error(sprintf(translate("loadMapData: Unexpected map type '%(mapType)s'"), { mapType: g_GameAttributes.mapType })); 543 549 return undefined; 544 550 } 545 551 } … … function selectNumPlayers(num) 620 626 if (g_IsNetworked) 621 627 Engine.AssignNetworkPlayer(player, ""); 622 628 else 623 g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1} };629 g_PlayerAssignments = { "local": { "name": translate("You"), "player": 1, "civ": "", "team": -1} }; 624 630 } 625 631 } 626 632 … … function selectMapType(type) 674 680 break; 675 681 676 682 default: 677 error( "selectMapType: Unexpected map type '"+g_GameAttributes.mapType+"'");683 error(sprintf(translate("selectMapType: Unexpected map type '%(mapType)s'"), { mapType: g_GameAttributes.mapType })); 678 684 return; 679 685 } 680 686 … … function selectMapType(type) 683 689 updateGameAttributes(); 684 690 } 685 691 686 function selectMapFilter( filterName)692 function selectMapFilter(id) 687 693 { 688 694 // Avoid recursion 689 695 if (g_IsInGuiUpdate) … … function selectMapFilter(filterName) 693 699 if (g_IsNetworked && !g_IsController) 694 700 return; 695 701 696 g_GameAttributes.mapFilter = filterName;702 g_GameAttributes.mapFilter = id; 697 703 698 704 initMapNameList(); 699 705 … … function selectMap(name) 721 727 // Copy any new settings 722 728 g_GameAttributes.map = name; 723 729 g_GameAttributes.script = mapSettings.Script; 724 if ( mapData !== "Random")730 if (g_GameAttributes.map !== "random") 725 731 for (var prop in mapSettings) 726 732 g_GameAttributes.settings[prop] = mapSettings[prop]; 727 733 … … function selectMap(name) 737 743 // Reset player assignments on map change 738 744 if (!g_IsNetworked) 739 745 { // Slot 1 740 g_PlayerAssignments = { "local": { "name": "You", "player": 1, "civ": "", "team": -1} };746 g_PlayerAssignments = { "local": { "name": translate("You"), "player": 1, "civ": "", "team": -1} }; 741 747 } 742 748 else 743 749 { … … function launchGame() 759 765 { 760 766 if (g_IsNetworked && !g_IsController) 761 767 { 762 error( "Only host can start game");768 error(translate("Only host can start game")); 763 769 return; 764 770 } 765 771 … … function launchGame() 812 818 usedName++; 813 819 814 820 // Assign civ specific names to AI players 821 chosenName = translate(chosenName); 815 822 if (usedName) 816 g_GameAttributes.settings.PlayerData[i].Name = chosenName + " " + romanNumbers[usedName+1];823 g_GameAttributes.settings.PlayerData[i].Name = sprintf(translate("%(playerName)s %(romanNumber)s"), { playerName: chosenName, romanNumber: romanNumbers[usedName+1]}); 817 824 else 818 825 g_GameAttributes.settings.PlayerData[i].Name = chosenName; 819 826 } … … function onGameAttributesChange() 862 869 // Update some controls for clients 863 870 if (!g_IsController) 864 871 { 865 getGUIObjectByName("mapFilterText").caption = g_GameAttributes.mapFilter; 872 var mapFilderSelection = getGUIObjectByName("mapFilterText"); 873 var mapFilterId = mapFilderSelection.list_data.indexOf(g_GameAttributes.mapFilter); 874 getGUIObjectByName("mapFilterText").caption = mapFilderSelection.list[mapFilterId]; 866 875 var mapTypeSelection = getGUIObjectByName("mapTypeSelection"); 867 876 var idx = mapTypeSelection.list_data.indexOf(g_GameAttributes.mapType); 868 877 getGUIObjectByName("mapTypeText").caption = mapTypeSelection.list[idx]; … … function onGameAttributesChange() 900 909 var speedIdx = (g_GameAttributes.gameSpeed !== undefined && g_GameSpeeds.speeds.indexOf(g_GameAttributes.gameSpeed) != -1) ? g_GameSpeeds.speeds.indexOf(g_GameAttributes.gameSpeed) : g_GameSpeeds["default"]; 901 910 var victoryIdx = (VICTORY_DATA.indexOf(mapSettings.GameType) != -1 ? VICTORY_DATA.indexOf(mapSettings.GameType) : VICTORY_DEFAULTIDX); 902 911 enableCheats.checked = (g_GameAttributes.settings.CheatsEnabled === undefined || !g_GameAttributes.settings.CheatsEnabled ? false : true) 903 enableCheatsText.caption = (enableCheats.checked ? "Yes" : "No");912 enableCheatsText.caption = (enableCheats.checked ? translate("Yes") : translate("No")); 904 913 gameSpeedText.caption = g_GameSpeeds.names[speedIdx]; 905 914 populationCap.selected = (POPULATION_CAP_DATA.indexOf(mapSettings.PopulationCap) != -1 ? POPULATION_CAP_DATA.indexOf(mapSettings.PopulationCap) : POPULATION_CAP_DEFAULTIDX); 906 915 populationCapText.caption = POPULATION_CAP[populationCap.selected]; … … function onGameAttributesChange() 934 943 populationCapText.hidden = true; 935 944 startingResourcesText.hidden = true; 936 945 937 mapSizeText.caption = "Map size:";946 mapSizeText.caption = translate("Map size:"); 938 947 mapSize.selected = sizeIdx; 939 revealMapText.caption = "Reveal map:";948 revealMapText.caption = translate("Reveal map:"); 940 949 revealMap.checked = (mapSettings.RevealMap ? true : false); 941 950 942 victoryConditionText.caption = "Victory condition:";951 victoryConditionText.caption = translate("Victory condition:"); 943 952 victoryCondition.selected = victoryIdx; 944 lockTeamsText.caption = "Teams locked:";953 lockTeamsText.caption = translate("Teams locked:"); 945 954 lockTeams.checked = (mapSettings.LockTeams ? true : false); 946 955 } 947 956 else … … function onGameAttributesChange() 959 968 960 969 numPlayersText.caption = numPlayers; 961 970 mapSizeText.caption = g_MapSizes.names[sizeIdx]; 962 revealMapText.caption = (mapSettings.RevealMap ? "Yes" : "No");971 revealMapText.caption = (mapSettings.RevealMap ? translate("Yes") : translate("No")); 963 972 victoryConditionText.caption = VICTORY_TEXT[victoryIdx]; 964 lockTeamsText.caption = (mapSettings.LockTeams ? "Yes" : "No");973 lockTeamsText.caption = (mapSettings.LockTeams ? translate("Yes") : translate("No")); 965 974 } 966 975 967 976 break; … … function onGameAttributesChange() 1035 1044 startingResourcesText.hidden = false; 1036 1045 1037 1046 numPlayersText.caption = numPlayers; 1038 mapSizeText.caption = "Default";1039 revealMapText.caption = (mapSettings.RevealMap ? "Yes" : "No");1047 mapSizeText.caption = translate("Default"); 1048 revealMapText.caption = (mapSettings.RevealMap ? translate("Yes") : translate("No")); 1040 1049 victoryConditionText.caption = VICTORY_TEXT[victoryIdx]; 1041 lockTeamsText.caption = (mapSettings.LockTeams ? "Yes" : "No");1050 lockTeamsText.caption = (mapSettings.LockTeams ? translate("Yes") : translate("No")); 1042 1051 getGUIObjectByName("populationCap").selected = POPULATION_CAP_DEFAULTIDX; 1043 1052 1044 1053 break; 1045 1054 1046 1055 default: 1047 error( "onGameAttributesChange: Unexpected map type '"+g_GameAttributes.mapType+"'");1056 error(sprintf(translate("onGameAttributesChange: Unexpected map type '%(mapType)s'"), { mapType: g_GameAttributes.mapType })); 1048 1057 return; 1049 1058 } 1050 1059 … … function onGameAttributesChange() 1052 1061 getGUIObjectByName("mapInfoName").caption = getMapDisplayName(mapName); 1053 1062 1054 1063 // Load the description from the map file, if there is one 1055 var description = mapSettings.Description || "Sorry, no description available.";1064 var description = mapSettings.Description || translate("Sorry, no description available."); 1056 1065 1057 if (g_GameAttributes.mapFilter == " Naval Maps")1066 if (g_GameAttributes.mapFilter == "naval") 1058 1067 description += g_NavalWarning; 1059 1068 1060 1069 // Describe the number of players 1061 var playerString = numPlayers + " " + (numPlayers == 1 ? "player" : "players") + ". ";1070 var playerString = sprintf(translatePlural("%(number)s player. %(description)s", "%(number)s players. %(description)s", numPlayers), { number: numPlayers, description: description }); 1062 1071 1063 1072 for (var i = 0; i < MAX_PLAYERS; ++i) 1064 1073 { … … function onGameAttributesChange() 1097 1106 pTeam.hidden = true; 1098 1107 // Set text values 1099 1108 if (civ == "random") 1100 pCivText.caption = "[color=\"orange\"] Random";1109 pCivText.caption = "[color=\"orange\"]" + translateWithContext("civilization", "Random"); 1101 1110 else 1102 1111 pCivText.caption = g_CivData[civ].Name; 1103 1112 pTeamText.caption = (team !== undefined && team >= 0) ? team+1 : "-"; … … function onGameAttributesChange() 1114 1123 } 1115 1124 } 1116 1125 1117 getGUIObjectByName("mapInfoDescription").caption = playerString + description;1126 getGUIObjectByName("mapInfoDescription").caption = playerString; 1118 1127 1119 1128 g_IsInGuiUpdate = false; 1120 1129 … … function updatePlayerList() 1178 1187 } 1179 1188 // Give AI a different color so it stands out 1180 1189 aiAssignments[ai.id] = hostNameList.length; 1181 hostNameList.push("[color=\"70 150 70 255\"] AI: " + ai.data.name);1190 hostNameList.push("[color=\"70 150 70 255\"]" + sprintf(translate("AI: %(ai)s"), { ai: translate(ai.data.name) })); 1182 1191 hostGuidList.push("ai:" + ai.id); 1183 1192 } 1184 1193 1185 1194 noAssignment = hostNameList.length; 1186 hostNameList.push("[color=\"140 140 140 255\"] Unassigned");1195 hostNameList.push("[color=\"140 140 140 255\"]" + translate("Unassigned")); 1187 1196 hostGuidList.push(""); 1188 1197 1189 1198 for (var i = 0; i < MAX_PLAYERS; ++i) … … function updatePlayerList() 1210 1219 if (aiId in aiAssignments) 1211 1220 selection = aiAssignments[aiId]; 1212 1221 else 1213 warn( "AI \""+aiId+"\" not present. Defaulting to unassigned.");1222 warn(sprintf(translate("AI \"%(id)s\" not present. Defaulting to unassigned."), { id: aiId })); 1214 1223 } 1215 1224 1216 1225 if (!selection) … … function addChatMessage(msg) 1385 1394 switch (msg.type) 1386 1395 { 1387 1396 case "connect": 1388 formatted = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font] [color="gold"]has joined[/color]'; 1397 var formattedUsername = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font][color="gold"]' 1398 formatted = '[color="gold"]' + sprintf(translate("%(username)s has joined"), { username: formattedUsername }); 1389 1399 break; 1390 1400 1391 1401 case "disconnect": 1392 formatted = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font] [color="gold"]has left[/color]'; 1402 var formattedUsername = '[font="serif-bold-13"][color="'+ color +'"]' + username + '[/color][/font][color="gold"]' 1403 formatted = '[color="gold"]' + sprintf(translate("%(username)s has left"), { username: formattedUsername }); 1393 1404 break; 1394 1405 1395 1406 case "message": 1396 formatted = '[font="serif-bold-13"]<[color="'+ color +'"]' + username + '[/color]>[/font] ' + message; 1407 var formattedUsername = '[color="'+ color +'"]' + username + '[/color]' 1408 var formattedUsernamePrefix = '[font="serif-bold-13"]' + sprintf(translate("<%(username)s>"), { username: formattedUsername }) + '[/font]' 1409 formatted = sprintf(translate("%(username)s %(message)s"), { username: formattedUsernamePrefix, message: message }); 1397 1410 break; 1398 1411 1399 1412 default: 1400 error( "Invalid chat message '" + uneval(msg) + "'");1413 error(sprintf(translate("Invalid chat message '%(message)s'"), { message: uneval(msg) })); 1401 1414 return; 1402 1415 } 1403 1416 … … function toggleMoreOptions() 1415 1428 // Basic map filters API 1416 1429 1417 1430 // Add a new map list filter 1418 function addFilter( name, filterFunc)1431 function addFilter(id, name, filterFunc) 1419 1432 { 1420 1433 if (filterFunc instanceof Object) 1421 1434 { // Basic validity test 1422 1435 var newFilter = {}; 1436 newFilter.id = id; 1423 1437 newFilter.name = name; 1424 1438 newFilter.filter = filterFunc; 1425 1439 … … function addFilter(name, filterFunc) 1427 1441 } 1428 1442 else 1429 1443 { 1430 error( "Invalid map filter: "+name);1444 error(sprintf(translate("Invalid map filter: %(name)s"), { name: name })); 1431 1445 } 1432 1446 } 1433 1447 1448 // Get array of map filter IDs 1449 function getFilterIds() 1450 { 1451 var filters = []; 1452 for (var i = 0; i < g_MapFilters.length; ++i) 1453 filters.push(g_MapFilters[i].id); 1454 1455 return filters; 1456 } 1457 1434 1458 // Get array of map filter names 1435 function getFilter s()1459 function getFilterNames() 1436 1460 { 1437 1461 var filters = []; 1438 1462 for (var i = 0; i < g_MapFilters.length; ++i) … … function getFilters() 1442 1466 } 1443 1467 1444 1468 // Test map filter on given map settings object 1445 function testFilter( name, mapSettings)1469 function testFilter(id, mapSettings) 1446 1470 { 1447 1471 for (var i = 0; i < g_MapFilters.length; ++i) 1448 if (g_MapFilters[i]. name == name)1472 if (g_MapFilters[i].id == id) 1449 1473 return g_MapFilters[i].filter(mapSettings); 1450 1474 1451 error( "Invalid map filter: "+name);1475 error(sprintf(translate("Invalid map filter: %(id)s"), { id: id })); 1452 1476 return false; 1453 1477 } 1454 1478 -
binaries/data/mods/public/gui/gamesetup/gamesetup.xml
diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.xml b/binaries/data/mods/public/gui/gamesetup/gamesetup.xml index 157afc5..cb2213a 100644
a b 12 12 <object type="image" style="StoneWindow" size="0 0 100% 100%"> 13 13 14 14 <object style="TitleText" type="text" size="50%-128 4 50%+128 36"> 15 Match Setup15 <translatableAttribute id="caption">Match Setup</translatableAttribute> 16 16 </object> 17 17 18 18 <object type="image" style="StoneDialog" size="50%-190 50%-80 50%+190 50%+80" name="loadingWindow"> 19 19 20 20 <object type="text" style="TitleText" size="50%-128 0%-16 50%+128 16"> 21 Loading21 <translatableAttribute id="caption">Loading</translatableAttribute> 22 22 </object> 23 23 24 24 <object type="text" style="CenteredLabelText"> 25 Loading map data. Please wait...25 <translatableAttribute id="caption">Loading map data. Please wait...</translatableAttribute> 26 26 </object> 27 27 28 28 </object> … … 38 38 39 39 <!-- Number of Players--> 40 40 <object size="0 0 150 28"> 41 <object size="0 0 100% 100%" type="text" style="RightLabelText">Number of players:</object> 41 <object size="0 0 100% 100%" type="text" style="RightLabelText"> 42 <translatableAttribute id="caption">Number of players:</translatableAttribute> 43 </object> 42 44 </object> 43 45 44 46 <!-- Number of Players--> … … 48 50 type="dropdown" 49 51 style="StoneDropDown" 50 52 size="0 0 100% 28" 51 tooltip_style="onscreenToolTip" 52 tooltip="Select number of players.">53 tooltip_style="onscreenToolTip"> 54 <translatableAttribute id="tooltip">Select number of players.</translatableAttribute> 53 55 <action on="SelectionChange">selectNumPlayers(this.list_data[this.selected]);</action> 54 56 </object> 55 57 </object> … … 59 61 <!-- Player assignments --> 60 62 <object size="24 59 100%-440 358" type="image" sprite="BackgroundIndentFillDark" name="playerAssignmentsPannel"> 61 63 <object size="0 6 100% 30"> 62 <object name="playerNameHeading" type="text" style="CenteredLabelText" size="0 0 25% 100%">Player Name</object> 63 <object name="playerPlacementHeading" type="text" style="CenteredLabelText" size="25%+5 0 55% 100%">Player Placement</object> 64 <object name="playerCivHeading" type="text" style="CenteredLabelText" size="55%+65 0 85% 100%">Civilization</object> 64 <object name="playerNameHeading" type="text" style="CenteredLabelText" size="0 0 25% 100%"> 65 <translatableAttribute id="caption">Player Name</translatableAttribute> 66 </object> 67 <object name="playerPlacementHeading" type="text" style="CenteredLabelText" size="25%+5 0 55% 100%"> 68 <translatableAttribute id="caption">Player Placement</translatableAttribute> 69 </object> 70 <object name="playerCivHeading" type="text" style="CenteredLabelText" size="55%+65 0 85% 100%"> 71 <translatableAttribute id="caption">Civilization</translatableAttribute> 72 </object> 65 73 <object name="civInfoButton" 66 74 type="button" 67 75 sprite="iconInfoGold" 68 76 sprite_over="iconInfoWhite" 69 77 size="85%-8 0 85%+8 16" 70 78 tooltip_style="onscreenToolTip" 71 tooltip="View civilization info"72 79 > 80 <translatableAttribute id="tooltip">View civilization info</translatableAttribute> 73 81 <action on="Press"><![CDATA[ 74 82 Engine.PushGuiPage("page_civinfo.xml"); 75 83 ]]></action> 76 84 </object> 77 <object name="playerTeamHeading" type="text" style="CenteredLabelText" size="85%+5 0 100%-5 100%">Team</object> 85 <object name="playerTeamHeading" type="text" style="CenteredLabelText" size="85%+5 0 100%-5 100%"> 86 <translatableAttribute id="caption">Team</translatableAttribute> 87 </object> 78 88 </object> 79 89 <object size="1 36 100%-1 100%"> 80 90 <repeat count="8"> 81 91 <object name="playerBox[n]" size="0 0 100% 32" hidden="true"> 82 92 <object name="playerColour[n]" type="image" size="0 0 100% 100%"/> 83 93 <object name="playerName[n]" type="text" style="CenteredLabelText" size="0 2 25% 30"/> 84 <object name="playerAssignment[n]" type="dropdown" style="StoneDropDown" size="25%+5 2 55% 30" tooltip_style="onscreenToolTip" tooltip="Select player."/> 94 <object name="playerAssignment[n]" type="dropdown" style="StoneDropDown" size="25%+5 2 55% 30" tooltip_style="onscreenToolTip"> 95 <translatableAttribute id="tooltip">Select player.</translatableAttribute> 96 </object> 85 97 <object name="playerConfig[n]" type="button" style="StoneButton" size="55%+5 6 55%+60 26" 86 98 tooltip_style="onscreenToolTip" 87 tooltip="Configure AI settings."88 99 font="serif-bold-stroke-12" 89 >Settings</object> 90 <object name="playerCiv[n]" type="dropdown" style="StoneDropDown" size="55%+65 2 85% 30" tooltip_style="onscreenToolTip" tooltip="Select player's civilization."/> 100 > 101 <translatableAttribute id="caption">Settings</translatableAttribute> 102 <translatableAttribute id="tooltip">Configure AI settings.</translatableAttribute> 103 </object> 104 <object name="playerCiv[n]" type="dropdown" style="StoneDropDown" size="55%+65 2 85% 30" tooltip_style="onscreenToolTip"> 105 <translatableAttribute id="tooltip">Select player's civilization.</translatableAttribute> 106 </object> 91 107 <object name="playerCivText[n]" type="text" style="CenteredLabelText" size="55%+65 0 85% 30"/> 92 <object name="playerTeam[n]" type="dropdown" style="StoneDropDown" size="85%+5 2 100%-5 30" tooltip_style="onscreenToolTip" tooltip="Select player's team."/> 108 <object name="playerTeam[n]" type="dropdown" style="StoneDropDown" size="85%+5 2 100%-5 30" tooltip_style="onscreenToolTip"> 109 <translatableAttribute id="tooltip">Select player's team.</translatableAttribute> 110 </object> 93 111 <object name="playerTeamText[n]" type="text" style="CenteredLabelText" size="85%+5 0 100%-5 100%"/> 94 112 </object> 95 113 </repeat> … … 100 118 101 119 102 120 <object size="100%-425 363 100%-325 455" name="mapTypeSelectionTooltip"> 103 <object type="text" style="RightLabelText" size="0 0 100% 30">Match Type:</object> 104 <object type="text" style="RightLabelText" size="0 32 100% 62">Map Filter:</object> 105 <object type="text" style="RightLabelText" size="0 64 100% 94">Select Map:</object> 106 <object type="text" style="RightLabelText" size="0 96 100% 126">Map Size:</object> 121 <object type="text" style="RightLabelText" size="0 0 100% 30"> 122 <translatableAttribute id="caption">Match Type:</translatableAttribute> 123 </object> 124 <object type="text" style="RightLabelText" size="0 32 100% 62"> 125 <translatableAttribute id="caption">Map Filter:</translatableAttribute> 126 </object> 127 <object type="text" style="RightLabelText" size="0 64 100% 94"> 128 <translatableAttribute id="caption">Select Map:</translatableAttribute> 129 </object> 130 <object type="text" style="RightLabelText" size="0 96 100% 126"> 131 <translatableAttribute id="caption">Map Size:</translatableAttribute> 132 </object> 107 133 </object> 108 134 109 135 <object size="100%-327 363 100%-25 423" name="mapFilterSelectionTooltip"> … … 117 143 type="dropdown" 118 144 style="StoneDropDown" 119 145 size="100%-325 363 100%-25 391" 120 tooltip_style="onscreenToolTip" 121 tooltip="Select a map type.">146 tooltip_style="onscreenToolTip"> 147 <translatableAttribute id="tooltip">Select a map type.</translatableAttribute> 122 148 <action on="SelectionChange">selectMapType(this.list_data[this.selected]);</action> 123 149 </object> 124 150 … … 126 152 type="dropdown" 127 153 style="StoneDropDown" 128 154 size="100%-325 395 100%-25 423" 129 tooltip_style="onscreenToolTip" 130 tooltip="Select a map filter.">131 <action on="SelectionChange">selectMapFilter(this.list [this.selected]);</action>155 tooltip_style="onscreenToolTip"> 156 <translatableAttribute id="tooltip">Select a map filter.</translatableAttribute> 157 <action on="SelectionChange">selectMapFilter(this.list_data[this.selected]);</action> 132 158 </object> 133 159 134 160 <object size="100%-325 427 100%-25 455" name="mapSelectionPannel" z="55"> … … 137 163 style="StoneDropDown" 138 164 type="dropdown" 139 165 size="0 0 100% 100%" 140 tooltip_style="onscreenToolTip" 141 tooltip="Select a map to play on.">166 tooltip_style="onscreenToolTip"> 167 <translatableAttribute id="tooltip">Select a map to play on.</translatableAttribute> 142 168 <action on="SelectionChange">selectMap(this.list_data[this.selected]);</action> 143 169 </object> 144 170 145 171 </object> 146 172 147 <object name="mapSize" size="100%-325 459 100%-25 487" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip" tooltip="Select map size. (Larger sizes may reduce performance.)"/> 173 <object name="mapSize" size="100%-325 459 100%-25 487" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip"> 174 <translatableAttribute id="tooltip">Select map size. (Larger sizes may reduce performance.)</translatableAttribute> 175 </object> 148 176 149 177 <!-- Map Preview --> 150 178 <object type="image" sprite="BackgroundIndentFillDark" name="gamePreviewBox" size="100%-426 57 100%-24 359"> … … 168 196 style="StoneButton" 169 197 size="100%-120 0 100% 28" 170 198 tooltip_style="onscreenToolTip" 171 tooltip="See more game options"172 199 > 173 More Options 200 <translatableAttribute id="caption">More Options</translatableAttribute> 201 <translatableAttribute id="tooltip">See more game options</translatableAttribute> 174 202 <action on="Press">toggleMoreOptions();</action> 175 203 </object> 176 204 … … 180 208 <!-- More Options --> 181 209 <object name="moreOptions" type="image" sprite="StoneWindow" size="50%-200 50%-150 50%+200 50%+155" z="70" hidden="true"> 182 210 <object style="TitleText" type="text" size="50%-128 11 50%+128 27"> 183 More Options211 <translatableAttribute id="caption">More Options</translatableAttribute> 184 212 </object> 185 213 186 214 <object size="14 38 94% 66"> 187 215 <object size="0 0 40% 28"> 188 <object size="0 0 100% 100%" type="text" style="RightLabelText">Game Speed:</object> 216 <object size="0 0 100% 100%" type="text" style="RightLabelText"> 217 <translatableAttribute id="caption">Game Speed:</translatableAttribute> 218 </object> 189 219 </object> 190 220 <object name="gameSpeedText" size="40% 0 100% 100%" type="text" style="LeftLabelText"/> 191 <object name="gameSpeed" size="40% 0 100% 28" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip" tooltip="Select game speed."/> 221 <object name="gameSpeed" size="40% 0 100% 28" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip"> 222 <translatableAttribute id="tooltip">Select game speed.</translatableAttribute> 223 </object> 192 224 </object> 193 225 194 226 <object size="14 68 94% 96"> 195 227 <object size="0 0 40% 28"> 196 <object size="0 0 100% 100%" type="text" style="RightLabelText">Victory Condition:</object> 228 <object size="0 0 100% 100%" type="text" style="RightLabelText"> 229 <translatableAttribute id="caption">Victory Condition:</translatableAttribute> 230 </object> 197 231 </object> 198 232 <object name="victoryConditionText" size="40% 0 100% 100%" type="text" style="LeftLabelText"/> 199 <object name="victoryCondition" size="40% 0 100% 28" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip" tooltip="Select victory condition."/> 233 <object name="victoryCondition" size="40% 0 100% 28" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip"> 234 <translatableAttribute id="tooltip">Select victory condition.</translatableAttribute> 235 </object> 200 236 </object> 201 237 202 238 <object size="14 98 94% 126"> 203 239 <object size="0 0 40% 28"> 204 <object size="0 0 100% 100%" type="text" style="RightLabelText">Population Cap:</object> 240 <object size="0 0 100% 100%" type="text" style="RightLabelText"> 241 <translatableAttribute id="caption">Population Cap:</translatableAttribute> 242 </object> 205 243 </object> 206 244 <object name="populationCapText" size="40% 0 100% 100%" type="text" style="LeftLabelText"/> 207 <object name="populationCap" size="40% 0 100% 28" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip" tooltip="Select population cap."/> 245 <object name="populationCap" size="40% 0 100% 28" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip"> 246 <translatableAttribute id="tooltip">Select population cap.</translatableAttribute> 247 </object> 208 248 </object> 209 249 210 250 <object size="14 128 94% 156"> 211 251 <object size="0 0 40% 28"> 212 <object size="0 0 100% 100%" type="text" style="RightLabelText">Starting Resources:</object> 252 <object size="0 0 100% 100%" type="text" style="RightLabelText"> 253 <translatableAttribute id="caption">Starting Resources:</translatableAttribute> 254 </object> 213 255 </object> 214 256 <object name="startingResourcesText" size="40% 0 100% 100%" type="text" style="LeftLabelText"/> 215 <object name="startingResources" size="40% 0 100% 28" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip" tooltip="Select the game's starting resources."/> 257 <object name="startingResources" size="40% 0 100% 28" type="dropdown" style="StoneDropDown" hidden="true" tooltip_style="onscreenToolTip"> 258 <translatableAttribute id="tooltip">Select the game's starting resources.</translatableAttribute> 259 </object> 216 260 </object> 217 261 218 262 <object size="14 158 94% 246"> 219 263 <object size="0 0 40% 28"> 220 <object size="0 0 100% 100%" type="text" style="RightLabelText">Reveal Map:</object> 264 <object size="0 0 100% 100%" type="text" style="RightLabelText"> 265 <translatableAttribute id="caption">Reveal Map:</translatableAttribute> 266 </object> 221 267 </object> 222 268 <object size="0 30 40% 58"> 223 <object size="0 0 100% 100%" type="text" style="RightLabelText">Teams Locked:</object> 269 <object size="0 0 100% 100%" type="text" style="RightLabelText"> 270 <translatableAttribute id="caption">Teams Locked:</translatableAttribute> 271 </object> 224 272 </object> 225 273 <object size="0 60 40% 88" name="enableCheatsDesc" hidden="true"> 226 <object size="0 0 100% 100%" type="text" style="RightLabelText">Cheats:</object> 274 <object size="0 0 100% 100%" type="text" style="RightLabelText"> 275 <translatableAttribute id="caption">Cheats:</translatableAttribute> 276 </object> 227 277 </object> 228 278 229 279 <object size="40% 0 100% 28"> 230 280 <object name="revealMapText" size="0 0 100% 100%" type="text" style="LeftLabelText"/> 231 <object name="revealMap" size="4 50%-8 20 50%+8" type="checkbox" style="StoneCrossBox" hidden="true" tooltip_style="onscreenToolTip" tooltip="Toggle reveal map."/> 281 <object name="revealMap" size="4 50%-8 20 50%+8" type="checkbox" style="StoneCrossBox" hidden="true" tooltip_style="onscreenToolTip"> 282 <translatableAttribute id="tooltip">Toggle reveal map.</translatableAttribute> 283 </object> 232 284 </object> 233 285 <object size="40% 30 100% 58"> 234 286 <object name="lockTeamsText" size="0 0 100% 100%" type="text" style="LeftLabelText"/> 235 <object name="lockTeams" size="4 50%-8 20 50%+8" type="checkbox" style="StoneCrossBox" hidden="true" tooltip_style="onscreenToolTip" tooltip="Toggle locked teams."/> 287 <object name="lockTeams" size="4 50%-8 20 50%+8" type="checkbox" style="StoneCrossBox" hidden="true" tooltip_style="onscreenToolTip"> 288 <translatableAttribute id="tooltip">Toggle locked teams.</translatableAttribute> 289 </object> 236 290 </object> 237 291 <object size="40% 60 100% 88"> 238 292 <object name="enableCheatsText" size="0 0 100% 100%" type="text" style="LeftLabelText" hidden="true"/> 239 <object name="enableCheats" size="4 50%-8 20 50%+8" type="checkbox" style="StoneCrossBox" hidden="true" tooltip_style="onscreenToolTip" tooltip="Toggle the usability of cheats."/> 293 <object name="enableCheats" size="4 50%-8 20 50%+8" type="checkbox" style="StoneCrossBox" hidden="true" tooltip_style="onscreenToolTip"> 294 <translatableAttribute id="tooltip">Toggle the usability of cheats.</translatableAttribute> 295 </object> 240 296 </object> 241 297 </object> 242 298 … … 247 303 style="StoneButton" 248 304 size="50%-70 248 50%+70 274" 249 305 tooltip_style="onscreenToolTip" 250 tooltip="Close more game options window"251 306 > 252 OK 307 <translatableAttribute id="caption">OK</translatableAttribute> 308 <translatableAttribute id="tooltip">Close more game options window</translatableAttribute> 253 309 <action on="Press">toggleMoreOptions();</action> 254 310 </object> 255 311 <!-- End More Options --> … … 279 335 sprite="BackgroundTranslucent" 280 336 hidden="true" 281 337 size="100%-700 100%-56 100%-312 100%-24" 282 >[Tooltip text]</object> 338 > 339 <translatableAttribute id="caption">[Tooltip text]</translatableAttribute> 340 </object> 283 341 284 342 <!-- Start Button --> 285 343 <object … … 288 346 style="StoneButton" 289 347 size="100%-308 100%-52 100%-168 100%-24" 290 348 tooltip_style="onscreenToolTip" 291 tooltip="Start a new game with the current settings."292 349 enabled="false" 293 350 > 294 Start game! 351 <translatableAttribute id="caption">Start game!</translatableAttribute> 352 <translatableAttribute id="tooltip">Start a new game with the current settings.</translatableAttribute> 295 353 <action on="Press">launchGame();</action> 296 354 </object> 297 355 … … 302 360 style="StoneButton" 303 361 size="100%-164 100%-52 100%-24 100%-24" 304 362 tooltip_style="onscreenToolTip" 305 tooltip="Return to the main menu."306 363 > 307 Main menu 364 <translatableAttribute id="caption">Main menu</translatableAttribute> 365 <translatableAttribute id="tooltip">Return to the main menu.</translatableAttribute> 308 366 <action on="Press"> 309 367 <![CDATA[ 310 368 cancelSetup(); … … 314 372 </object> 315 373 316 374 </object> 317 375 318 376 </object> 319 377 320 378 </objects> -
binaries/data/mods/public/gui/gamesetup/gamesetup_mp.js
diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup_mp.js b/binaries/data/mods/public/gui/gamesetup/gamesetup_mp.js index a27c993..5615a65 100644
a b function init(multiplayerGameType) 18 18 getGUIObjectByName("pageHost").hidden = false; 19 19 break; 20 20 default: 21 error( "Unrecognised multiplayer game type : " + multiplayerGameType);21 error(sprintf(translate("Unrecognised multiplayer game type: %(gameType)s"), { gameType: multiplayerGameType })); 22 22 break; 23 23 } 24 24 } … … function startConnectionStatus(type) 35 35 g_GameType = type; 36 36 g_IsConnecting = true; 37 37 g_IsRejoining = false; 38 getGUIObjectByName("connectionStatus").caption = "Connecting to server...";38 getGUIObjectByName("connectionStatus").caption = translate("Connecting to server..."); 39 39 } 40 40 41 41 function onTick() … … function onTick() 49 49 if (!message) 50 50 break; 51 51 52 log( "Net message: "+uneval(message));52 log(sprintf(translate("Net message: %(message)s"), { message: uneval(message) })); 53 53 54 54 // If we're rejoining an active game, we don't want to actually display 55 55 // the game setup screen, so perform similar processing to gamesetup.js … … function onTick() 67 67 return; 68 68 69 69 default: 70 error( "Unrecognised netstatus type "+message.status);70 error(sprintf(translate("Unrecognised netstatus type %(netType)s"), { netType: message.status })); 71 71 break; 72 72 } 73 73 break; … … function onTick() 93 93 break; 94 94 95 95 default: 96 error( "Unrecognised net message type "+message.type);96 error(sprintf(translate("Unrecognised net message type %(messageType)s"), { messageType: message.type })); 97 97 } 98 98 } 99 99 else … … function onTick() 106 106 switch (message.status) 107 107 { 108 108 case "connected": 109 getGUIObjectByName("connectionStatus").caption = "Registering with server...";109 getGUIObjectByName("connectionStatus").caption = translate("Registering with server..."); 110 110 break; 111 111 112 112 case "authenticated": 113 113 if (message.rejoining) 114 114 { 115 getGUIObjectByName("connectionStatus").caption = "Game has already started - rejoining...";115 getGUIObjectByName("connectionStatus").caption = translate("Game has already started, rejoining..."); 116 116 g_IsRejoining = true; 117 117 return; // we'll process the game setup messages in the next tick 118 118 } … … function onTick() 128 128 return; 129 129 130 130 default: 131 error( "Unrecognised netstatus type "+message.status);131 error(sprintf(translate("Unrecognised netstatus type %(netType)s"), { netType: message.status })); 132 132 break; 133 133 } 134 134 break; 135 135 default: 136 error( "Unrecognised net message type "+message.type);136 error(sprintf(translate("Unrecognised net message type %(messageType)s"), { messageType: message.type })); 137 137 break; 138 138 } 139 139 } … … function startHost(playername, servername) 156 156 { 157 157 cancelSetup(); 158 158 messageBox(400, 200, 159 "Cannot host game: " + e.message + ".",160 "Error", 2);159 sprintf(translate("Cannot host game: %(message)s."), { message: e.message }), 160 translate("Error"), 2); 161 161 return false; 162 162 } 163 163 … … function startJoin(playername, ip) 177 177 { 178 178 cancelSetup(); 179 179 messageBox(400, 200, 180 "Cannot join game: " + e.message + ".",181 "Error", 2);180 sprintf(translate("Cannot join game: %(message)s."), { message: e.message }), 181 translate("Error"), 2); 182 182 return false; 183 183 } 184 184 -
binaries/data/mods/public/gui/gamesetup/gamesetup_mp.xml
diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup_mp.xml b/binaries/data/mods/public/gui/gamesetup/gamesetup_mp.xml index c8b4be8..13af6a6 100644
a b 16 16 </action> 17 17 18 18 <object style="TitleText" type="text" size="50%-128 0%-16 50%+128 16"> 19 Multiplayer19 <translatableAttribute id="caption">Multiplayer</translatableAttribute> 20 20 </object> 21 21 22 22 <object name="pageJoin" size="0 32 100% 100%" hidden="true"> 23 23 24 24 <object type="text" style="CenteredLabelText" size="0 0 400 30"> 25 Joining an existing game.25 <translatableAttribute id="caption">Joining an existing game.</translatableAttribute> 26 26 </object> 27 27 28 28 <object type="text" size="0 40 200 70" style="RightLabelText"> 29 Player name:29 <translatableAttribute id="caption">Player name:</translatableAttribute> 30 30 </object> 31 31 32 32 <object name="joinPlayerName" type="input" size="210 40 100%-32 64" style="StoneInput"> … … 36 36 </object> 37 37 38 38 <object type="text" size="0 80 200 110" style="RightLabelText"> 39 Server Hostname or IP:39 <translatableAttribute id="caption">Server Hostname or IP:</translatableAttribute> 40 40 </object> 41 41 42 42 <object name="joinServer" type="input" size="210 80 100%-32 104" style="StoneInput"> … … 46 46 </object>3 100%-33 103 100%-3 47 47 48 48 <object hotkey="confirm" type="button" size="50%-144 100%-60 50%-16 100%-32" style="StoneButton"> 49 Continue49 <translatableAttribute id="caption">Continue</translatableAttribute> 50 50 <action on="Press"> 51 51 var joinPlayerName = getGUIObjectByName("joinPlayerName").caption; 52 52 var joinServer = getGUIObjectByName("joinServer").caption; … … 62 62 <object name="pageHost" size="0 32 100% 100%" hidden="true"> 63 63 64 64 <object type="text" style="CenteredLabelText" size="0 0 400 30"> 65 Set up your server to host.65 <translatableAttribute id="caption">Set up your server to host.</translatableAttribute> 66 66 </object> 67 67 68 68 <object type="text" size="0 40 200 70" style="RightLabelText"> 69 Player name:69 <translatableAttribute id="caption">Player name:</translatableAttribute> 70 70 </object> 71 71 72 72 <object name="hostPlayerName" type="input" size="210 40 100%-32 64" style="StoneInput"> … … 77 77 78 78 <object hidden="true"> <!-- TODO: restore this when the server name is actually used --> 79 79 <object type="text" size="0 80 200 110" style="RightLabelText"> 80 Server name:80 <translatableAttribute id="caption">Server name:</translatableAttribute> 81 81 </object> 82 82 83 83 <object name="hostServerName" type="input" size="210 80 100%-32 104" style="StoneInput"> … … 88 88 </object> 89 89 90 90 <object type="button" size="50%-144 100%-60 50%-16 100%-32" style="StoneButton"> 91 Continue91 <translatableAttribute id="caption">Continue</translatableAttribute> 92 92 <action on="Press"> 93 93 var hostPlayerName = getGUIObjectByName("hostPlayerName").caption; 94 94 Engine.SaveMPConfig(hostPlayerName, Engine.GetDefaultMPServer()); … … 103 103 </object> 104 104 105 105 <object type="button" style="StoneButton" size="50%+16 100%-60 50%+144 100%-32"> 106 Cancel106 <translatableAttribute id="caption">Cancel</translatableAttribute> 107 107 <action on="Press">cancelSetup();</action> 108 108 </object> 109 109 110 110 <object name="pageConnecting" hidden="true"> 111 111 <object name="connectionStatus" type="text" style="CenteredLabelText" size="0 100 100% 120"> 112 [Connection status]112 <translatableAttribute id="caption">[Connection status]</translatableAttribute> 113 113 </object> 114 114 </object> 115 115 -
binaries/data/mods/public/gui/loading/loading.js
diff --git a/binaries/data/mods/public/gui/loading/loading.js b/binaries/data/mods/public/gui/loading/loading.js index 182d86c..5a2649f 100644
a b function init(data) 15 15 { 16 16 // Set tip text 17 17 var tipTextFilePath = tipTextLoadingArray[getRandom (0, tipTextLoadingArray.length-1)]; 18 var tipText = readFile(tipTextFilePath);18 var tipText = Engine.translateLines(readFile(tipTextFilePath)); 19 19 20 20 if (tipText) 21 21 { … … function init(data) 34 34 } 35 35 else 36 36 { 37 error( "Failed to find any matching tips for the loading screen.")37 error(translate("Failed to find any matching tips for the loading screen.")) 38 38 } 39 39 40 40 // janwas: main loop now sets progress / description, but that won't … … function init(data) 48 48 { 49 49 case "skirmish": 50 50 case "scenario": 51 loadingMapName.caption = "Loading \"" + mapName + "\"";51 loadingMapName.caption = sprintf(translate("Loading \"%(map)s\""), {map: mapName}); 52 52 break; 53 53 54 54 case "random": 55 loadingMapName.caption = "Generating \"" + mapName + "\"";55 loadingMapName.caption = sprintf(translate("Generating \"%(map)s\""), {map: mapName}); 56 56 break; 57 57 58 58 default: 59 error( "Unknown map type: " + data.attribs.mapType);59 error(sprintf(translate("Unknown map type: %(mapType)s"), { mapType: data.attribs.mapType })); 60 60 } 61 61 } 62 62 … … function init(data) 65 65 66 66 // Pick a random quote of the day (each line is a separate tip). 67 67 var quoteArray = readFileLines("gui/text/quotes.txt"); 68 getGUIObjectByName("quoteText").caption = quoteArray[getRandom(0, quoteArray.length-1)];68 getGUIObjectByName("quoteText").caption = translate(quoteArray[getRandom(0, quoteArray.length-1)]); 69 69 } 70 70 71 71 // ==================================================================== -
binaries/data/mods/public/gui/loading/loading.xml
diff --git a/binaries/data/mods/public/gui/loading/loading.xml b/binaries/data/mods/public/gui/loading/loading.xml index 7ad8c38..d7b9a49 100644
a b 44 44 45 45 <!-- LOADING SCREEN QUOTE (needs increased z value to overcome the transparent area of the tip image above it --> 46 46 <object size="50%-448 50%+230 50%+448 100%-16" z="20"> 47 <object name="quoteTitleText" size="0 0 100% 30" type="text" style="LoadingTitleText">Quote of the Day:</object> 47 <object name="quoteTitleText" size="0 0 100% 30" type="text" style="LoadingTitleText"> 48 <translatableAttribute id="caption">Quote of the Day:</translatableAttribute> 49 </object> 48 50 <object name="quoteText" size="0 30 100% 100%" type="text" style="LoadingText"></object> 49 51 </object> 50 52 </object> -
new file inaries/data/mods/public/gui/locale/locale.js
diff --git a/binaries/data/mods/public/gui/locale/locale.js b/binaries/data/mods/public/gui/locale/locale.js new file mode 100644 index 0000000..1aa587f
- + 1 function init() 2 { 3 var languageList = getGUIObjectByName("languageList"); 4 languageList.list = Engine.GetSupportedLocaleDisplayNames(); 5 languageList.list_data = Engine.GetSupportedLocaleCodes(); 6 languageList.selected = Engine.GetCurrentLocaleIndex(); 7 } 8 9 function cancelSetup() 10 { 11 Engine.PopGuiPage(); 12 } 13 14 function applySelectedLocale() 15 { 16 var languageList = getGUIObjectByName("languageList"); 17 Engine.SetLocale(languageList.list_data[languageList.selected]); 18 Engine.SwitchGuiPage("page_pregame.xml"); 19 } -
new file inaries/data/mods/public/gui/locale/locale.xml
diff --git a/binaries/data/mods/public/gui/locale/locale.xml b/binaries/data/mods/public/gui/locale/locale.xml new file mode 100644 index 0000000..f83fdff
- + 1 <?xml version="1.0" encoding="utf-8"?> 2 3 <objects> 4 5 <script file="gui/common/functions_global_object.js"/> 6 <script file="gui/locale/locale.js"/> 7 8 <!-- Add a translucent black background to fade out the menu page --> 9 <object type="image" z="0" sprite="bkTranslucent"/> 10 11 <object type="image" style="StoneDialog" size="50%-190 50%-100 50%+190 50%+100"> 12 13 <object style="TitleText" type="text" size="50%-128 0%-16 50%+128 16"> 14 <translatableAttribute id="caption">Language</translatableAttribute> 15 </object> 16 17 <object size="0 32 100% 100%"> 18 <object type="text" size="0 0 140 30" style="RightLabelText"> 19 <translatableAttribute id="caption">Language:</translatableAttribute> 20 </object> 21 22 <object name="languageList" 23 type="dropdown" 24 style="StoneDropDown" 25 size="150 0 100%-32 28"> 26 </object> 27 28 <object type="text" size="30 40 100%-30 100" style="LeftLabelText"> 29 <translatableAttribute id="caption">Note: Restart the game for these changes to take effect.</translatableAttribute> 30 </object> 31 32 <object type="button" size="50%-154 100%-60 50%+10 100%-32" style="StoneButton"> 33 <translatableAttribute id="caption">Accept</translatableAttribute> 34 <action on="Press">applySelectedLocale();</action> 35 </object> 36 </object> 37 38 <object type="button" style="StoneButton" size="50%+26 100%-60 50%+154 100%-32"> 39 <translatableAttribute id="caption">Cancel</translatableAttribute> 40 <action on="Press">cancelSetup();</action> 41 </object> 42 43 </object> 44 45 </objects> -
binaries/data/mods/public/gui/manual/manual.js
diff --git a/binaries/data/mods/public/gui/manual/manual.js b/binaries/data/mods/public/gui/manual/manual.js index 0d6ad6e..191d966 100644
a b var closeCallback; 2 2 3 3 function init(data) 4 4 { 5 getGUIObjectByName("mainText").caption = readFile("gui/manual/" + data.page + ".txt");5 getGUIObjectByName("mainText").caption = Engine.translateLines(readFile("gui/manual/" + data.page + ".txt")); 6 6 closeCallback = data.closeCallback; 7 7 } 8 8 -
binaries/data/mods/public/gui/manual/manual.xml
diff --git a/binaries/data/mods/public/gui/manual/manual.xml b/binaries/data/mods/public/gui/manual/manual.xml index eff09d8..1c7fe52 100644
a b 8 8 <object type="image" z="0" style="TranslucentPanel"/> 9 9 10 10 <object type="image" style="StoneDialog" size="50%-466 50%-316 50%+466 50%+316"> 11 <object type="text" style="TitleText" size="50%-128 0%-16 50%+128 16">Manual</object> 11 <object type="text" style="TitleText" size="50%-128 0%-16 50%+128 16"> 12 <translatableAttribute id="caption">Manual</translatableAttribute> 13 </object> 12 14 13 15 <object type="image" sprite="BackgroundTranslucent" size="20 20 100%-20 100%-58"> 14 16 <object name="mainText" type="text" style="textPanel"/> 15 17 </object> 16 <object type="button" style="StoneButton" size="100%-308 100%-52 100%-168 100%-24"> 17 Online Manual 18 19 <object type="button" style="StoneButton" size="100%-308 100%-52 100%-168 100%-24"> 20 <translatableAttribute id="caption">Online Manual</translatableAttribute> 18 21 <action on="Press"><![CDATA[ 19 22 var url = "http://trac.wildfiregames.com/wiki/0adManual"; 20 23 Engine.OpenURL(url); 21 24 messageBox(450, 200, "Opening "+url+"\n in default web browser. Please wait...", "Opening page", 2); 22 25 ]]></action> 23 26 </object> 24 27 <object type="button" style="StoneButton" tooltip_style="snToolTip" size="100%-164 100%-52 100%-24 100%-24"> 25 Close28 <translatableAttribute id="caption">Close</translatableAttribute> 26 29 <action on="Press"><![CDATA[closeManual();]]></action> 27 30 </object> 28 31 </object> -
new file inaries/data/mods/public/gui/msgbox/msgbox.js
diff --git a/binaries/data/mods/public/gui/msgbox/msgbox.js b/binaries/data/mods/public/gui/msgbox/msgbox.js new file mode 100644 index 0000000..954cab4
- + 1 function init(data) 2 { 3 var mbMainObj = getGUIObjectByName("mbMain"); 4 var mbTitleObj = getGUIObjectByName("mbTitleBar"); 5 var mbTextObj = getGUIObjectByName("mbText"); 6 7 var mbButton1Obj = getGUIObjectByName("mbButton1"); 8 var mbButton2Obj = getGUIObjectByName("mbButton2"); 9 var mbButton3Obj = getGUIObjectByName("mbButton3"); 10 11 // Calculate size 12 var mbLRDiff = data.width / 2; // Message box left/right difference from 50% of screen 13 var mbUDDiff = data.height / 2; // Message box up/down difference from 50% of screen 14 15 var mbSizeString = "50%-" + mbLRDiff + " 50%-" + mbUDDiff + " 50%+" + mbLRDiff + " 50%+" + mbUDDiff; 16 17 mbMainObj.size = mbSizeString; 18 19 // Texts 20 mbTitleObj.caption = data.title; 21 mbTextObj.caption = data.message; 22 23 if (data.font) 24 mbTextObj.font = data.font; 25 26 // Message box modes 27 // There is a number of standard modes, and if none of these is used (mbMode == 0), the button captions will be 28 // taken from the array mbButtonCaptions; there currently is a maximum of three buttons. 29 switch (data.mode) 30 { 31 case 1: 32 // Simple Yes/No question box 33 data.buttonCaptions = [translate("Yes"), translate("No")]; 34 break; 35 case 2: 36 // Okay-only box 37 data.buttonCaptions = [translate("OK")]; 38 break; 39 case 3: 40 // Retry/Abort/Ignore box (will we ever need this?!) 41 data.buttonCaptions = [translate("Retry"), translate("Ignore"), translate("Abort")]; 42 default: 43 break; 44 } 45 46 // Buttons 47 var codes = data.buttonCode; 48 if (data.buttonCaptions.length >= 1) 49 { 50 mbButton1Obj.caption = data.buttonCaptions[0]; 51 mbButton1Obj.onPress = function () { Engine.PopGuiPage(); if (codes && codes[0]) codes[0](); } 52 mbButton1Obj.hidden = false; 53 } 54 if (data.buttonCaptions.length >= 2) 55 { 56 mbButton2Obj.caption = data.buttonCaptions[1]; 57 mbButton2Obj.onPress = function () { Engine.PopGuiPage(); if (codes && codes[1]) codes[1](); } 58 mbButton2Obj.hidden = false; 59 } 60 if (data.buttonCaptions.length >= 3) 61 { 62 mbButton3Obj.caption = data.buttonCaptions[2]; 63 mbButton3Obj.onPress = function () { Engine.PopGuiPage(); if (codes && codes[2]) codes[2](); } 64 mbButton3Obj.hidden = false; 65 } 66 67 switch (data.buttonCaptions.length) 68 { 69 case 1: 70 mbButton1Obj.size = "50%-64 100%-76 50%+64 100%-48"; 71 break; 72 case 2: 73 mbButton1Obj.size = "50%-144 100%-76 50%-16 100%-48"; 74 mbButton2Obj.size = "50%+16 100%-76 50%+144 100%-48"; 75 break; 76 case 3: 77 mbButton1Obj.size = "10% 100%-76 30% 100%-48"; 78 mbButton2Obj.size = "40% 100%-76 60% 100%-48"; 79 mbButton3Obj.size = "70% 100%-76 90% 100%-48"; 80 break; 81 } 82 } -
binaries/data/mods/public/gui/msgbox/msgbox.xml
diff --git a/binaries/data/mods/public/gui/msgbox/msgbox.xml b/binaries/data/mods/public/gui/msgbox/msgbox.xml index 9e05a0a..508de2d 100644
a b 1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 3 3 <objects> 4 <script><![CDATA[ 5 function init(data) 6 { 7 var mbMainObj = getGUIObjectByName("mbMain"); 8 var mbTitleObj = getGUIObjectByName("mbTitleBar"); 9 var mbTextObj = getGUIObjectByName("mbText"); 10 11 var mbButton1Obj = getGUIObjectByName("mbButton1"); 12 var mbButton2Obj = getGUIObjectByName("mbButton2"); 13 var mbButton3Obj = getGUIObjectByName("mbButton3"); 14 15 // Calculate size 16 var mbLRDiff = data.width / 2; // Message box left/right difference from 50% of screen 17 var mbUDDiff = data.height / 2; // Message box up/down difference from 50% of screen 18 19 var mbSizeString = "50%-" + mbLRDiff + " 50%-" + mbUDDiff + " 50%+" + mbLRDiff + " 50%+" + mbUDDiff; 20 21 mbMainObj.size = mbSizeString; 22 23 // Texts 24 mbTitleObj.caption = data.title; 25 mbTextObj.caption = data.message; 26 27 if (data.font) 28 mbTextObj.font = data.font; 29 30 // Message box modes 31 // There is a number of standard modes, and if none of these is used (mbMode == 0), the button captions will be 32 // taken from the array mbButtonCaptions; there currently is a maximum of three buttons. 33 switch (data.mode) 34 { 35 case 1: 36 // Simple Yes/No question box 37 data.buttonCaptions = ["Yes", "No"]; 38 break; 39 case 2: 40 // Okay-only box 41 data.buttonCaptions = ["OK"]; 42 break; 43 case 3: 44 // Retry/Abort/Ignore box (will we ever need this?!) 45 data.buttonCaptions = ["Retry", "Ignore", "Abort"]; 46 default: 47 break; 48 } 49 50 // Buttons 51 var codes = data.buttonCode; 52 if (data.buttonCaptions.length >= 1) 53 { 54 mbButton1Obj.caption = data.buttonCaptions[0]; 55 mbButton1Obj.onPress = function () { Engine.PopGuiPage(); if (codes && codes[0]) codes[0](); } 56 mbButton1Obj.hidden = false; 57 } 58 if (data.buttonCaptions.length >= 2) 59 { 60 mbButton2Obj.caption = data.buttonCaptions[1]; 61 mbButton2Obj.onPress = function () { Engine.PopGuiPage(); if (codes && codes[1]) codes[1](); } 62 mbButton2Obj.hidden = false; 63 } 64 if (data.buttonCaptions.length >= 3) 65 { 66 mbButton3Obj.caption = data.buttonCaptions[2]; 67 mbButton3Obj.onPress = function () { Engine.PopGuiPage(); if (codes && codes[2]) codes[2](); } 68 mbButton3Obj.hidden = false; 69 } 70 71 switch (data.buttonCaptions.length) 72 { 73 case 1: 74 mbButton1Obj.size = "50%-64 100%-76 50%+64 100%-48"; 75 break; 76 case 2: 77 mbButton1Obj.size = "50%-144 100%-76 50%-16 100%-48"; 78 mbButton2Obj.size = "50%+16 100%-76 50%+144 100%-48"; 79 break; 80 case 3: 81 mbButton1Obj.size = "10% 100%-76 30% 100%-48"; 82 mbButton2Obj.size = "40% 100%-76 60% 100%-48"; 83 mbButton3Obj.size = "70% 100%-76 90% 100%-48"; 84 break; 85 } 86 } 87 ]]></script> 4 <script file="gui/msgbox/msgbox.js"/> 88 5 89 6 <object hotkey="leave"> 90 7 <action on="Press">Engine.PopGuiPage();</action> -
binaries/data/mods/public/gui/options/options.xml
diff --git a/binaries/data/mods/public/gui/options/options.xml b/binaries/data/mods/public/gui/options/options.xml index 6870c15..3650bef 100644
a b 13 13 <script file="gui/session/music.js"/> 14 14 <script file="gui/options/options.js"/> 15 15 16 16 <!-- Add a translucent black background to fade out the menu page --> 17 17 <object type="image" z="0" style="TranslucentPanel"/> 18 19 18 19 <!-- Settings Window --> 20 20 <object name="options" type="image" style="StonePanelLight" size="50%-190 50%-120 50%+190 50%+120"> 21 21 22 23 Game Options22 <object style="StoneDialogTitleBar" type="text" size="50%-128 0%-16 50%+128 16"> 23 <translatableAttribute id="caption">Game Options</translatableAttribute> 24 24 </object> 25 25 26 <object size="50%-190 50%-80 50%+140 50%+95"> 27 28 <!-- Settings / shadows --> 29 <object size="0 10 100%-80 35" type="text" style="RightLabelText" ghost="true">Enable Shadows</object> 30 <object name="shadowsCheckbox" size="100%-56 15 100%-30 40" type="checkbox" style="StoneCrossBox" checked="true"> 31 <action on="Load">this.checked = Engine.Renderer_GetShadowsEnabled();</action> 32 <action on="Press">Engine.Renderer_SetShadowsEnabled(this.checked);</action> 33 </object> 26 <object size="50%-190 50%-80 50%+140 50%+95"> 27 28 <!-- Settings / shadows --> 29 <object size="0 10 100%-80 35" type="text" style="RightLabelText" ghost="true"> 30 <translatableAttribute id="caption">Enable Shadows</translatableAttribute> 31 </object> 32 <object name="shadowsCheckbox" size="100%-56 15 100%-30 40" type="checkbox" style="StoneCrossBox" checked="true"> 33 <action on="Load">this.checked = Engine.Renderer_GetShadowsEnabled();</action> 34 <action on="Press">Engine.Renderer_SetShadowsEnabled(this.checked);</action> 35 </object> 34 36 35 <!-- Settings / Shadow PCF --> 36 <object size="0 35 100%-80 60" type="text" style="RightLabelText" ghost="true">Enable Shadow Filtering</object> 37 <object name="shadowPCFCheckbox" size="100%-56 40 100%-30 65" type="checkbox" style="StoneCrossBox" checked="true"> 38 <action on="Load">this.checked = Engine.Renderer_GetShadowPCFEnabled();</action> 39 <action on="Press">Engine.Renderer_SetShadowPCFEnabled(this.checked);</action> 40 </object> 37 <!-- Settings / Shadow PCF --> 38 <object size="0 35 100%-80 60" type="text" style="RightLabelText" ghost="true"> 39 <translatableAttribute id="caption">Enable Shadow Filtering</translatableAttribute> 40 </object> 41 <object name="shadowPCFCheckbox" size="100%-56 40 100%-30 65" type="checkbox" style="StoneCrossBox" checked="true"> 42 <action on="Load">this.checked = Engine.Renderer_GetShadowPCFEnabled();</action> 43 <action on="Press">Engine.Renderer_SetShadowPCFEnabled(this.checked);</action> 44 </object> 41 45 42 46 <!-- Settings / Water --> 43 47 <!-- <object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true">Enable Water Reflections</object> … … 46 50 <action on="Press">Engine.Renderer_SetWaterNormalEnabled(this.checked);</action> 47 51 </object>--> 48 52 49 <!-- Settings / Music--> 50 <object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true">Enable Music</object> 51 <object size="100%-56 65 100%-30 90" type="checkbox" style="StoneCrossBox" checked="true"> 52 <action on="Press">if (this.checked) startMusic(); else stopMusic();</action> 53 </object> 53 <!-- Settings / Music--> 54 <object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true"> 55 <translatableAttribute id="caption">Enable Music</translatableAttribute> 56 </object> 57 <object size="100%-56 65 100%-30 90" type="checkbox" style="StoneCrossBox" checked="true"> 58 <action on="Press">if (this.checked) startMusic(); else stopMusic();</action> 59 </object> 54 60 55 61 <!-- Settings / Dev Overlay --> 56 62 <!-- <object size="0 110 100%-80 135" type="text" style="RightLabelText" ghost="true">Developer Overlay</object> 57 63 <object size="100%-56 115 100%-30 140" type="checkbox" style="StoneCrossBox" checked="false"> 58 64 <action on="Press">toggleDeveloperOverlay();</action> 59 65 </object>--> 60 61 62 63 Cancel66 </object> 67 68 <object type="button" style="StoneButton" size="50%-64 100%-64 50%+64 100%-32"> 69 <translatableAttribute id="caption">Cancel</translatableAttribute> 64 70 <action on="Press"><![CDATA[Engine.PopGuiPage();]]></action> 65 71 </object> 66 72 67 73 </object> 68 74 </objects> -
new file inaries/data/mods/public/gui/page_locale.xml
diff --git a/binaries/data/mods/public/gui/page_locale.xml b/binaries/data/mods/public/gui/page_locale.xml new file mode 100644 index 0000000..ac75bc1
- + 1 <?xml version="1.0" encoding="utf-8"?> 2 <page> 3 <include>common/setup.xml</include> 4 <include>common/styles.xml</include> 5 <include>common/sprite1.xml</include> 6 <include>common/common_sprites.xml</include> 7 <include>common/common_styles.xml</include> 8 9 <include>locale/locale.xml</include> 10 11 <include>common/global.xml</include> 12 </page> -
binaries/data/mods/public/gui/pregame/mainmenu.js
diff --git a/binaries/data/mods/public/gui/pregame/mainmenu.js b/binaries/data/mods/public/gui/pregame/mainmenu.js index 43d1f4a..665da98 100644
a b function formatUserReportStatus(status) 103 103 var d = status.split(/:/, 3); 104 104 105 105 if (d[0] == "disabled") 106 return "disabled";106 return translate("disabled"); 107 107 108 108 if (d[0] == "connecting") 109 return "connecting to server";109 return translate("connecting to server"); 110 110 111 111 if (d[0] == "sending") 112 112 { 113 113 var done = d[1]; 114 return "uploading (" + Math.floor(100*done) + "%)";114 return sprintf(translate("uploading (%f%%)"), Math.floor(100*done)); 115 115 } 116 116 117 117 if (d[0] == "completed") 118 118 { 119 119 var httpCode = d[1]; 120 120 if (httpCode == 200) 121 return "upload succeeded";121 return translate("upload succeeded"); 122 122 else 123 return "upload failed (" + httpCode + ")";123 return sprintf(translate("upload failed (%{errorCode}s)"), { errorCode: httpCode }); 124 124 } 125 125 126 126 if (d[0] == "failed") 127 127 { 128 128 var errCode = d[1]; 129 129 var errMessage = d[2]; 130 return "upload failed (" + errMessage + ")";130 return sprintf(translate("upload failed (%{errorMessage}s)"), { errorMessage: errMessage }); 131 131 } 132 132 133 return "unknown";133 return translate("unknown"); 134 134 } 135 135 136 136 var lastTickTime = new Date; … … function onTick() 166 166 messageBox( 167 167 600, 168 168 300, 169 "[font=\"serif-bold-16\"][color=\"200 20 20\"]Warning:[/color] You appear to be using non-shader (fixed function) graphics. This option will be removed in a future 0 A.D. release, to allow for more advanced graphics features. We advise upgrading your graphics card to a more recent, shader-compatible model.\n\nPlease press \"Read More\" for more information or \"Ok\" to continue.", 170 "WARNING!", 169 "[font=\"serif-bold-16\"]" + 170 sprintf(translate("%{startWarning}sWarning:%{endWarning}s You appear to be using non-shader (fixed function) graphics. This option will be removed in a future 0 A.D. release, to allow for more advanced graphics features. We advise upgrading your graphics card to a more recent, shader-compatible model."), { startWarning: "[color=\"200 20 20\"]", endWarning: "[/color]"}) + 171 "\n\n" + 172 translate("Please press \"Read More\" for more information or \"OK\" to continue."), 173 translate("WARNING!"), 171 174 0, 172 [ "Ok", "Read More"],175 [translate("OK"), translate("Read More")], 173 176 [null, function() { Engine.OpenURL("http://www.wildfiregames.com/forum/index.php?showtopic=16734"); }] 174 177 ); 175 178 } … … function blendSubmenuIntoMain(topPosition, bottomPosition) 264 267 bottomSprite.size = "100%-2 " + (bottomPosition) + " 100% 100%"; 265 268 } 266 269 270 function getBuildString() 271 { 272 return sprintf(translate("Build: %(buildDate)s (%(revision)s)"), { buildDate: Engine.GetBuildTimestamp(0), revision: Engine.GetBuildTimestamp(2) }); 273 } 274 267 275 /* 268 276 * FUNCTIONS BELOW DO NOT WORK YET 269 277 */ … … function blendSubmenuIntoMain(topPosition, bottomPosition) 319 327 // guiUnHide ("pg"); 320 328 // } 321 329 //} 330 331 function exitGamePressed() 332 { 333 closeMenu(); 334 var btCaptions = [translate("Yes"), translate("No")]; 335 var btCode = [exit, null]; 336 messageBox(400, 200, translate("Are you sure you want to quit 0 A.D.?"), translate("Confirmation"), 0, btCaptions, btCode); 337 } 338 339 function pressedScenarioEditorButton() 340 { 341 closeMenu(); 342 // Start Atlas 343 if (Engine.AtlasIsAvailable()) 344 Engine.RestartInAtlas(); 345 else 346 messageBox(400, 200, translate("The scenario editor is not available or failed to load."), translate("Error"), 2); 347 } -
binaries/data/mods/public/gui/pregame/mainmenu.xml
diff --git a/binaries/data/mods/public/gui/pregame/mainmenu.xml b/binaries/data/mods/public/gui/pregame/mainmenu.xml index 837f6bf..b905dcf 100644
a b 91 91 <object 92 92 type="text" 93 93 style="userReportText" 94 >[font="serif-bold-16"]Help improve 0 A.D.![/font] 95 96 You can automatically send us anonymous feedback that will help us fix bugs, and improve performance and compatibility. 94 > 95 <attribute id="caption"> 96 <keep>[font="serif-bold-16"]</keep> 97 <translate>Help improve 0 A.D.!</translate> 98 <keep>[/font]\n\n</keep> 99 <translate>You can automatically send us anonymous feedback that will help us fix bugs, and improve performance and compatibility.</translate> 100 </attribute> 97 101 </object> 98 102 <object type="button" style="StoneButton" size="8 100%-36 146 100%-8"> 99 Enable feedback103 <translatableAttribute id="caption">Enable feedback</translatableAttribute> 100 104 <action on="Press">EnableUserReport(true);</action> 101 105 </object> 102 106 <object type="button" style="StoneButton" size="100%-146 100%-36 100%-8 100%-8"> 103 Technical details107 <translatableAttribute id="caption">Technical details</translatableAttribute> 104 108 <action on="Press">Engine.PushGuiPage("page_manual.xml", { "page": "userreport" });</action> 105 109 </object> 106 110 </object> … … You can automatically send us anonymous feedback that will help us fix bugs, and 115 119 name="userReportEnabledText" 116 120 type="text" 117 121 style="userReportText" 118 >[font="serif-bold-16"]Thank you for helping improve 0 A.D.![/font] 119 120 Anonymous feedback is currently enabled. 121 Status: $status. 122 </object> 122 > 123 <attribute id="caption"> 124 <keep>[font="serif-bold-16"]</keep> 125 <translate>Thank you for helping improve 0 A.D.!</translate> 126 <keep>[/font]\n\n</keep> 127 <translate>Anonymous feedback is currently enabled.</translate> 128 <keep>\n</keep> 129 <translate>Status: $status.</translate> 130 </attribute> 131 </object> 123 132 124 133 <object type="button" style="StoneButton" size="8 100%-36 146 100%-8"> 125 Disable feedback134 <translatableAttribute id="caption">Disable feedback</translatableAttribute> 126 135 <action on="Press">EnableUserReport(false);</action> 127 136 </object> 128 137 <object type="button" style="StoneButton" size="100%-146 100%-36 100%-8 100%-8"> 129 Technical details138 <translatableAttribute id="caption">Technical details</translatableAttribute> 130 139 <action on="Press">Engine.PushGuiPage("page_manual.xml", { "page": "userreport" });</action> 131 140 </object> 132 141 </object> … … Status: $status. 157 166 type="image" 158 167 size="0 4 100%-4 100%-4" 159 168 tooltip_style="pgToolTip" 160 tooltip="The 0 A.D. Game Manual."161 169 hidden="true" 162 170 > 163 171 <object name="subMenuSinglePlayerButton" … … Status: $status. 165 173 style="StoneButtonFancy" 166 174 size="0 0 100% 28" 167 175 tooltip_style="pgToolTip" 168 tooltip="Click here to start a new single player game."169 176 > 170 Matches 177 <translatableAttribute id="caption">Matches</translatableAttribute> 178 <translatableAttribute id="tooltip">Click here to start a new single player game.</translatableAttribute> 171 179 <action on="Press"> 172 180 Engine.SwitchGuiPage("page_gamesetup.xml", { type: "offline" }); 173 181 </action> … … Status: $status. 178 186 style="StoneButtonFancy" 179 187 size="0 32 100% 60" 180 188 tooltip_style="pgToolTip" 181 tooltip="Relive history through historical military campaigns. [NOT YET IMPLEMENTED]"182 189 enabled="false" 183 190 > 184 Campaigns 191 <translatableAttribute id="caption">Campaigns</translatableAttribute> 192 <translatableAttribute id="tooltip">Relive history through historical military campaigns. [NOT YET IMPLEMENTED]</translatableAttribute> 185 193 <action on="Press"> 186 194 closeMenu(); 187 195 <![CDATA[ … … Status: $status. 196 204 style="StoneButtonFancy" 197 205 size="0 64 100% 92" 198 206 tooltip_style="pgToolTip" 199 tooltip="Click here to load a saved game."200 207 > 201 Load Game 208 <translatableAttribute id="caption">Load Game</translatableAttribute> 209 <translatableAttribute id="tooltip">Click here to load a saved game.</translatableAttribute> 202 210 <action on="Press"> 203 211 closeMenu(); 204 212 Engine.PushGuiPage("page_loadgame.xml", { type: "offline" }); … … Status: $status. 212 220 type="image" 213 221 size="0 4 100%-4 100%-4" 214 222 tooltip_style="pgToolTip" 215 tooltip="The 0 A.D. Game Manual"216 223 hidden="true" 217 224 > 218 225 <object name="subMenuMultiplayerJoinButton" … … Status: $status. 220 227 style="StoneButtonFancy" 221 228 size="0 0 100% 28" 222 229 tooltip_style="pgToolTip" 223 tooltip="Joining an existing multiplayer game."224 230 > 225 Join Game 231 <translatableAttribute id="caption">Join Game</translatableAttribute> 232 <translatableAttribute id="tooltip">Joining an existing multiplayer game.</translatableAttribute> 226 233 <action on="Press"> 227 234 closeMenu(); 228 235 // Open Multiplayer connection window with join option. … … Status: $status. 235 242 style="StoneButtonFancy" 236 243 size="0 32 100% 60" 237 244 tooltip_style="pgToolTip" 238 tooltip="Host a multiplayer game.\n\nRequires UDP port 20595 to be open."239 245 > 240 Host Game 246 <translatableAttribute id="caption">Host Game</translatableAttribute> 247 <translatableAttribute id="tooltip">Host a multiplayer game.\n\nRequires UDP port 20595 to be open.</translatableAttribute> 241 248 <action on="Press"> 242 249 closeMenu(); 243 250 // Open Multiplayer connection window with host option. … … Status: $status. 251 258 type="image" 252 259 size="0 4 100%-4 100%-4" 253 260 tooltip_style="pgToolTip" 254 tooltip="The 0 A.D. Game Manual"255 261 hidden="true" 256 262 > 257 263 <object name="submenuOptionsButton" … … Status: $status. 259 265 type="button" 260 266 size="0 0 100% 28" 261 267 tooltip_style="pgToolTip" 262 tooltip="Adjust game settings. [NOT YET IMPLEMENTED]"263 268 enabled="false" 264 269 > 265 Options 270 <translatableAttribute id="caption">Options</translatableAttribute> 271 <translatableAttribute id="tooltip">Adjust game settings. [NOT YET IMPLEMENTED]</translatableAttribute> 266 272 <action on="Press"> 267 273 closeMenu(); 268 274 <![CDATA[ … … Status: $status. 272 278 </action> 273 279 </object> 274 280 275 <object name="submenu EditorButton"281 <object name="submenuLocaleButton" 276 282 style="StoneButtonFancy" 277 283 type="button" 278 284 size="0 32 100% 60" 279 285 tooltip_style="pgToolTip" 280 tooltip="Open the Atlas Scenario Editor in a new window. You can run this more reliably by starting the game with the command-line argument "-editor"."281 286 > 282 Scenario Editor 287 <translatableAttribute id="caption">Language</translatableAttribute> 288 <translatableAttribute id="tooltip">Choose the language of the game.</translatableAttribute> 283 289 <action on="Press"> 284 closeMenu();285 290 <![CDATA[ 286 // Start Atlas 287 if (Engine.AtlasIsAvailable()) 288 Engine.RestartInAtlas(); 289 else 290 messageBox(400, 200, "The scenario editor is not available or failed to load.", "Error", 2); 291 closeMenu(); 292 Engine.PushGuiPage("page_locale.xml"); 291 293 ]]> 292 294 </action> 293 295 </object> 296 297 <object name="submenuEditorButton" 298 style="StoneButtonFancy" 299 type="button" 300 size="0 64 100% 92" 301 tooltip_style="pgToolTip" 302 > 303 <translatableAttribute id="caption">Scenario Editor</translatableAttribute> 304 <translatableAttribute id="tooltip">Open the Atlas Scenario Editor in a new window. You can run this more reliably by starting the game with the command-line argument "-editor".</translatableAttribute> 305 <action on="Press"> 306 pressedScenarioEditorButton(); 307 </action> 308 </object> 294 309 </object> 295 310 </object><!-- end of submenu --> 296 311 … … Status: $status. 338 353 style="StoneButtonFancy" 339 354 size="4 4 100%-4 32" 340 355 tooltip_style="pgToolTip" 341 tooltip="The 0 A.D. Game Manual"342 356 > 343 Learn To Play 357 <translatableAttribute id="caption">Learn To Play</translatableAttribute> 358 <translatableAttribute id="tooltip">The 0 A.D. Game Manual</translatableAttribute> 344 359 <action on="Press"> 345 360 closeMenu(); 346 361 <![CDATA[ … … Status: $status. 355 370 type="button" 356 371 size="4 36 100%-4 64" 357 372 tooltip_style="pgToolTip" 358 tooltip="Challenge the computer player to a single player match."359 373 > 360 Single Player 374 <translatableAttribute id="caption">Single Player</translatableAttribute> 375 <translatableAttribute id="tooltip">Challenge the computer player to a single player match.</translatableAttribute> 361 376 <action on="Press"> 362 377 closeMenu(); 363 378 openMenu("submenuSinglePlayer", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 3); … … Status: $status. 370 385 type="button" 371 386 size="4 68 100%-4 96" 372 387 tooltip_style="pgToolTip" 373 tooltip="Fight against one or more human players in a multiplayer game."374 388 > 375 Multiplayer 389 <translatableAttribute id="caption">Multiplayer</translatableAttribute> 390 <translatableAttribute id="tooltip">Fight against one or more human players in a multiplayer game.</translatableAttribute> 376 391 <action on="Press"> 377 392 closeMenu(); 378 393 openMenu("submenuMultiplayer", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 2); … … Status: $status. 385 400 type="button" 386 401 size="4 100 100%-4 128" 387 402 tooltip_style="pgToolTip" 388 tooltip="Game options and scenario design tools."389 403 > 390 Tools <![CDATA[&]]> Options 404 <translatableAttribute id="caption">Tools & Options</translatableAttribute> 405 <translatableAttribute id="tooltip">Game options and scenario design tools.</translatableAttribute> 391 406 <action on="Press"> 392 407 closeMenu(); 393 openMenu("submenuToolsAndOptions", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 2);408 openMenu("submenuToolsAndOptions", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 3); 394 409 </action> 395 410 </object> 396 411 … … Status: $status. 400 415 type="button" 401 416 size="4 132 100%-4 160" 402 417 tooltip_style="pgToolTip" 403 tooltip="Learn about the many civilizations featured in 0 A.D."404 418 > 405 History 419 <translatableAttribute id="caption">History</translatableAttribute> 420 <translatableAttribute id="tooltip">Learn about the many civilizations featured in 0 A.D.</translatableAttribute> 406 421 <action on="Press"> 407 422 closeMenu(); 408 423 <![CDATA[ … … Status: $status. 417 432 style="StoneButtonFancy" 418 433 size="4 164 100%-4 192" 419 434 tooltip_style="pgToolTip" 420 tooltip="Exit Game"421 435 > 422 Exit 423 <action on="Press"> 424 closeMenu(); 425 <![CDATA[ 426 var btCaptions = ["Yes", "No"]; 427 var btCode = [exit, null]; 428 messageBox(400, 200, "Are you sure you want to quit 0 A.D.?", "Confirmation", 0, btCaptions, btCode); 429 ]]> 430 </action> 436 <translatableAttribute id="caption">Exit</translatableAttribute> 437 <translatableAttribute id="tooltip">Exit Game</translatableAttribute> 438 <action on="Press">exitGamePressed();</action> 431 439 </object> 432 440 </object> 433 441 … … Status: $status. 445 453 size="8 8 100%-8 100%-36" 446 454 ghost="true" 447 455 > 448 [font="serif-bold-16"]Alpha XIV: Naukratis<!-- IMPORTANT: remember to update session/session.xml in sync with this -->[/font] 449 450 WARNING: This is an early development version of the game. Many features have not been added yet. 451 452 Get involved at: play0ad.com 456 <!-- IMPORTANT: remember to update session/session.xml in sync with this: --> 457 <attribute id="caption"> 458 <keep>[font="serif-bold-16"]</keep> 459 <translate>Alpha XIV: Naukratis</translate> 460 <keep>[/font]\n\n</keep> 461 <translate>WARNING: This is an early development version of the game. Many features have not been added yet.</translate> 462 <keep>\n\n</keep> 463 <translate>Get involved at: play0ad.com</translate> 464 </attribute> 453 465 </object> 454 466 455 467 <!-- FUNDRAISER --> 456 468 <object type="button" 457 469 style="StoneButton" 458 470 tooltip_style="pgToolTip" 459 tooltip="Click to view fundraiser information."460 471 size="8 100%-108 100%-8 100%-80" 461 472 > 462 Fundraiser 473 <translatableAttribute id="caption">Fundraiser</translatableAttribute> 474 <translatableAttribute id="tooltip">Click to view fundraiser information.</translatableAttribute> 463 475 <action on="Press"><![CDATA[ 464 476 closeMenu(); 465 477 Engine.PushGuiPage("page_splashscreen.xml", { "page": "splashscreen" }); … … Get involved at: play0ad.com 470 482 <object type="button" 471 483 style="StoneButton" 472 484 tooltip_style="pgToolTip" 473 tooltip="Click to open play0ad.com in your web browser."474 485 size="8 100%-72 50%-4 100%-44" 475 486 > 476 Website 487 <translatableAttribute id="caption">Website</translatableAttribute> 488 <translatableAttribute id="tooltip">Click to open play0ad.com in your web browser.</translatableAttribute> 477 489 <action on="Press"><![CDATA[ 478 490 var url = "http://play0ad.com/"; 479 491 Engine.OpenURL(url); … … Get involved at: play0ad.com 484 496 <object type="button" 485 497 style="StoneButton" 486 498 tooltip_style="pgToolTip" 487 tooltip="Click to open the 0 A.D. IRC chat in your browser. (#0ad on webchat.quakenet.org)"488 499 size="50%+4 100%-72 100%-8 100%-44" 489 500 > 490 Chat 501 <translatableAttribute id="caption">Chat</translatableAttribute> 502 <translatableAttribute id="tooltip">Click to open the 0 A.D. IRC chat in your browser. (#0ad on webchat.quakenet.org)</translatableAttribute> 491 503 <action on="Press"><![CDATA[ 492 504 var url = "http://webchat.quakenet.org/?channels=0ad"; 493 505 Engine.OpenURL(url); … … Get involved at: play0ad.com 498 510 <object type="button" 499 511 style="StoneButton" 500 512 tooltip_style="pgToolTip" 501 tooltip="Click to visit 0 A.D. Trac to report a bug, crash, or error"502 513 size="8 100%-36 100%-8 100%-8" 503 514 > 504 Report a Bug 515 <translatableAttribute id="caption">Report a Bug</translatableAttribute> 516 <translatableAttribute id="tooltip">Click to visit 0 A.D. Trac to report a bug, crash, or error</translatableAttribute> 505 517 <action on="Press"><![CDATA[ 506 518 var url = "http://trac.wildfiregames.com/wiki/ReportingErrors/"; 507 519 Engine.OpenURL(url); … … Get involved at: play0ad.com 530 542 style="MediumTitleText" 531 543 ghost="true" 532 544 size="50%-128 32 50%+128 48" 533 >WILDFIRE GAMES</object> 545 > 546 <translatableAttribute id="caption">WILDFIRE GAMES</translatableAttribute> 547 </object> 534 548 </object> 535 549 536 550 <!-- VERSION --> … … Get involved at: play0ad.com 540 554 ghost="true" 541 555 size="50%-128 100%-36 50%+128 100%" 542 556 > 543 <action on="Load"> <![CDATA[544 this.caption = "Build: " + buildTime(0) + " - " + buildTime(2);545 ]]></action>557 <action on="Load"> 558 this.caption = getBuildString(); 559 </action> 546 560 </object> 547 561 </object> 548 562 </object> -
binaries/data/mods/public/gui/savedgames/load.js
diff --git a/binaries/data/mods/public/gui/savedgames/load.js b/binaries/data/mods/public/gui/savedgames/load.js index 3201421..f058ba8 100644
a b function init() 5 5 var savedGames = Engine.GetSavedGames(); 6 6 if (savedGames.length == 0) 7 7 { 8 gameSelection.list = [ "No saved games found"];8 gameSelection.list = [translate("No saved games found")]; 9 9 gameSelection.selected = 0; 10 10 getGUIObjectByName("loadGameButton").enabled = false; 11 11 getGUIObjectByName("deleteGameButton").enabled = false; … … function loadGame() 32 32 { 33 33 // Probably the file wasn't found 34 34 // Show error and refresh saved game list 35 error( "Could not load saved game '"+gameID+"'");35 error(sprintf(translate("Could not load saved game '%(id)s'"), { id: gameID })); 36 36 init(); 37 37 } 38 38 else … … function deleteGame() 53 53 var gameID = gameSelection.list_data[gameSelection.selected]; 54 54 55 55 // Ask for confirmation 56 var btCaptions = [ "Yes", "No"];56 var btCaptions = [translate("Yes"), translate("No")]; 57 57 var btCode = [function(){ reallyDeleteGame(gameID); }, null]; 58 messageBox(500, 200, "\""+gameLabel+"\"\nSaved game will be permanently deleted, are you sure?", "DELETE", 0, btCaptions, btCode);58 messageBox(500, 200, sprintf(translate("\"%(label)s\""), { label: gameLabel }) + "\n" + translate("Saved game will be permanently deleted, are you sure?"), translate("DELETE"), 0, btCaptions, btCode); 59 59 } 60 60 61 61 function reallyDeleteGame(gameID) 62 62 { 63 63 if (!Engine.DeleteSavedGame(gameID)) 64 error( "Could not delete saved game '"+gameID+"'");64 error(sprintf(translate("Could not delete saved game '%(id)s'"), { id: gameID })); 65 65 66 66 // Run init again to refresh saved game list 67 67 init(); -
binaries/data/mods/public/gui/savedgames/load.xml
diff --git a/binaries/data/mods/public/gui/savedgames/load.xml b/binaries/data/mods/public/gui/savedgames/load.xml index 81f245e..7d64312 100644
a b 12 12 <object type="image" style="StoneDialog" size="50%-300 50%-200 50%+300 50%+200"> 13 13 14 14 <object type="text" style="TitleText" size="50%-128 0%-16 50%+128 16"> 15 Load Game15 <translatableAttribute id="caption">Load Game</translatableAttribute> 16 16 </object> 17 17 18 18 <object name="gameSelection" … … 22 22 </object> 23 23 24 24 <object name="loadGameButton" type="button" size="0%+25 100%-60 33%+10 100%-32" style="StoneButton"> 25 Load25 <translatableAttribute id="caption">Load</translatableAttribute> 26 26 <action on="Press">loadGame();</action> 27 27 </object> 28 28 29 29 <object name="deleteGameButton" type="button" size="33%+20 100%-60 66%-15 100%-32" style="StoneButton"> 30 Delete30 <translatableAttribute id="caption">Delete</translatableAttribute> 31 31 <action on="Press">deleteGame();</action> 32 32 </object> 33 33 34 34 <object type="button" style="StoneButton" size="66%-5 100%-60 100%-25 100%-32"> 35 Cancel35 <translatableAttribute id="caption">Cancel</translatableAttribute> 36 36 <action on="Press">Engine.PopGuiPage();</action> 37 37 </object> 38 38 -
binaries/data/mods/public/gui/savedgames/save.js
diff --git a/binaries/data/mods/public/gui/savedgames/save.js b/binaries/data/mods/public/gui/savedgames/save.js index d734655..3fc55fd 100644
a b function init(data) 30 30 var savedGames = Engine.GetSavedGames(); 31 31 if (savedGames.length == 0) 32 32 { 33 gameSelection.list = [ "No saved games found"];33 gameSelection.list = [translate("No saved games found")]; 34 34 gameSelection.selected = -1; 35 35 return; 36 36 } … … function saveGame() 59 59 if (gameSelection.selected != -1) 60 60 { 61 61 // Ask for confirmation 62 var btCaptions = [ "Yes", "No"];62 var btCaptions = [translate("Yes"), translate("No")]; 63 63 var btCode = [function(){ reallySaveGame(name, desc, false); }, null]; 64 messageBox(500, 200, "\""+gameLabel+"\"\nSaved game will be permanently overwritten, are you sure?", "OVERWRITE SAVE", 0, btCaptions, btCode);64 messageBox(500, 200, sprintf(translate("\"%(label)s\""), { label: gameLabel }) + "\n" + translate("Saved game will be permanently overwritten, are you sure?"), translate("OVERWRITE SAVE"), 0, btCaptions, btCode); 65 65 } 66 66 else 67 67 reallySaveGame(name, desc, true); … … function deleteGame() 91 91 var gameID = gameSelection.list_data[gameSelection.selected]; 92 92 93 93 // Ask for confirmation 94 var btCaptions = [ "Yes", "No"];94 var btCaptions = [translate("Yes"), translate("No")]; 95 95 var btCode = [function(){ reallyDeleteGame(gameID); }, null]; 96 messageBox(500, 200, "\""+gameLabel+"\"\nSaved game will be permanently deleted, are you sure?", "DELETE", 0, btCaptions, btCode);96 messageBox(500, 200, sprintf(translate("\"%(label)s\""), { label: gameLabel }) + "\n" + translate("Saved game will be permanently deleted, are you sure?"), translate("DELETE"), 0, btCaptions, btCode); 97 97 } 98 98 99 99 function reallyDeleteGame(gameID) 100 100 { 101 101 if (!Engine.DeleteSavedGame(gameID)) 102 error( "Could not delete saved game '"+gameID+"'");102 error(sprintf(translate("Could not delete saved game '%(id)s'"), { id: gameID })); 103 103 104 104 // Run init again to refresh saved game list 105 105 init(); -
binaries/data/mods/public/gui/savedgames/save.xml
diff --git a/binaries/data/mods/public/gui/savedgames/save.xml b/binaries/data/mods/public/gui/savedgames/save.xml index 70d24e9..004aa91 100644
a b 12 12 <object type="image" style="StoneDialog" size="50%-300 50%-200 50%+300 50%+200"> 13 13 <object type="image" z="0" sprite="BackgroundTranslucent"/> 14 14 <object type="text" style="TitleText" size="50%-128 0%-16 50%+128 16"> 15 Save Game15 <translatableAttribute id="caption">Save Game</translatableAttribute> 16 16 </object> 17 17 18 18 <object name="gameSelection" … … 25 25 </action> 26 26 </object> 27 27 28 <object size="24 100%-124 100%-24 100%-100" name="descLabel" type="text" style="LeftLabelText">Description:</object> 28 <object size="24 100%-124 100%-24 100%-100" name="descLabel" type="text" style="LeftLabelText"> 29 <translatableAttribute id="caption">Description:</translatableAttribute> 30 </object> 29 31 30 32 <object name="saveGameDesc" size="24 100%-96 100%-24 100%-72" type="input" style="StoneInput"/> 31 33 32 34 <object name="saveButton" type="button" size="0%+25 100%-60 33%+10 100%-32" style="StoneButton"> 33 Save35 <translatableAttribute id="caption">Save</translatableAttribute> 34 36 <action on="Press">saveGame();</action> 35 37 </object> 36 38 37 39 <object name="deleteGameButton" type="button" size="33%+20 100%-60 66%-15 100%-32" style="StoneButton"> 38 Delete40 <translatableAttribute id="caption">Delete</translatableAttribute> 39 41 <action on="Press">deleteGame();</action> 40 42 </object> 41 43 42 44 <object type="button" style="StoneButton" size="66%-5 100%-60 100%-25 100%-32"> 43 Cancel45 <translatableAttribute id="caption">Cancel</translatableAttribute> 44 46 <action on="Press">closeSave(true);</action> 45 47 </object> 46 48 -
binaries/data/mods/public/gui/session/input.js
diff --git a/binaries/data/mods/public/gui/session/input.js b/binaries/data/mods/public/gui/session/input.js index 5c51e12..2cac0d1 100644
a b function updateBuildingPlacementPreview() 135 135 elevationBonus: placementSupport.attack.elevationBonus, 136 136 }; 137 137 var averageRange = Engine.GuiInterfaceCall("GetAverageRangeForBuildings",cmd); 138 placementSupport.tooltipMessage = "Basic range: "+Math.round(cmd.range/4)+"\nAverage bonus range: "+Math.round((averageRange - cmd.range)/4);138 placementSupport.tooltipMessage = sprintf(translate("Basic range: %(range)s"), { range: Math.round(cmd.range/4) }) + "\n" + sprintf(translate("Average bonus range: %(range)s"), { range: Math.round((averageRange - cmd.range)/4) }); 139 139 } 140 140 return true; 141 141 } … … function getActionInfo(action, target) 241 241 data.command = "garrison"; 242 242 data.target = target; 243 243 cursor = "action-garrison"; 244 tooltip = "Current garrison: " + targetState.garrisonHolder.entities.length 245 + "/" + targetState.garrisonHolder.capacity; 244 tooltip = sprintf(translate("Current garrison: %(garrisoned)s/%(capacity)s"), { 245 garrisoned: targetState.garrisonHolder.entities.length, 246 capacity: targetState.garrisonHolder.capacity 247 }); 246 248 if (targetState.garrisonHolder.entities.length >= targetState.garrisonHolder.capacity) 247 249 tooltip = "[color=\"orange\"]" + tooltip + "[/color]"; 248 250 } … … function getActionInfo(action, target) 287 289 data.target = traderData.secondMarket; 288 290 data.source = traderData.firstMarket; 289 291 cursor = "action-setup-trade-route"; 290 tooltip = "Right-click to establish a default route for new traders.";292 tooltip = translate("Right-click to establish a default route for new traders."); 291 293 if (trader) 292 tooltip += "\n Gain (metal): " + getTradingTooltip(gain);294 tooltip += "\n" + sprintf(translate("Gain (metal): %(gain)s"), { gain: getTradingTooltip(gain) }); 293 295 else // Foundation or cannot produce traders 294 tooltip += "\n Expected gain (metal): " + getTradingTooltip(gain);296 tooltip += "\n" + sprintf(translate("Expected gain (metal): %(gain)s"), { gain: getTradingTooltip(gain) }); 295 297 } 296 298 } 297 299 … … function getActionInfo(action, target) 328 330 case "garrison": 329 331 if (hasClass(entState, "Unit") && targetState.garrisonHolder && (playerOwned || mutualAllyOwned)) 330 332 { 331 var tooltip = "Current garrison: " + targetState.garrisonHolder.entities.length 332 + "/" + targetState.garrisonHolder.capacity; 333 var tooltip = sprintf(translate("Current garrison: %(garrisoned)s/%(capacity)s"), { 334 garrisoned: targetState.garrisonHolder.entities.length, 335 capacity: targetState.garrisonHolder.capacity 336 }); 333 337 if (targetState.garrisonHolder.entities.length >= targetState.garrisonHolder.capacity) 334 338 tooltip = "[color=\"orange\"]" + tooltip + "[/color]"; 335 339 var allowedClasses = targetState.garrisonHolder.allowedClasses; … … function getActionInfo(action, target) 353 357 switch (tradingDetails.type) 354 358 { 355 359 case "is first": 356 tooltip = "Origin trade market.";360 tooltip = translate("Origin trade market."); 357 361 if (tradingDetails.hasBothMarkets) 358 tooltip += "\nGain (" + tradingDetails.goods + "): " + getTradingTooltip(tradingDetails.gain); 362 tooltip += "\n" + sprintf(translate("Gain (%(goods)s): %(gain)s"), { 363 goods: tradingDetails.goods, 364 gain: getTradingTooltip(tradingDetails.gain) 365 }); 359 366 else 360 tooltip += "\n Right-click on another market to set it as a destination trade market."367 tooltip += "\n" + translate("Right-click on another market to set it as a destination trade market.") 361 368 break; 362 369 case "is second": 363 tooltip = "Destination trade market.\nGain (" + tradingDetails.goods + "): " + getTradingTooltip(tradingDetails.gain); 370 tooltip = translate("Destination trade market.") + "\n" + sprintf(translate("Gain (%(goods)s): %(gain)s"), { 371 goods: tradingDetails.goods, 372 gain: getTradingTooltip(tradingDetails.gain) 373 }); 364 374 break; 365 375 case "set first": 366 tooltip = "Right-click to set as origin trade market";376 tooltip = translate("Right-click to set as origin trade market"); 367 377 break; 368 378 case "set second": 369 tooltip = "Right-click to set as destination trade market.\nGain (" + tradingDetails.goods + "): " + getTradingTooltip(tradingDetails.gain); 379 tooltip = translate("Right-click to set as destination trade market.") + "\n" + sprintf(translate("Gain (%(goods)s): %(gain)s"), { 380 goods: tradingDetails.goods, 381 gain: getTradingTooltip(tradingDetails.gain) 382 }); 370 383 break; 371 384 } 372 385 return {"possible": true, "tooltip": tooltip}; … … function tryPlaceBuilding(queued) 542 555 { 543 556 if (placementSupport.mode !== "building") 544 557 { 545 error("[tryPlaceBuilding] Called while in '"+placementSupport.mode+"' placement mode instead of 'building'"); 558 error(sprintf(translate("[%(functionName)s] Called while in '%(mode)s' placement mode instead of 'building'"), { 559 functionName: "tryPlaceBuilding", 560 mode: placementSupport.mode 561 })); 546 562 return false; 547 563 } 548 564 … … function tryPlaceWall(queued) 583 599 { 584 600 if (placementSupport.mode !== "wall") 585 601 { 586 error("[tryPlaceWall] Called while in '" + placementSupport.mode + "' placement mode; expected 'wall' mode"); 602 error(sprintf(translate("[%(functionName)s] Called while in '%(mode)s' placement mode; expected 'wall' mode"), { 603 functionName: "tryPlaceWall", 604 mode: placementSupport.mode 605 })); 587 606 return false; 588 607 } 589 608 590 609 var wallPlacementInfo = updateBuildingPlacementPreview(); // entities making up the wall (wall segments, towers, ...) 591 610 if (!(wallPlacementInfo === false || typeof(wallPlacementInfo) === "object")) 592 611 { 593 error("[tryPlaceWall] Unexpected return value from updateBuildingPlacementPreview: '" + uneval(placementInfo) + "'; expected either 'false' or 'object'"); 612 error(sprintf(translate("[%(functionName)s] Unexpected return value from %(function2Name)s: '%(value)s'; expected either 'false' or 'object'"), { 613 functionName: "tryPlaceWall", 614 function2Name: "updateBuildingPlacementPreview", 615 value: uneval(placementInfo) 616 })); 594 617 return false; 595 618 } 596 619 … … function handleInputBeforeGui(ev, hoveredObject) 922 945 } 923 946 else 924 947 { 925 placementSupport.tooltipMessage = "Cannot build wall here!";948 placementSupport.tooltipMessage = translate("Cannot build wall here!"); 926 949 } 927 950 928 951 updateBuildingPlacementPreview(); -
binaries/data/mods/public/gui/session/menu.js
diff --git a/binaries/data/mods/public/gui/session/menu.js b/binaries/data/mods/public/gui/session/menu.js index 0046f64..1e2879c 100644
a b function resignMenuButton() 133 133 closeMenu(); 134 134 closeOpenDialogs(); 135 135 pauseGame(); 136 var btCaptions = [ "Yes", "No"];136 var btCaptions = [translate("Yes"), translate("No")]; 137 137 var btCode = [resignGame, resumeGame]; 138 messageBox(400, 200, "Are you sure you want to resign?", "Confirmation", 0, btCaptions, btCode);138 messageBox(400, 200, translate("Are you sure you want to resign?"), translate("Confirmation"), 0, btCaptions, btCode); 139 139 } 140 140 141 141 function exitMenuButton() … … function exitMenuButton() 143 143 closeMenu(); 144 144 closeOpenDialogs(); 145 145 pauseGame(); 146 var btCaptions = [ "Yes", "No"];146 var btCaptions = [translate("Yes"), translate("No")]; 147 147 var btCode = [leaveGame, resumeGame]; 148 messageBox(400, 200, "Are you sure you want to quit?", "Confirmation", 0, btCaptions, btCode);148 messageBox(400, 200, translate("Are you sure you want to quit?"), translate("Confirmation"), 0, btCaptions, btCode); 149 149 } 150 150 151 151 function openDeleteDialog(selection) … … function openDeleteDialog(selection) 158 158 Engine.PostNetworkCommand({"type": "delete-entities", "entities": selection}); 159 159 }; 160 160 161 var btCaptions = [ "Yes", "No"];161 var btCaptions = [translate("Yes"), translate("No")]; 162 162 var btCode = [deleteSelectedEntities, resumeGame]; 163 163 164 messageBox(400, 200, "Destroy everything currently selected?", "Delete", 0, btCaptions, btCode);164 messageBox(400, 200, translate("Destroy everything currently selected?"), translate("Delete"), 0, btCaptions, btCode); 165 165 } 166 166 167 167 // Menu functions … … function openDiplomacy() 264 264 getGUIObjectByName("diplomacyPlayerName["+(i-1)+"]").caption = "[color=\"" + playerColor + "\"]" + players[i].name + "[/color]"; 265 265 getGUIObjectByName("diplomacyPlayerCiv["+(i-1)+"]").caption = g_CivData[players[i].civ].Name; 266 266 267 getGUIObjectByName("diplomacyPlayerTeam["+(i-1)+"]").caption = (players[i].team < 0) ? "None": players[i].team+1;267 getGUIObjectByName("diplomacyPlayerTeam["+(i-1)+"]").caption = (players[i].team < 0) ? translateWithContext("team", "None") : players[i].team+1; 268 268 269 269 if (i != we) 270 getGUIObjectByName("diplomacyPlayerTheirs["+(i-1)+"]").caption = (players[i].isAlly[we] ? "Ally" : (players[i].isNeutral[we] ? "Neutral" : "Enemy"));270 getGUIObjectByName("diplomacyPlayerTheirs["+(i-1)+"]").caption = (players[i].isAlly[we] ? translate("Ally") : (players[i].isNeutral[we] ? translate("Neutral") : translate("Enemy"))); 271 271 272 272 // Don't display the options for ourself, or if we or the other player aren't active anymore 273 273 if (i == we || players[we].state != "active" || players[i].state != "active") … … function openDiplomacy() 328 328 if (setting == "ally") 329 329 { 330 330 if (players[we].isAlly[i]) 331 button.caption = "x";331 button.caption = translate("x"); 332 332 else 333 333 button.caption = ""; 334 334 } 335 335 else if (setting == "neutral") 336 336 { 337 337 if (players[we].isNeutral[i]) 338 button.caption = "x";338 button.caption = translate("x"); 339 339 else 340 340 button.caption = ""; 341 341 } 342 342 else // "enemy" 343 343 { 344 344 if (players[we].isEnemy[i]) 345 button.caption = "x";345 button.caption = translate("x"); 346 346 else 347 347 button.caption = ""; 348 348 } 349 350 349 button.onpress = (function(e){ return function() { setDiplomacy(e) } })({"player": i, "to": setting}); 351 350 button.hidden = false; 352 351 } … … function openManual() 421 420 function toggleDeveloperOverlay() 422 421 { 423 422 var devCommands = getGUIObjectByName("devCommands"); 424 var text = devCommands.hidden ? "opened." : "closed."; 425 submitChatDirectly("The Developer Overlay was " + text); 423 if (devCommands.hidden) 424 submitChatDirectly(translate("The Developer Overlay was opened.")); 425 else 426 submitChatDirectly(translate("The Developer Overlay was closed.")); 426 427 // Update the options dialog 427 428 getGUIObjectByName("developerOverlayCheckbox").checked = devCommands.hidden; 428 429 devCommands.hidden = !devCommands.hidden; … … function closeOpenDialogs() 439 440 function formatTributeTooltip(player, resource, amount) 440 441 { 441 442 var playerColor = player.color.r + " " + player.color.g + " " + player.color.b; 442 return "Tribute " + amount + " " + resource + " to [color=\"" + playerColor + "\"]" + player.name + 443 "[/color]. Shift-click to tribute " + (amount < 500 ? 500 : amount + 500) + "."; 443 return sprintf(translate("Tribute %(resourceAmount)s %(resourceType)s to %(playerName)s. Shift-click to tribute %(greaterAmount)s."), { 444 resourceAmount: amount, 445 resourceType: resource, 446 playerName: "[color=\"" + playerColor + "\"]" + player.name + "[/color]", 447 greaterAmount: (amount < 500 ? 500 : amount + 500) 448 }); 444 449 } -
binaries/data/mods/public/gui/session/messages.js
diff --git a/binaries/data/mods/public/gui/session/messages.js b/binaries/data/mods/public/gui/session/messages.js index f8a5171..1d35981 100644
a b function getCheatsData() 19 19 { 20 20 var currentCheat = parseJSONData("simulation/data/cheats/"+fileName+".json"); 21 21 if (Object.keys(cheats).indexOf(currentCheat.Name) !== -1) 22 warn( "Cheat name '"+currentCheat.Name+"' is already present");22 warn(sprintf(translate("Cheat name '%(name)s' is already present"), { name: currentCheat.Name })); 23 23 else 24 24 cheats[currentCheat.Name] = currentCheat.Data; 25 25 } … … function getUsernameAndColor(player) 153 153 // Messages 154 154 function handleNetMessage(message) 155 155 { 156 log( "Net message: " + uneval(message));156 log(sprintf(translate("Net message: %(message)s"), { message: uneval(message) })); 157 157 158 158 switch (message.type) 159 159 { … … function handleNetMessage(message) 166 166 switch (message.status) 167 167 { 168 168 case "waiting_for_players": 169 obj.caption = "Waiting for other players to connect...";169 obj.caption = translate("Waiting for other players to connect..."); 170 170 obj.hidden = false; 171 171 break; 172 172 case "join_syncing": 173 obj.caption = "Synchronising gameplay with other players...";173 obj.caption = translate("Synchronising gameplay with other players..."); 174 174 obj.hidden = false; 175 175 break; 176 176 case "active": … … function handleNetMessage(message) 178 178 obj.hidden = true; 179 179 break; 180 180 case "connected": 181 obj.caption = "Connected to the server.";181 obj.caption = translate("Connected to the server."); 182 182 obj.hidden = false; 183 183 break; 184 184 case "authenticated": 185 obj.caption = "Connection to the server has been authenticated.";185 obj.caption = translate("Connection to the server has been authenticated."); 186 186 obj.hidden = false; 187 187 break; 188 188 case "disconnected": 189 189 g_Disconnected = true; 190 obj.caption = "Connection to the server has been lost.\n\nThe game has ended.";190 obj.caption = translate("Connection to the server has been lost.") + "\n\n" + translate("The game has ended."); 191 191 obj.hidden = false; 192 192 break; 193 193 default: 194 error( "Unrecognised netstatus type "+message.status);194 error(sprintf(translate("Unrecognised netstatus type %(netType)s"), { netType: message.status })); 195 195 break; 196 196 } 197 197 break; … … function handleNetMessage(message) 237 237 break; 238 238 239 239 default: 240 error( "Unrecognised net message type "+message.type);240 error(sprintf(translate("Unrecognised net message type %(messageType)s"), { messageType: message.type })); 241 241 } 242 242 } 243 243 … … function addChatMessage(msg, playerAssignments) 319 319 320 320 var playerColor, username; 321 321 322 // No prefixby default. May be set by parseChatCommands().323 msg. prefix= "";322 // No context by default. May be set by parseChatCommands(). 323 msg.context = ""; 324 324 325 325 if (playerAssignments[msg.guid]) 326 326 { … … function addChatMessage(msg, playerAssignments) 344 344 else 345 345 { 346 346 playerColor = "255 255 255"; 347 username = "Unknown player";347 username = translate("Unknown player"); 348 348 } 349 349 350 350 var message = escapeText(msg.text); … … function addChatMessage(msg, playerAssignments) 354 354 switch (msg.type) 355 355 { 356 356 case "connect": 357 formatted = "[color=\"" + playerColor + "\"]" + username + "[/color] has joined the game.";357 formatted = sprintf(translate("%(player)s has joined the game."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 358 358 break; 359 359 case "disconnect": 360 formatted = "[color=\"" + playerColor + "\"]" + username + "[/color] has left the game.";360 formatted = sprintf(translate("%(player)s has left the game."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 361 361 break; 362 362 case "defeat": 363 363 // In singleplayer, the local player is "You". "You has" is incorrect. 364 var verb = (!g_IsNetworked && msg.player == Engine.GetPlayerID()) ? "have" : "has"; 365 formatted = "[color=\"" + playerColor + "\"]" + username + "[/color] " + verb + " been defeated."; 364 if (!g_IsNetworked && msg.player == Engine.GetPlayerID()) 365 formatted = translate("You have been defeated."); 366 else 367 formatted = sprintf(translate("%(player)s has been defeated."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 366 368 break; 367 369 case "diplomacy": 368 370 var status = (msg.status == "ally" ? "allied" : (msg.status == "enemy" ? "at war" : "neutral")); 369 371 if (msg.player == Engine.GetPlayerID()) 370 372 { 371 373 [username, playerColor] = getUsernameAndColor(msg.player1); 372 formatted = "You are now "+status+" with [color=\"" + playerColor + "\"]"+username + "[/color]."; 374 if (msg.status == "ally") 375 formatted = sprintf(translate("You are now allied with %(player)s."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 376 else if (msg.status == "enemy") 377 formatted = sprintf(translate("You are now at war with %(player)s."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 378 else // (msg.status == "neutral") 379 formatted = sprintf(translate("You are now neutral with %(player)s."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 373 380 } 374 381 else if (msg.player1 == Engine.GetPlayerID()) 375 382 { 376 [username, playerColor] = getUsernameAndColor(msg.player); 377 formatted = "[color=\"" + playerColor + "\"]" + username + "[/color] is now " + status + " with you." 383 [username, playerColor] = getUsernameAndColor(msg.player1); 384 if (msg.status == "ally") 385 formatted = sprintf(translate("%(player)s is now allied with you."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 386 else if (msg.status == "enemy") 387 formatted = sprintf(translate("%(player)s is now at war with you."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 388 else // (msg.status == "neutral") 389 formatted = sprintf(translate("%(player)s is now neutral with you."), { player: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 378 390 } 379 391 else // No need for other players to know of this. 380 392 return; … … function addChatMessage(msg, playerAssignments) 393 405 if (amounts.length > 1) 394 406 { 395 407 var lastAmount = amounts.pop(); 396 amounts = amounts.join(", ") + " and " + lastAmount; 408 amounts = sprintf(translate("%(previousAmounts)s and %(lastAmount)s"), { 409 previousAmounts: amounts.join(translate(", ")), 410 lastAmount: lastAmount 411 }); 397 412 } 398 413 399 formatted = "[color=\"" + playerColor + "\"]" + username + "[/color] has sent you " + amounts + "."; 414 formatted = sprintf(translate("%(player)s has sent you %(amounts)s."), { 415 player: "[color=\"" + playerColor + "\"]" + username + "[/color]", 416 amounts: amounts 417 }); 400 418 break; 401 419 case "attack": 402 420 if (msg.player != Engine.GetPlayerID()) 403 421 return; 404 422 405 423 [username, playerColor] = getUsernameAndColor(msg.attacker); 406 formatted = "You have been attacked by [color=\"" + playerColor + "\"]" + username + "[/color]!";424 formatted = sprintf("You have been attacked by %(attacker)s!", { attacker: "[color=\"" + playerColor + "\"]" + username + "[/color]" }); 407 425 break; 408 426 case "message": 409 427 // May have been hidden by the 'team' command. … … function addChatMessage(msg, playerAssignments) 412 430 413 431 if (msg.action) 414 432 { 415 Engine.Console_Write(msg.prefix + "* " + username + " " + message); 416 formatted = msg.prefix + "* [color=\"" + playerColor + "\"]" + username + "[/color] " + message; 433 if (msg.context !== "") 434 { 435 Engine.Console_Write(sprintf(translate("(%(context)s) * %(user)s %(message)s"), { 436 context: msg.context, 437 user: username, 438 message: message 439 })); 440 formatted = sprintf(translate("(%(context)s) * %(user)s %(message)s"), { 441 context: msg.context, 442 user: "[color=\"" + playerColor + "\"]" + username + "[/color]", 443 message: message 444 }); 445 } 446 else 447 { 448 Engine.Console_Write(sprintf(translate("* %(user)s %(message)s"), { 449 user: username, 450 message: message 451 })); 452 formatted = sprintf(translate("* %(user)s %(message)s"), { 453 user: "[color=\"" + playerColor + "\"]" + username + "[/color]", 454 message: message 455 }); 456 } 417 457 } 418 458 else 419 459 { 420 Engine.Console_Write(msg.prefix + "<" + username + "> " + message); 421 formatted = msg.prefix + "<[color=\"" + playerColor + "\"]" + username + "[/color]> " + message; 460 var userTag = sprintf(translate("<%(user)s>"), { user: username }) 461 var formattedUserTag = sprintf(translate("<%(user)s>"), { user: "[color=\"" + playerColor + "\"]" + username + "[/color]" }) 462 if (msg.context !== "") 463 { 464 Engine.Console_Write(sprintf(translate("(%(context)s) %(userTag)s %(message)s"), { 465 context: msg.context, 466 userTag: userTag, 467 message: message 468 })); 469 formatted = sprintf(translate("(%(context)s) %(userTag)s %(message)s"), { 470 context: msg.context, 471 userTag: formattedUserTag, 472 message: message 473 }); 474 } 475 else 476 { 477 Engine.Console_Write(sprintf(translate("%(userTag)s %(message)s"), { userTag: userTag, message: message})); 478 formatted = sprintf(translate("%(userTag)s %(message)s"), { userTag: formattedUserTag, message: message}); 479 } 422 480 } 423 481 break; 424 482 default: 425 error( "Invalid chat message '" + uneval(msg) + "'");483 error(sprintf(translate("Invalid chat message '%(message)s'"), { message: uneval(msg) })); 426 484 return; 427 485 } 428 486 … … function parseChatCommands(msg, playerAssignments) 464 522 { 465 523 case "/all": 466 524 // Resets values that 'team' or 'enemy' may have set. 467 msg. prefix= "";525 msg.context = ""; 468 526 msg.hide = false; 469 527 recurse = true; 470 528 break; … … function parseChatCommands(msg, playerAssignments) 475 533 if (g_Players[Engine.GetPlayerID()].team != g_Players[sender].team) 476 534 msg.hide = true; 477 535 else 478 msg. prefix = "(Team) ";536 msg.context = translate("Team"); 479 537 } 480 538 else 481 539 msg.hide = true; … … function parseChatCommands(msg, playerAssignments) 488 546 if (g_Players[Engine.GetPlayerID()].team == g_Players[sender].team && sender != Engine.GetPlayerID()) 489 547 msg.hide = true; 490 548 else 491 msg. prefix = "(Enemy) ";549 msg.context = translate("Enemy"); 492 550 } 493 551 recurse = true; 494 552 break; … … function parseChatCommands(msg, playerAssignments) 508 566 var playerName = g_Players[Engine.GetPlayerID()].name; 509 567 if (matched.length && (matched == playerName || sender == Engine.GetPlayerID())) 510 568 { 511 msg. prefix = "(Private) ";569 msg.context = translate("Private"); 512 570 msg.text = trimmed.substr(matched.length + 1); 513 571 msg.hide = false; // Might override team message hiding. 514 572 return; -
binaries/data/mods/public/gui/session/selection_details.js
diff --git a/binaries/data/mods/public/gui/session/selection_details.js b/binaries/data/mods/public/gui/session/selection_details.js index c454fe0..60f2994 100644
a b function layoutSelectionMultiple() 10 10 getGUIObjectByName("detailsAreaSingle").hidden = true; 11 11 } 12 12 13 function getLocalizedResourceName(resourceCode) 14 { 15 switch(resourceCode) 16 { 17 case "food": return translate("Food"); 18 case "meat": return translate("Meat"); 19 case "metal": return translate("Metal"); 20 case "ore": return translate("Ore"); 21 case "rock": return translate("Rock"); 22 case "ruins": return translate("Ruins"); 23 case "stone": return translate("Stone"); 24 case "treasure": return translate("Treasure"); 25 case "tree": return translate("Tree"); 26 case "wood": return translate("Wood"); 27 case "fruit": return translate("Fruit"); 28 case "grain": return translate("Grain"); 29 case "fish": return translate("Fish"); 30 default: 31 warn(sprintf(translate("Internationalization: Unexpected resource type found with code ‘%(resource)s’. This resource type must be internationalized."), { resource: resourceCode })); 32 return resourceCode; // It should never get here. 33 } 34 } 35 36 function getResourceTypeDisplayName(resourceType) 37 { 38 var resourceCode = resourceType["generic"]; 39 var displayName = ""; 40 if (resourceCode == "treasure") 41 displayName = getLocalizedResourceName(resourceType["specific"]); 42 else 43 displayName = getLocalizedResourceName(resourceCode); 44 return displayName; 45 } 46 13 47 // Fills out information that most entities have 14 48 function displaySingle(entState, template) 15 49 { … … function displaySingle(entState, template) 18 52 var genericName = template.name.generic != template.name.specific? template.name.generic : ""; 19 53 // If packed, add that to the generic name (reduces template clutter) 20 54 if (genericName && template.pack && template.pack.state == "packed") 21 genericName += " -- Packed";55 genericName = sprintf(translate("%(genericName)s — Packed"), { genericName: genericName }); 22 56 var playerState = g_Players[entState.player]; 23 57 24 58 var civName = g_CivData[playerState.civ].Name; … … function displaySingle(entState, template) 30 64 // Indicate disconnected players by prefixing their name 31 65 if (g_Players[entState.player].offline) 32 66 { 33 playerName = "[OFFLINE] " + playerName;67 playerName = sprintf(translate("[OFFLINE] %(player)s"), { player: playerName }); 34 68 } 35 69 36 70 // Rank 37 71 if (entState.identity && entState.identity.rank && entState.identity.classes) 38 { 39 getGUIObjectByName("rankIcon").tooltip = entState.identity.rank + " Rank";40 getGUIObjectByName("rankIcon").sprite = getRankIconSprite(entState); 41 getGUIObjectByName("rankIcon").hidden = false; 42 } 72 { 73 getGUIObjectByName("rankIcon").tooltip = sprintf(translate("%(rank)s Rank"), { rank: entState.identity.rank }); 74 getGUIObjectByName("rankIcon").sprite = getRankIconSprite(entState); 75 getGUIObjectByName("rankIcon").hidden = false; 76 } 43 77 else 44 78 { 45 79 getGUIObjectByName("rankIcon").hidden = true; 46 getGUIObjectByName("rankIcon").tooltip = ""; 47 } 48 49 // Hitpoints 50 if (entState.hitpoints) 80 getGUIObjectByName("rankIcon").tooltip = ""; 81 } 82 83 // Hitpoints 84 if (entState.hitpoints) 51 85 { 52 86 var unitHealthBar = getGUIObjectByName("healthBar"); 53 87 var healthSize = unitHealthBar.size; 54 88 healthSize.rright = 100*Math.max(0, Math.min(1, entState.hitpoints / entState.maxHitpoints)); 55 89 unitHealthBar.size = healthSize; 56 90 57 var hitpoints = Math.ceil(entState.hitpoints) + " / " + entState.maxHitpoints; 58 getGUIObjectByName("healthStats").caption = hitpoints; 91 getGUIObjectByName("healthStats").caption = sprintf(translate("%(hitpoints)s / %(maxHitpoints)s"), { 92 hitpoints: Math.ceil(entState.hitpoints), 93 maxHitpoints: entState.maxHitpoints 94 }); 59 95 getGUIObjectByName("healthSection").hidden = false; 60 96 } 61 97 else 62 98 { 63 getGUIObjectByName("healthSection").hidden = true; 64 } 65 66 // TODO: Stamina 67 var player = Engine.GetPlayerID(); 99 getGUIObjectByName("healthSection").hidden = true; 100 } 101 102 // TODO: Stamina 103 var player = Engine.GetPlayerID(); 68 104 if (entState.stamina && (entState.player == player || g_DevSettings.controlAll)) 69 {70 105 getGUIObjectByName("staminaSection").hidden = false; 71 }72 106 else 73 {74 107 getGUIObjectByName("staminaSection").hidden = true; 75 }76 108 77 109 // Experience 78 110 if (entState.promotion) 79 111 { 80 112 var experienceBar = getGUIObjectByName("experienceBar"); 81 113 var experienceSize = experienceBar.size; 82 experienceSize.rtop = 100 - (100 * Math.max(0, Math.min(1, 1.0 * +entState.promotion.curr / +entState.promotion.req))); 83 experienceBar.size = experienceSize; 84 85 var experience = "[font=\"serif-bold-13\"]Experience: [/font]" + Math.floor(entState.promotion.curr); 86 if (entState.promotion.curr < entState.promotion.req) 87 experience += " / " + entState.promotion.req; 88 getGUIObjectByName("experience").tooltip = experience; 114 experienceSize.rtop = 100 - (100 * Math.max(0, Math.min(1, 1.0 * +entState.promotion.curr / +entState.promotion.req))); 115 experienceBar.size = experienceSize; 116 117 var experience = "[font=\"serif-bold-13\"]Experience: [/font]" + Math.floor(entState.promotion.curr); 118 if (entState.promotion.curr < entState.promotion.req) 119 getGUIObjectByName("experience").tooltip = sprintf(translate("%(experience)s %(current)s / %(required)s"), { 120 experience: "[font=\"serif-bold-13\"]" + translate("Experience:") + "[/font]", 121 current: Math.floor(entState.promotion.curr), 122 required: entState.promotion.req 123 }); 124 else 125 getGUIObjectByName("experience").tooltip = sprintf(translate("%(experience)s %(current)s"), { 126 experience: "[font=\"serif-bold-13\"]" + translate("Experience:") + "[/font]", 127 current: Math.floor(entState.promotion.curr) 128 }); 89 129 getGUIObjectByName("experience").hidden = false; 90 130 } 91 131 else … … function displaySingle(entState, template) 96 136 // Resource stats 97 137 if (entState.resourceSupply) 98 138 { 99 var resources = entState.resourceSupply.isInfinite ? "\u221E" : // Infinity symbol 100 Math.ceil(+entState.resourceSupply.amount) + " / " + entState.resourceSupply.max; 101 var resourceType = entState.resourceSupply.type["generic"]; 102 if (resourceType == "treasure") 103 resourceType = entState.resourceSupply.type["specific"]; 139 var resources = entState.resourceSupply.isInfinite ? translate("∞") : // Infinity symbol 140 sprintf(translate("%(amount)s / %(max)s"), { amount: Math.ceil(+entState.resourceSupply.amount), max: entState.resourceSupply.max }); 141 var resourceType = getResourceTypeDisplayName(entState.resourceSupply.type); 104 142 105 143 var unitResourceBar = getGUIObjectByName("resourceBar"); 106 144 var resourceSize = unitResourceBar.size; … … function displaySingle(entState, template) 108 146 resourceSize.rright = entState.resourceSupply.isInfinite ? 100 : 109 147 100 * Math.max(0, Math.min(1, +entState.resourceSupply.amount / +entState.resourceSupply.max)); 110 148 unitResourceBar.size = resourceSize; 111 getGUIObjectByName("resourceLabel").caption = toTitleCase(resourceType) + ":";149 getGUIObjectByName("resourceLabel").caption = sprintf(translate("%(resource)s:"), { resource: resourceType }); 112 150 getGUIObjectByName("resourceStats").caption = resources; 113 151 114 152 if (entState.hitpoints) … … function displaySingle(entState, template) 120 158 } 121 159 else 122 160 { 123 getGUIObjectByName("resourceSection").hidden = true; 124 } 125 126 // Resource carrying 161 getGUIObjectByName("resourceSection").hidden = true; 162 } 163 164 // Resource carrying 127 165 if (entState.resourceCarrying && entState.resourceCarrying.length) 128 166 { 129 167 // We should only be carrying one resource type at once, so just display the first … … function displaySingle(entState, template) 132 170 getGUIObjectByName("resourceCarryingIcon").hidden = false; 133 171 getGUIObjectByName("resourceCarryingText").hidden = false; 134 172 getGUIObjectByName("resourceCarryingIcon").sprite = "stretched:session/icons/resources/"+carried.type+".png"; 135 getGUIObjectByName("resourceCarryingText").caption = carried.amount + " / " + carried.max;173 getGUIObjectByName("resourceCarryingText").caption = sprintf(translate("%(amount)s / %(max)s"), { amount: carried.amount, max: carried.max }); 136 174 getGUIObjectByName("resourceCarryingIcon").tooltip = ""; 137 175 } 138 176 // Use the same indicators for traders … … function displaySingle(entState, template) 147 185 if (entState.trader.goods.amount.market2Gain) 148 186 totalGain += entState.trader.goods.amount.market2Gain; 149 187 getGUIObjectByName("resourceCarryingText").caption = totalGain; 150 getGUIObjectByName("resourceCarryingIcon").tooltip = "Gain: " + getTradingTooltip(entState.trader.goods.amount);151 } 152 // And for number of workers 153 else if (entState.foundation) 154 { 155 getGUIObjectByName("resourceCarryingIcon").hidden = false; 156 getGUIObjectByName("resourceCarryingText").hidden = false; 188 getGUIObjectByName("resourceCarryingIcon").tooltip = sprintf(translate("Gain: %(amount)s"), { amount: getTradingTooltip(entState.trader.goods.amount) }); 189 } 190 // And for number of workers 191 else if (entState.foundation) 192 { 193 getGUIObjectByName("resourceCarryingIcon").hidden = false; 194 getGUIObjectByName("resourceCarryingText").hidden = false; 157 195 getGUIObjectByName("resourceCarryingIcon").sprite = "stretched:session/icons/repair.png"; 158 196 getGUIObjectByName("resourceCarryingText").caption = entState.foundation.numBuilders + " "; 159 getGUIObjectByName("resourceCarryingIcon").tooltip = "Number of builders";160 } 161 else if (entState.resourceSupply && (!entState.resourceSupply.killBeforeGather || !entState.hitpoints)) 162 { 163 getGUIObjectByName("resourceCarryingIcon").hidden = false; 164 getGUIObjectByName("resourceCarryingText").hidden = false; 197 getGUIObjectByName("resourceCarryingIcon").tooltip = translate("Number of builders"); 198 } 199 else if (entState.resourceSupply && (!entState.resourceSupply.killBeforeGather || !entState.hitpoints)) 200 { 201 getGUIObjectByName("resourceCarryingIcon").hidden = false; 202 getGUIObjectByName("resourceCarryingText").hidden = false; 165 203 getGUIObjectByName("resourceCarryingIcon").sprite = "stretched:session/icons/repair.png"; 166 getGUIObjectByName("resourceCarryingText").caption = entState.resourceSupply.gatherers.length + " / " + entState.resourceSupply.maxGatherers+ " ";167 getGUIObjectByName("resourceCarryingIcon").tooltip = "Current/max gatherers";168 } 169 else 204 getGUIObjectByName("resourceCarryingText").caption = sprintf(translate("%(amount)s / %(max)s"), { amount: entState.resourceSupply.gatherers.length, max: entState.resourceSupply.maxGatherers }) + " "; 205 getGUIObjectByName("resourceCarryingIcon").tooltip = translate("Current/max gatherers"); 206 } 207 else 170 208 { 171 209 getGUIObjectByName("resourceCarryingIcon").hidden = true; 172 210 getGUIObjectByName("resourceCarryingText").hidden = true; … … function displaySingle(entState, template) 174 212 175 213 // Set Player details 176 214 getGUIObjectByName("specific").caption = specificName; 177 getGUIObjectByName("player").caption = playerName; 178 getGUIObjectByName("playerColorBackground").sprite = "colour: " + playerColor; 179 180 if (genericName) 181 { 182 getGUIObjectByName("generic").caption = "(" + genericName + ")";215 getGUIObjectByName("player").caption = playerName; 216 getGUIObjectByName("playerColorBackground").sprite = "colour: " + playerColor; 217 218 if (genericName) 219 { 220 getGUIObjectByName("generic").caption = sprintf(translate("(%(genericName)s)"), { genericName: genericName }); 183 221 } 184 222 else 185 223 { … … function displaySingle(entState, template) 209 247 getGUIObjectByName("icon").sprite = "bkFillBlack"; 210 248 } 211 249 250 var armorLabel = "[font=\"serif-bold-13\"]" + translate("Armor:") + "[/font]" 251 var armorString = sprintf(translate("%(label)s %(details)s"), { label: armorLabel, details: armorTypeDetails(entState.armour) }); 252 212 253 // Attack and Armor 213 var type = "";214 var attack = "[font=\"serif-bold-13\"]"+type+"Attack:[/font] " + damageTypeDetails(entState.attack);215 254 if (entState.attack) 216 255 { 217 type = entState.attack.type + " "; 218 219 // Show max attack range if ranged attack, also convert to tiles (4m per tile) 256 var attack; 257 var label = "[font=\"serif-bold-13\"]" + getAttackTypeLabel(entState.attack.type) + "[/font]" 220 258 if (entState.attack.type == "Ranged") 221 259 { 222 var realRange = entState.attack.elevationAdaptedRange; 223 var range = entState.attack.maxRange; 224 attack += ", [font=\"serif-bold-13\"]Range:[/font] " + 225 Math.round(range/4); 226 227 if (Math.round((realRange - range)/4) > 0) 228 { 229 attack += " (+" + Math.round((realRange - range)/4) + ")"; 230 } 231 else if (Math.round((realRange - range)/4) < 0) 232 { 233 attack += " (" + Math.round((realRange - range)/4) + ")"; 234 } // don't show when it's 0 235 236 } 237 } 238 239 getGUIObjectByName("attackAndArmorStats").tooltip = attack + "\n[font=\"serif-bold-13\"]Armor:[/font] " + armorTypeDetails(entState.armour); 240 260 // Show max attack range if ranged attack, also convert to tiles (4m per tile) 261 var realRange = entState.attack.elevationAdaptedRange; 262 var range = entState.attack.maxRange; 263 var rangeLabel = "[font=\"serif-bold-13\"]" + translate("Range:") + "[/font]" 264 var relativeRange = Math.round((realRange - range)/4); 265 266 if (relativeRange > 0) 267 attack = sprintf(translate("%(label)s %(details)s, %(rangeLabel)s %(range)s (%(relative)s)"), { 268 label: label, 269 details: damageTypeDetails(entState.attack), 270 rangeLabel: rangeLabel, 271 range: Math.round(range/4), 272 relative: "+" + relativeRange 273 }); 274 else if (relativeRange < 0) 275 attack = sprintf(translate("%(label)s %(details)s, %(rangeLabel)s %(range)s"), { 276 label: label, 277 details: damageTypeDetails(entState.attack), 278 rangeLabel: rangeLabel, 279 range: Math.round(range/4), 280 relative: relativeRange 281 }); 282 else // don't show when it's 0 283 attack = sprintf(translate("%(label)s %(details)s, %(rangeLabel)s %(range)s"), { 284 label: label, 285 details: damageTypeDetails(entState.attack), 286 rangeLabel: rangeLabel, 287 range: Math.round(range/4) 288 }); 289 } 290 else 291 { 292 attack = sprintf(translate("%(label)s %(details)s"), { 293 label: label, 294 details: damageTypeDetails(entState.attack) 295 }); 296 } 297 getGUIObjectByName("attackAndArmorStats").tooltip = attack + "\n" + armorString; 298 } 299 else 300 { 301 getGUIObjectByName("attackAndArmorStats").tooltip = armorString; 302 } 303 241 304 // Icon Tooltip 242 305 var iconTooltip = ""; 243 306 … … function displayMultiple(selection, template) 274 337 } 275 338 276 339 if (averageHealth > 0) 277 { 278 var unitHealthBar = getGUIObjectByName("healthBarMultiple"); 279 var healthSize = unitHealthBar.size; 280 healthSize.rtop = 100-100*Math.max(0, Math.min(1, averageHealth / maxHealth)); 281 unitHealthBar.size = healthSize; 340 { 341 var unitHealthBar = getGUIObjectByName("healthBarMultiple"); 342 var healthSize = unitHealthBar.size; 343 healthSize.rtop = 100-100*Math.max(0, Math.min(1, averageHealth / maxHealth)); 344 unitHealthBar.size = healthSize; 282 345 283 var hitpoints = "[font=\"serif-bold-13\"]Hitpoints [/font]" + averageHealth + " / " + maxHealth; 346 var hitpointsLabel = "[font=\"serif-bold-13\"]" + translate("Hitpoints:") + "[/font]" 347 var hitpoints = sprintf(translate("%(label)s %(current)s / %(max)s"), { label: hitpointsLabel, current: averageHealth, max: maxHealth }); 284 348 var healthMultiple = getGUIObjectByName("healthMultiple"); 285 349 healthMultiple.tooltip = hitpoints; 286 350 healthMultiple.hidden = false; 287 351 } 288 352 else 289 353 { 290 getGUIObjectByName("healthMultiple").hidden = true; 291 } 292 293 // TODO: Stamina 294 // getGUIObjectByName("staminaBarMultiple"); 354 getGUIObjectByName("healthMultiple").hidden = true; 355 } 356 357 // TODO: Stamina 358 // getGUIObjectByName("staminaBarMultiple"); 295 359 296 360 getGUIObjectByName("numberOfUnits").caption = selection.length; 297 361 … … function updateSelectionDetails() 307 371 var detailsPanel = getGUIObjectByName("selectionDetails"); 308 372 var commandsPanel = getGUIObjectByName("unitCommands"); 309 373 310 g_Selection.update(); 311 var selection = g_Selection.toList(); 312 313 if (selection.length == 0) 314 { 374 g_Selection.update(); 375 var selection = g_Selection.toList(); 376 377 if (selection.length == 0) 378 { 315 379 getGUIObjectByName("detailsAreaMultiple").hidden = true; 316 getGUIObjectByName("detailsAreaSingle").hidden = true; 317 hideUnitCommands(); 318 319 supplementalDetailsPanel.hidden = true; 320 detailsPanel.hidden = true; 380 getGUIObjectByName("detailsAreaSingle").hidden = true; 381 hideUnitCommands(); 382 383 supplementalDetailsPanel.hidden = true; 384 detailsPanel.hidden = true; 321 385 commandsPanel.hidden = true; 322 386 return; 323 387 } -
binaries/data/mods/public/gui/session/session.js
diff --git a/binaries/data/mods/public/gui/session/session.js b/binaries/data/mods/public/gui/session/session.js index 9f8349a..a09d08b 100644
a b var g_CivData = {}; 9 9 var g_GameSpeeds = {}; 10 10 var g_CurrentSpeed; 11 11 12 var g_PlayerAssignments = { "local": { "name": "You", "player": 1 } };12 var g_PlayerAssignments = { "local": { "name": translate("You"), "player": 1 } }; 13 13 14 14 // Cache dev-mode settings that are frequently or widely used 15 15 var g_DevSettings = { … … function GetEntityState(entId) 61 61 62 62 // Cache TemplateData 63 63 var g_TemplateData = {}; // {id:template} 64 var g_TemplateDataWithoutLocalization = {}; 64 65 65 66 66 67 function GetTemplateData(templateName) … … function GetTemplateData(templateName) 68 69 if (!(templateName in g_TemplateData)) 69 70 { 70 71 var template = Engine.GuiInterfaceCall("GetTemplateData", templateName); 72 translateObjectKeys(template, ["specific", "generic", "tooltip"]); 71 73 g_TemplateData[templateName] = template; 72 74 } 73 75 74 76 return g_TemplateData[templateName]; 75 77 } 76 78 79 function GetTemplateDataWithoutLocalization(templateName) 80 { 81 if (!(templateName in g_TemplateDataWithoutLocalization)) 82 { 83 var template = Engine.GuiInterfaceCall("GetTemplateData", templateName); 84 g_TemplateDataWithoutLocalization[templateName] = template; 85 } 86 87 return g_TemplateDataWithoutLocalization[templateName]; 88 } 89 77 90 // Cache TechnologyData 78 91 var g_TechnologyData = {}; // {id:template} 79 92 … … function GetTechnologyData(technologyName) 82 95 if (!(technologyName in g_TechnologyData)) 83 96 { 84 97 var template = Engine.GuiInterfaceCall("GetTechnologyData", technologyName); 98 translateObjectKeys(template, ["specific", "generic", "description", "tooltip", "requirementsTooltip"]); 85 99 g_TechnologyData[technologyName] = template; 86 100 } 87 101 … … function init(initData, hotloadData) 112 126 113 127 // Cache civ data 114 128 g_CivData = loadCivData(); 115 g_CivData["gaia"] = { "Code": "gaia", "Name": "Gaia"};129 g_CivData["gaia"] = { "Code": "gaia", "Name": translate("Gaia") }; 116 130 117 131 g_GameSpeeds = initGameSpeeds(); 118 132 g_CurrentSpeed = Engine.GetSimRate(); … … function leaveGame() 218 232 var gameResult; 219 233 if (g_Disconnected) 220 234 { 221 gameResult = "You have been disconnected."235 gameResult = translate("You have been disconnected."); 222 236 } 223 237 else if (playerState.state == "won") 224 238 { 225 gameResult = "You have won the battle!";239 gameResult = translate("You have won the battle!"); 226 240 } 227 241 else if (playerState.state == "defeated") 228 242 { 229 gameResult = "You have been defeated...";243 gameResult = translate("You have been defeated..."); 230 244 } 231 245 else // "active" 232 246 { 233 gameResult = "You have abandoned the game.";247 gameResult = translate("You have abandoned the game."); 234 248 235 249 // Tell other players that we have given up and been defeated 236 250 Engine.PostNetworkCommand({ … … function checkPlayerState() 359 373 if (Engine.IsAtlasRunning()) 360 374 { 361 375 // If we're in Atlas, we can't leave the game 362 var btCaptions = [ "OK"];376 var btCaptions = [translate("OK")]; 363 377 var btCode = [null]; 364 var message = "Press OK to continue";378 var message = translate("Press OK to continue"); 365 379 } 366 380 else 367 381 { 368 var btCaptions = [ "Yes", "No"];382 var btCaptions = [translate("Yes"), translate("No")]; 369 383 var btCode = [leaveGame, null]; 370 var message = "Do you want to quit?";384 var message = translate("Do you want to quit?"); 371 385 } 372 messageBox(400, 200, message, "DEFEATED!", 0, btCaptions, btCode);386 messageBox(400, 200, message, translate("DEFEATED!"), 0, btCaptions, btCode); 373 387 } 374 388 else if (playerState.state == "won") 375 389 { … … function checkPlayerState() 385 399 if (Engine.IsAtlasRunning()) 386 400 { 387 401 // If we're in Atlas, we can't leave the game 388 var btCaptions = [ "OK"];402 var btCaptions = [translate("OK")]; 389 403 var btCode = [null]; 390 var message = "Press OK to continue";404 var message = translate("Press OK to continue"); 391 405 } 392 406 else 393 407 { 394 var btCaptions = [ "Yes", "No"];408 var btCaptions = [translate("Yes"), translate("No")]; 395 409 var btCode = [leaveGame, null]; 396 var message = "Do you want to quit?";410 var message = translate("Do you want to quit?"); 397 411 } 398 messageBox(400, 200, message, "VICTORIOUS!", 0, btCaptions, btCode);412 messageBox(400, 200, message, translate("VICTORIOUS!"), 0, btCaptions, btCode); 399 413 } 400 414 } 401 415 } … … function updateHero() 476 490 477 491 // Setup tooltip 478 492 var tooltip = "[font=\"serif-bold-16\"]" + template.name.specific + "[/font]"; 479 tooltip += "\n[font=\"serif-bold-13\"]Health:[/font] " + heroState.hitpoints + "/" + heroState.maxHitpoints; 480 tooltip += "\n[font=\"serif-bold-13\"]" + (heroState.attack ? heroState.attack.type + " " : "") 481 + "Attack:[/font] " + damageTypeDetails(heroState.attack); 482 // Show max attack range if ranged attack, also convert to tiles (4m per tile) 493 var healthLabel = "[font=\"serif-bold-13\"]" + translate("Health:") + "[/font]"; 494 tooltip += "\n" + sprintf(translate("%(label)s %(current)s / %(max)s"), { label: healthLabel, current: heroState.hitpoints, max: heroState.maxHitpoints }); 495 var attackLabel = "[font=\"serif-bold-13\"]" + getAttackTypeLabel(heroState.attack.type) + "[/font]"; 483 496 if (heroState.attack && heroState.attack.type == "Ranged") 484 tooltip += ", [font=\"serif-bold-13\"]Range:[/font] " + Math.round(heroState.attack.maxRange/4); 497 // Show max attack range if ranged attack, also convert to tiles (4m per tile) 498 tooltip += "\n" + sprintf( 499 translate("%(attackLabel)s %(details)s, %(rangeLabel)s %(range)s"), 500 { 501 attackLabel: attackLabel, 502 details: damageTypeDetails(heroState.attack), 503 rangeLabel: "[font=\"serif-bold-13\"]" + translate("Range:") + "[/font]", 504 range: Math.round(heroState.attack.maxRange/4) 505 } 506 ); 507 else 508 tooltip += "\n" + sprintf(translate("%(label)s %(details)s"), { label: attackLabel, details: damageTypeDetails(heroState.armour) }); 485 509 486 tooltip += "\n[font=\"serif-bold-13\"]Armor:[/font] " + damageTypeDetails(heroState.armour); 510 var armorLabel = "[font=\"serif-bold-13\"]" + translate("Armor:") + "[/font]"; 511 tooltip += "\n" + sprintf(translate("%(label)s %(details)s"), { label: armorLabel, details: damageTypeDetails(heroState.attack) }); 487 512 tooltip += "\n" + template.tooltip; 488 513 489 514 heroButton.tooltip = tooltip; … … function updateResearchDisplay() 629 654 function updateTimeElapsedCounter() 630 655 { 631 656 var simState = GetSimState(); 632 var speed = g_CurrentSpeed != 1.0 ? " (" + g_CurrentSpeed + "x)" : "";633 657 var timeElapsedCounter = getGUIObjectByName("timeElapsedCounter"); 634 timeElapsedCounter.caption = timeToString(simState.timeElapsed) + speed; 658 if (g_CurrentSpeed != 1.0) 659 timeElapsedCounter.caption = sprintf(translate("%(time)s (%(speed)sx)"), { time: timeToString(simState.timeElapsed), speed: Engine.formatDecimalNumberIntoString(g_CurrentSpeed) }); 660 else 661 timeElapsedCounter.caption = timeToString(simState.timeElapsed); 635 662 } 636 663 637 664 // Toggles the display of status bars for all of the player's entities. … … function playRandomAmbient(type) 671 698 break; 672 699 673 700 default: 674 Engine.Console_Write( "Unrecognized ambient type: " + type);701 Engine.Console_Write(sprintf(translate("Unrecognized ambient type: %(ambientType)s"), { ambientType: type })); 675 702 break; 676 703 } 677 704 } … … function stopAmbient() 685 712 currentAmbient = null; 686 713 } 687 714 } 715 716 function getBuildString() 717 { 718 return sprintf(translate("Build: %(buildDate)s (%(revision)s)"), { buildDate: Engine.GetBuildTimestamp(0), revision: Engine.GetBuildTimestamp(2) }); 719 } 720 721 function showTimeWarpMessageBox() 722 { 723 messageBox(500, 250, translate("Note: time warp mode is a developer option, and not intended for use over long periods of time. Using it incorrectly may cause the game to run out of memory or crash."), translate("Time warp mode"), 2); 724 } -
binaries/data/mods/public/gui/session/session.xml
diff --git a/binaries/data/mods/public/gui/session/session.xml b/binaries/data/mods/public/gui/session/session.xml index d5b3353..6d1c1d2 100644
a b 251 251 toggleDeveloperOverlay(); 252 252 </action> 253 253 254 <object size="0 0 100%-18 16" type="text" style="devCommandsText">Control all units</object> 254 <object size="0 0 100%-18 16" type="text" style="devCommandsText"> 255 <translatableAttribute id="caption">Control all units</translatableAttribute> 256 </object> 255 257 <object size="100%-16 0 100% 16" type="checkbox" name="devControlAll" style="StoneCrossBox"> 256 258 <action on="Press"> 257 259 g_DevSettings.controlAll = this.checked; … … 259 261 </action> 260 262 </object> 261 263 262 <object size="0 16 100%-18 32" type="text" style="devCommandsText">Change perspective</object> 264 <object size="0 16 100%-18 32" type="text" style="devCommandsText"> 265 <translatableAttribute id="caption">Change perspective</translatableAttribute> 266 </object> 263 267 <object size="100%-16 16 100% 32" type="checkbox" style="StoneCrossBox"> 264 268 <action on="Press">getGUIObjectByName("viewPlayer").hidden = !this.checked;</action> 265 269 </object> 266 270 267 <object size="0 32 100%-18 48" type="text" style="devCommandsText">Display selection state</object> 271 <object size="0 32 100%-18 48" type="text" style="devCommandsText"> 272 <translatableAttribute id="caption">Display selection state</translatableAttribute> 273 </object> 268 274 <object size="100%-16 32 100% 48" type="checkbox" name="devDisplayState" style="StoneCrossBox"/> 269 275 270 <object size="0 48 100%-18 64" type="text" style="devCommandsText">Pathfinder overlay</object> 276 <object size="0 48 100%-18 64" type="text" style="devCommandsText"> 277 <translatableAttribute id="caption">Pathfinder overlay</translatableAttribute> 278 </object> 271 279 <object size="100%-16 48 100% 64" type="checkbox" style="StoneCrossBox"> 272 280 <action on="Press">Engine.GuiInterfaceCall("SetPathfinderDebugOverlay", this.checked);</action> 273 281 </object> 274 282 275 <object size="0 64 100%-18 80" type="text" style="devCommandsText">Obstruction overlay</object> 283 <object size="0 64 100%-18 80" type="text" style="devCommandsText"> 284 <translatableAttribute id="caption">Obstruction overlay</translatableAttribute> 285 </object> 276 286 <object size="100%-16 64 100% 80" type="checkbox" style="StoneCrossBox"> 277 287 <action on="Press">Engine.GuiInterfaceCall("SetObstructionDebugOverlay", this.checked);</action> 278 288 </object> 279 289 280 <object size="0 80 100%-18 96" type="text" style="devCommandsText">Unit motion overlay</object> 290 <object size="0 80 100%-18 96" type="text" style="devCommandsText"> 291 <translatableAttribute id="caption">Unit motion overlay</translatableAttribute> 292 </object> 281 293 <object size="100%-16 80 100% 96" type="checkbox" style="StoneCrossBox"> 282 294 <action on="Press">g_Selection.SetMotionDebugOverlay(this.checked);</action> 283 295 </object> 284 296 285 <object size="0 96 100%-18 112" type="text" style="devCommandsText">Range overlay</object> 297 <object size="0 96 100%-18 112" type="text" style="devCommandsText"> 298 <translatableAttribute id="caption">Range overlay</translatableAttribute> 299 </object> 286 300 <object size="100%-16 96 100% 112" type="checkbox" style="StoneCrossBox"> 287 301 <action on="Press">Engine.GuiInterfaceCall("SetRangeDebugOverlay", this.checked);</action> 288 302 </object> 289 303 290 <object size="0 112 100%-18 128" type="text" style="devCommandsText">Bounding box overlay</object> 304 <object size="0 112 100%-18 128" type="text" style="devCommandsText"> 305 <translatableAttribute id="caption">Bounding box overlay</translatableAttribute> 306 </object> 291 307 <object size="100%-16 112 100% 128" type="checkbox" style="StoneCrossBox"> 292 308 <action on="Press">Engine.SetBoundingBoxDebugOverlay(this.checked);</action> 293 309 </object> 294 310 295 <object size="0 128 100%-18 144" type="text" style="devCommandsText">Restrict camera</object> 311 <object size="0 128 100%-18 144" type="text" style="devCommandsText"> 312 <translatableAttribute id="caption">Restrict camera</translatableAttribute> 313 </object> 296 314 <object size="100%-16 128 100% 144" type="checkbox" style="StoneCrossBox" checked="true"> 297 315 <action on="Press">Engine.GameView_SetConstrainCameraEnabled(this.checked);</action> 298 316 </object> 299 317 300 <object size="0 144 100%-18 160" type="text" style="devCommandsText">Reveal map</object> 318 <object size="0 144 100%-18 160" type="text" style="devCommandsText"> 319 <translatableAttribute id="caption">Reveal map</translatableAttribute> 320 </object> 301 321 <object size="100%-16 144 100% 160" type="checkbox" name="devCommandsRevealMap" style="StoneCrossBox"> 302 322 <action on="Press">Engine.PostNetworkCommand({"type": "reveal-map", "enable": this.checked});</action> 303 323 </object> 304 324 305 <object size="0 160 100%-18 176" type="text" style="devCommandsText">Enable time warp</object> 325 <object size="0 160 100%-18 176" type="text" style="devCommandsText"> 326 <translatableAttribute id="caption">Enable time warp</translatableAttribute> 327 </object> 306 328 <object size="100%-16 160 100% 176" type="checkbox" name="devTimeWarp" style="StoneCrossBox"> 307 329 <action on="Press"> 308 330 if (this.checked) 309 messageBox(500, 250, "Note: time warp mode is a developer option, and not intended\nfor use over long periods of time. Using it incorrectly may\ncause the game to run out of memory or crash.", "Time warp mode", 2);331 showTimeWarpMessageBox(); 310 332 Engine.EnableTimeWarpRecording(this.checked ? 10 : 0);</action> 311 333 </object> 312 334 313 <object size="0 176 100%-18 192" type="text" style="devCommandsText">Promote selected units</object> 335 <object size="0 176 100%-18 192" type="text" style="devCommandsText"> 336 <translatableAttribute id="caption">Promote selected units</translatableAttribute> 337 </object> 314 338 <object size="100%-16 176 100% 192" type="button" style="StoneCrossBox"> 315 339 <action on="Press">Engine.PostNetworkCommand({"type": "promote", "entities": g_Selection.toList()});</action> 316 340 </object> … … 335 359 z="0" 336 360 > 337 361 <object size="0 0 100% 100%" type="image" sprite="devCommandsBackground" ghost="true" z="0"/> 338 <object size="50%-128 50%-20 50%+128 50%+20" type="text" style="PauseText" ghost="true" z="0">Game Paused</object> 339 <object size="50%-128 50%+20 50%+128 50%+30" type="text" style="PauseMessageText" ghost="true" z="0">Click to Resume Game</object> 362 <object size="50%-128 50%-20 50%+128 50%+20" type="text" style="PauseText" ghost="true" z="0"> 363 <translatableAttribute id="caption">Game Paused</translatableAttribute> 364 </object> 365 <object size="50%-128 50%+20 50%+128 50%+30" type="text" style="PauseMessageText" ghost="true" z="0"> 366 <translatableAttribute id="caption">Click to Resume Game</translatableAttribute> 367 </object> 340 368 <action on="Press">togglePause();</action> 341 369 </object> 342 370 … … 363 391 </object> 364 392 365 393 <object size="16 100%-40 30%+16 100%-12" type="button" style="StoneButton"> 366 Send367 <action on="Press">submitChatInput();</action>394 <translatableAttribute id="caption">Send</translatableAttribute> 395 <action on="Press">submitChatInput();</action> 368 396 </object> 369 397 370 398 <object size="30%+24 100%-40 60%+24 100%-12" type="button" style="StoneButton"> 371 Cancel372 <action on="Press">closeChat();</action>399 <translatableAttribute id="caption">Cancel</translatableAttribute> 400 <action on="Press">closeChat();</action> 373 401 </object> 374 402 <object name="toggleTeamChat" size="60%+32 100%-34 60%+48 100%-6" type="checkbox" style="StoneCrossBox"/> 375 403 <object size="60%+48 100%-40 100% 100%-12" type="text" style="LeftLabelText"> … … 386 414 hidden="true" 387 415 sprite="StoneDialog" 388 416 > 389 <object type="text" style="TitleText" size="50%-96 -16 50%+96 16">Diplomacy</object> 417 <object type="text" style="TitleText" size="50%-96 -16 50%+96 16"> 418 <translatableAttribute id="caption">Diplomacy</translatableAttribute> 419 </object> 390 420 391 421 <object name="diplomacyHeader" size="32 32 100%-32 64"> 392 <object name="diplomacyHeaderName" size="0 0 150 100%" type="text" style="chatPanel" ghost="true" caption="Name"/> 393 <object name="diplomacyHeaderCiv" size="150 0 250 100%" type="text" style="chatPanel" ghost="true" caption="Civilization"/> 394 <object name="diplomacyHeaderTeam" size="250 0 300 100%" type="text" style="chatPanel" ghost="true" caption="Team"/> 395 <object name="diplomacyHeaderTheirs" size="300 0 360 100%" type="text" style="chatPanel" ghost="true" caption="Theirs"/> 396 <object name="diplomacyHeaderAlly" size="100%-180 0 100%-160 100%" type="text" style="chatPanel" caption="A" tooltip="Ally" tooltip_style="sessionToolTipBold"/> 397 <object name="diplomacyHeaderNeutral" size="100%-160 0 100%-140 100%" type="text" style="chatPanel" caption="N" tooltip="Neutral" tooltip_style="sessionToolTipBold"/> 398 <object name="diplomacyHeaderEnemy" size="100%-140 0 100%-120 100%" type="text" style="chatPanel" caption="E" tooltip="Enemy" tooltip_style="sessionToolTipBold"/> 399 <object name="diplomacyHeaderTribute" size="100%-110 0 100% 100%" type="text" style="chatPanel" caption="Tribute"/> 422 <object name="diplomacyHeaderName" size="0 0 150 100%" type="text" style="chatPanel" ghost="true"> 423 <translatableAttribute id="caption">Name</translatableAttribute> 424 </object> 425 <object name="diplomacyHeaderCiv" size="150 0 250 100%" type="text" style="chatPanel" ghost="true"> 426 <translatableAttribute id="caption">Civilization</translatableAttribute> 427 </object> 428 <object name="diplomacyHeaderTeam" size="250 0 300 100%" type="text" style="chatPanel" ghost="true"> 429 <translatableAttribute id="caption">Team</translatableAttribute> 430 </object> 431 <object name="diplomacyHeaderTheirs" size="300 0 360 100%" type="text" style="chatPanel" ghost="true"> 432 <translatableAttribute id="caption">Theirs</translatableAttribute> 433 </object> 434 <object name="diplomacyHeaderAlly" size="100%-180 0 100%-160 100%" type="text" style="chatPanel" tooltip_style="sessionToolTipBold"> 435 <translatableAttribute id="caption">A</translatableAttribute> 436 <translatableAttribute id="tooltip">Ally</translatableAttribute> 437 </object> 438 <object name="diplomacyHeaderNeutral" size="100%-160 0 100%-140 100%" type="text" style="chatPanel" tooltip_style="sessionToolTipBold"> 439 <translatableAttribute id="caption">N</translatableAttribute> 440 <translatableAttribute id="tooltip">Neutral</translatableAttribute> 441 </object> 442 <object name="diplomacyHeaderEnemy" size="100%-140 0 100%-120 100%" type="text" style="chatPanel" tooltip_style="sessionToolTipBold"> 443 <translatableAttribute id="caption">E</translatableAttribute> 444 <translatableAttribute id="tooltip">Enemy</translatableAttribute> 445 </object> 446 <object name="diplomacyHeaderTribute" size="100%-110 0 100% 100%" type="text" style="chatPanel"> 447 <translatableAttribute id="caption">Tribute</translatableAttribute> 448 </object> 400 449 </object> 401 450 402 451 <object size="32 64 100%-32 384"> … … 445 494 hidden="true" 446 495 z="200" 447 496 > 448 <object type="text" style="TitleText" size="50%-96 -16 50%+96 16">Settings</object> 497 <object type="text" style="TitleText" size="50%-96 -16 50%+96 16"> 498 <translatableAttribute id="caption">Settings</translatableAttribute> 499 </object> 449 500 450 501 <object style="TranslucentPanelThinBorder" 451 502 type="image" 452 503 size="32 32 100%-32 100%-70" 453 504 > 454 505 <!-- Settings / shadows --> 455 <object size="0 10 100%-80 35" type="text" style="RightLabelText" ghost="true">Enable Shadows</object> 506 <object size="0 10 100%-80 35" type="text" style="RightLabelText" ghost="true"> 507 <translatableAttribute id="caption">Enable Shadows</translatableAttribute> 508 </object> 456 509 <object name="shadowsCheckbox" size="100%-56 15 100%-30 40" type="checkbox" style="StoneCrossBox" checked="true"> 457 510 <action on="Load">this.checked = Engine.Renderer_GetShadowsEnabled();</action> 458 511 <action on="Press">Engine.Renderer_SetShadowsEnabled(this.checked);</action> 459 512 </object> 460 513 461 514 <!-- Settings / Shadow PCF --> 462 <object size="0 35 100%-80 60" type="text" style="RightLabelText" ghost="true">Enable Shadow Filtering</object> 515 <object size="0 35 100%-80 60" type="text" style="RightLabelText" ghost="true"> 516 <translatableAttribute id="caption">Enable Shadow Filtering</translatableAttribute> 517 </object> 463 518 <object name="shadowPCFCheckbox" size="100%-56 40 100%-30 65" type="checkbox" style="StoneCrossBox" checked="true"> 464 519 <action on="Load">this.checked = Engine.Renderer_GetShadowPCFEnabled();</action> 465 520 <action on="Press">Engine.Renderer_SetShadowPCFEnabled(this.checked);</action> 466 521 </object> 467 522 468 523 <!-- Settings / Water Normals --> 469 <object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true">Water - HQ Waviness</object> 524 <object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true"> 525 <translatableAttribute id="caption">Water - HQ Waviness</translatableAttribute> 526 </object> 470 527 <object name="waterNormalCheckox" size="100%-56 65 100%-30 90" type="checkbox" style="StoneCrossBox" checked="true"> 471 528 <action on="Load">this.checked = Engine.Renderer_GetWaterNormalEnabled();</action> 472 529 <action on="Press">Engine.Renderer_SetWaterNormalEnabled(this.checked);</action> 473 530 </object> 474 531 475 532 <!-- Settings / Real Depth --> 476 <object size="0 85 100%-80 110" type="text" style="RightLabelText" ghost="true">Water - Use Actual Depth</object> 533 <object size="0 85 100%-80 110" type="text" style="RightLabelText" ghost="true"> 534 <translatableAttribute id="caption">Water - Use Actual Depth</translatableAttribute> 535 </object> 477 536 <object name="waterRealDepthCheckbox" size="100%-56 90 100%-30 115" type="checkbox" style="StoneCrossBox" checked="true"> 478 537 <action on="Load">this.checked = Engine.Renderer_GetWaterRealDepthEnabled();</action> 479 538 <action on="Press">Engine.Renderer_SetWaterRealDepthEnabled(this.checked);</action> 480 539 </object> 481 540 482 541 <!-- Settings / Reflection --> 483 <object size="0 110 100%-80 135" type="text" style="RightLabelText" ghost="true">Water - Enable Reflections</object> 542 <object size="0 110 100%-80 135" type="text" style="RightLabelText" ghost="true"> 543 <translatableAttribute id="caption">Water - Enable Reflections</translatableAttribute> 544 </object> 484 545 <object name="waterReflectionCheckbox" size="100%-56 115 100%-30 140" type="checkbox" style="StoneCrossBox" checked="true"> 485 546 <action on="Load">this.checked = Engine.Renderer_GetWaterReflectionEnabled();</action> 486 547 <action on="Press">Engine.Renderer_SetWaterReflectionEnabled(this.checked);</action> 487 548 </object> 488 549 489 550 <!-- Settings / Refraction --> 490 <object size="0 135 100%-80 160" type="text" style="RightLabelText" ghost="true">Water - Enable Refraction</object> 551 <object size="0 135 100%-80 160" type="text" style="RightLabelText" ghost="true"> 552 <translatableAttribute id="caption">Water - Enable Refraction</translatableAttribute> 553 </object> 491 554 <object name="waterRefractionCheckbox" size="100%-56 140 100%-30 165" type="checkbox" style="StoneCrossBox" checked="true"> 492 555 <action on="Load">this.checked = Engine.Renderer_GetWaterRefractionEnabled();</action> 493 556 <action on="Press">Engine.Renderer_SetWaterRefractionEnabled(this.checked);</action> 494 557 </object> 495 558 496 559 <!-- Settings / Foam --> 497 <object size="0 160 100%-80 185" type="text" style="RightLabelText" ghost="true">Water - Enable Shore Foam</object> 560 <object size="0 160 100%-80 185" type="text" style="RightLabelText" ghost="true"> 561 <translatableAttribute id="caption">Water - Enable Shore Foam</translatableAttribute> 562 </object> 498 563 <object name="waterFoamCheckbox" size="100%-56 165 100%-30 190" type="checkbox" style="StoneCrossBox" checked="true"> 499 564 <action on="Load">this.checked = Engine.Renderer_GetWaterFoamEnabled();</action> 500 565 <action on="Press">Engine.Renderer_SetWaterFoamEnabled(this.checked);</action> 501 566 </object> 502 567 503 568 <!-- Settings / Waves --> 504 <object size="0 185 100%-80 210" type="text" style="RightLabelText" ghost="true">Water - Enable Shore Waves</object> 569 <object size="0 185 100%-80 210" type="text" style="RightLabelText" ghost="true"> 570 <translatableAttribute id="caption">Water - Enable Shore Waves</translatableAttribute> 571 </object> 505 572 <object name="waterCoastalWavesCheckbox" size="100%-56 190 100%-30 215" type="checkbox" style="StoneCrossBox" checked="true"> 506 573 <action on="Load">this.checked = Engine.Renderer_GetWaterCoastalWavesEnabled();</action> 507 574 <action on="Press">Engine.Renderer_SetWaterCoastalWavesEnabled(this.checked);</action> 508 575 </object> 509 576 510 577 <!-- Settings / Shadows --> 511 <object size="0 210 100%-80 235" type="text" style="RightLabelText" ghost="true">Water - Use Surface Shadows</object> 578 <object size="0 210 100%-80 235" type="text" style="RightLabelText" ghost="true"> 579 <translatableAttribute id="caption">Water - Use Surface Shadows</translatableAttribute> 580 </object> 512 581 <object name="waterShadowsCheckbox" size="100%-56 215 100%-30 240" type="checkbox" style="StoneCrossBox" checked="true"> 513 582 <action on="Load">if (Engine.Renderer_GetWaterShadowEnabled()) this.checked = true; else this.checked = false;</action> 514 583 <action on="Press">Engine.Renderer_SetWaterShadowEnabled(this.checked);</action> 515 584 </object> 516 585 517 586 <!-- Settings / Particles --> 518 <object size="0 235 100%-80 260" type="text" style="RightLabelText" ghost="true">Enable Particles</object> 587 <object size="0 235 100%-80 260" type="text" style="RightLabelText" ghost="true"> 588 <translatableAttribute id="caption">Enable Particles</translatableAttribute> 589 </object> 519 590 <object name="particlesCheckbox" size="100%-56 240 100%-30 265" type="checkbox" style="StoneCrossBox" checked="true"> 520 591 <action on="Load">this.checked = Engine.Renderer_GetParticlesEnabled();</action> 521 592 <action on="Press">Engine.Renderer_SetParticlesEnabled(this.checked);</action> 522 593 </object> 523 594 524 595 <!-- Settings / Unit Silhouettes --> 525 <object size="0 260 100%-80 285" type="text" style="RightLabelText" ghost="true">Enable Unit Silhouettes</object> 596 <object size="0 260 100%-80 285" type="text" style="RightLabelText" ghost="true"> 597 <translatableAttribute id="caption">Enable Unit Silhouettes</translatableAttribute> 598 </object> 526 599 <object name="silhouettesCheckbox" size="100%-56 265 100%-30 290" type="checkbox" style="StoneCrossBox" checked="true"> 527 600 <action on="Load">this.checked = Engine.Renderer_GetSilhouettesEnabled();</action> 528 601 <action on="Press">Engine.Renderer_SetSilhouettesEnabled(this.checked);</action> 529 602 </object> 530 603 531 604 <!-- Settings / Music--> 532 <object size="0 285 100%-80 310" type="text" style="RightLabelText" ghost="true">Enable Music</object> 605 <object size="0 285 100%-80 310" type="text" style="RightLabelText" ghost="true"> 606 <translatableAttribute id="caption">Enable Music</translatableAttribute> 607 </object> 533 608 <object name="musicCheckbox" size="100%-56 290 100%-30 315" type="checkbox" style="StoneCrossBox" checked="true"> 534 609 <action on="Press">if (this.checked) global.music.start(); else global.music.stop();</action> 535 610 </object> 536 611 537 612 <!-- Settings / Dev Overlay --> 538 <object size="0 310 100%-80 335" type="text" style="RightLabelText" ghost="true">Developer Overlay</object> 613 <object size="0 310 100%-80 335" type="text" style="RightLabelText" ghost="true"> 614 <translatableAttribute id="caption">Developer Overlay</translatableAttribute> 615 </object> 539 616 <object name="developerOverlayCheckbox" size="100%-56 315 100%-30 340" type="checkbox" style="StoneCrossBox" checked="false"> 540 617 <action on="Press">toggleDeveloperOverlay();</action> 541 618 </object> … … 567 644 size="10 0 45% 100%" 568 645 > 569 646 <!-- Food --> 570 <object size="0 0 90 100%" type="image" style="resourceCounter" tooltip="Food" tooltip_style="sessionToolTipBold"> 647 <object size="0 0 90 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold"> 648 <translatableAttribute id="tooltip">Food</translatableAttribute> 571 649 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/food.png" ghost="true"/> 572 650 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourceFood"/> 573 651 </object> 574 652 575 653 <!-- Wood --> 576 <object size="90 0 180 100%" type="image" style="resourceCounter" tooltip="Wood" tooltip_style="sessionToolTipBold"> 654 <object size="90 0 180 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold"> 655 <translatableAttribute id="tooltip">Wood</translatableAttribute> 577 656 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/wood.png" ghost="true"/> 578 657 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourceWood"/> 579 658 </object> 580 659 581 660 <!-- Stone --> 582 <object size="180 0 270 100%" type="image" style="resourceCounter" tooltip="Stone" tooltip_style="sessionToolTipBold"> 661 <object size="180 0 270 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold"> 662 <translatableAttribute id="tooltip">Stone</translatableAttribute> 583 663 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/stone.png" ghost="true"/> 584 664 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourceStone"/> 585 665 </object> 586 666 587 667 <!-- Metal --> 588 <object size="270 0 360 100%" type="image" style="resourceCounter" tooltip="Metal" tooltip_style="sessionToolTipBold"> 668 <object size="270 0 360 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold"> 669 <translatableAttribute id="tooltip">Metal</translatableAttribute> 589 670 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/metal.png" ghost="true"/> 590 671 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourceMetal"/> 591 672 </object> 592 673 593 674 <!-- Population --> 594 <object size="360 0 450 100%" type="image" style="resourceCounter" tooltip="Population (current / limit)" tooltip_style="sessionToolTipBold"> 675 <object size="360 0 450 100%" type="image" style="resourceCounter" tooltip_style="sessionToolTipBold"> 676 <translatableAttribute id="tooltip">Population (current / limit)</translatableAttribute> 595 677 <object size="0 -4 40 34" type="image" sprite="stretched:session/icons/resources/population.png" ghost="true"/> 596 678 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourcePop"/> 597 679 </object> … … 603 685 <object size="50%-48 -26 50%+48 70" name="civIcon" type="image" tooltip_style="sessionToolTipBold"/> 604 686 605 687 <!-- Switch the view perspective to another player's (largely for AI development) --> 606 <object size="50%+50 5 50%+150 100%-5" name="viewPlayer" type="dropdown" hidden="true" style="StoneDropDown" tooltip_style="sessionToolTipBold" tooltip="Choose player to view"> 607 <action on="SelectionChange">selectViewPlayer(this.selected);</action> 688 <object size="50%+50 5 50%+150 100%-5" name="viewPlayer" type="dropdown" hidden="true" style="StoneDropDown" tooltip_style="sessionToolTipBold"> 689 <translatableAttribute id="tooltip">Choose player to view</translatableAttribute> 690 <action on="SelectionChange">selectViewPlayer(this.selected);</action> 608 691 </object> 609 692 610 693 <!-- ================================ ================================ --> … … 619 702 620 703 <!-- Displays Alpha name and number --> 621 704 <object size="50%+48 0 100%-226 100%" name="alphaLabel" type="text" style="CenteredLabelText" text_valign="top" ghost="true"> 622 ALPHA XIV : Naukratis<!-- IMPORTANT: remember to update pregame/mainmenu.xml in sync with this --> 705 <!-- IMPORTANT: remember to update pregame/mainmenu.xml in sync with this: --> 706 <translatableAttribute id="caption">ALPHA XIV : Naukratis</translatableAttribute> 623 707 624 708 <!-- Displays build date and revision number--> 625 709 <object size="50%-128 0 50%+128 100%-2" name="buildTimeLabel" type="text" style="BuildNameText" ghost="true"> 626 <action on="Load">this.caption = buildTime(0) + " (" + buildTime(2) + ")"</action>710 <action on="Load">this.caption = getBuildString()</action> 627 711 </object> 628 712 </object> 629 713 … … 635 719 size="100%-226 4 100%-198 32" 636 720 style="iconButton" 637 721 tooltip_style="sessionToolTip" 638 tooltip="Game speed"639 722 > 723 <translatableAttribute id="tooltip">Game speed</translatableAttribute> 640 724 <object size="5 5 100%-5 100%-5" type="image" sprite="stretched:session/icons/resources/time_small.png" ghost="true"/> 641 725 <action on="Press"> 642 726 toggleGameSpeed(); 643 727 </action> 644 728 </object> 645 729 646 <object size="100%-348 40 100%-198 65" name="gameSpeed" type="dropdown" buffer_zone="5" style="StoneDropDown" hidden="true" tooltip="Choose game speed" tooltip_style="sessionToolTip"/> 730 <object size="100%-348 40 100%-198 65" name="gameSpeed" type="dropdown" buffer_zone="5" style="StoneDropDown" hidden="true" tooltip_style="sessionToolTip"> 731 <translatableAttribute id="tooltip">Choose game speed</translatableAttribute> 732 </object> 733 647 734 648 735 <!-- ================================ ================================ --> 649 736 <!-- Diplomacy Button --> … … 653 740 size="100%-194 4 100%-166 32" 654 741 style="iconButton" 655 742 tooltip_style="sessionToolTip" 656 tooltip="Diplomacy"657 743 > 744 <translatableAttribute id="tooltip">Diplomacy</translatableAttribute> 658 745 <!-- TODO make the button less ugly --> 659 746 <object size="0 0 100% 100%" name="diplomacyButtonImage" type="image" sprite="stretched:session/icons/diplomacy.png" ghost="true"/> 660 747 <action on="Press"> … … 677 764 them on top of the main menu button --> 678 765 <object size="0 -4 100% 0" type="image" sprite="horizontalThinBorder" ghost="true"/> 679 766 680 <object size="50%-32 50%-16 50%+32 50%+16" type="image" sprite="menuButton" ghost="true">MENU</object> 767 <object size="50%-32 50%-16 50%+32 50%+16" type="image" sprite="menuButton" ghost="true"> 768 <translatableAttribute id="caption">MENU</translatableAttribute> 769 </object> 681 770 <action on="Press"> 682 771 toggleMenu(); 683 772 </action> … … 702 791 size="0 0 100% 28" 703 792 tooltip_style="sessionToolTip" 704 793 > 705 Settings794 <translatableAttribute id="caption">Settings</translatableAttribute> 706 795 <action on="Press">settingsMenuButton();</action> 707 796 </object> 708 797 … … 714 803 size="0 32 100% 60" 715 804 tooltip_style="sessionToolTip" 716 805 > 717 Save806 <translatableAttribute id="caption">Save</translatableAttribute> 718 807 <action on="Press"> 719 808 openSave(); 720 809 </action> … … 727 816 size="0 64 100% 92" 728 817 tooltip_style="sessionToolTip" 729 818 > 730 Chat819 <translatableAttribute id="caption">Chat</translatableAttribute> 731 820 <action on="Press">chatMenuButton();</action> 732 821 </object> 733 822 … … 738 827 size="0 96 100% 124" 739 828 tooltip_style="sessionToolTip" 740 829 > 741 Resign830 <translatableAttribute id="caption">Resign</translatableAttribute> 742 831 <action on="Press">resignMenuButton();</action> 743 832 </object> 744 833 … … 749 838 size="0 128 100% 156" 750 839 tooltip_style="sessionToolTip" 751 840 > 752 Exit841 <translatableAttribute id="caption">Exit</translatableAttribute> 753 842 <action on="Press">exitMenuButton();</action> 754 843 </object> 755 844 … … 760 849 size="0 160 100% 188" 761 850 tooltip_style="sessionToolTip" 762 851 > 763 <object name="pauseButtonText" type="text" style="CenteredButtonText" ghost="true">Pause</object> 852 <object name="pauseButtonText" type="text" style="CenteredButtonText" ghost="true"> 853 <translatableAttribute id="caption">Pause</translatableAttribute> 854 </object> 764 855 <action on="Press">togglePause();</action> 765 856 </object> 766 857 … … 771 862 size="0 192 100% 220" 772 863 tooltip_style="sessionToolTip" 773 864 > 774 Manual865 <translatableAttribute id="caption">Manual</translatableAttribute> 775 866 <action on="Press">openManual();</action> 776 867 </object> 777 868 </object> … … 795 886 size="0 36 50 86" 796 887 > 797 888 <object name="unitHeroButton" size="0 0 50 50" type="button" hidden="false" style="iconButton" 798 tooltip_style="sessionToolTip" tooltip="Attack and Armor"> 889 tooltip_style="sessionToolTip"> 890 <translatableAttribute id="tooltip">Attack and Armor</translatableAttribute> 799 891 <object name="unitHeroImage" size="5 5 100%-5 100%-5" type="image" ghost="true"/> 800 892 </object> 801 893 </object> … … 808 900 size="0% 50%-216 0%+36 50%+144" 809 901 > 810 902 <repeat count="10"> 811 <object name="unitGroupButton[n]" size="0 0 36 36" type="button" hidden="false" style="iconButton" tooltip_style="sessionToolTipBottomBold" 812 tooltip="Click to select grouped units.">903 <object name="unitGroupButton[n]" size="0 0 36 36" type="button" hidden="false" style="iconButton" tooltip_style="sessionToolTipBottomBold"> 904 <translatableAttribute id="tooltip">Click to select grouped units.</translatableAttribute> 813 905 <object name="unitGroupIcon[n]" size="3 3 33 33" type="image" sprite="groupsIcon" ghost="true"/> 814 906 <object name="unitGroupLabel[n]" type="text" style="largeCenteredOutlinedText" ghost="true"/> 815 907 </object> … … 859 951 <object type="button" 860 952 style="iconButton" 861 953 tooltip_style="sessionToolTip" 862 tooltip="Find idle worker"863 954 hotkey="selection.idleworker" 864 955 > 956 <translatableAttribute id="tooltip">Find idle worker</translatableAttribute> 865 957 <!-- TODO: should highlight the button if there's non-zero idle workers --> 866 958 <object size="0 0 100% 100%" type="image" sprite="idleWorker" ghost="true" /> 867 959 <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action> … … 904 996 size="6 36 100% 100%" 905 997 hidden="true" 906 998 > 907 <object ghost="true" style="resourceText" type="text" size="0 0 100% 20">Exchange resources:</object> 999 <object ghost="true" style="resourceText" type="text" size="0 0 100% 20"> 1000 <translatableAttribute id="tooltip">Exchange resources:</translatableAttribute> 1001 </object> 908 1002 <object size="0 32 100% 78"> 909 1003 <repeat count="4"> 910 1004 <object name="unitBarterSellButton[n]" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottomBold"> … … 961 1055 <object size="0 8 100% 60" type="image" sprite="edgedPanelShader"> 962 1056 <!-- Health bar --> 963 1057 <object size="88 0 100% 24" name="healthSection"> 964 <object size="0 0 100% 16" name="healthLabel" type="text" style="StatsTextLeft" ghost="true">Health:</object> 1058 <object size="0 0 100% 16" name="healthLabel" type="text" style="StatsTextLeft" ghost="true"> 1059 <translatableAttribute id="tooltip">Health:</translatableAttribute> 1060 </object> 965 1061 <object size="0 0 100% 16" name="healthStats" type="text" style="StatsTextRight" ghost="true"/> 966 1062 <object size="1 16 100% 23" name="health" type="image"> 967 1063 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> … … 973 1069 974 1070 <!-- Stamina bar --> 975 1071 <object size="88 28 100% 52" name="staminaSection"> 976 <object size="0 0 100% 16" name="staminaLabel" type="text" style="StatsTextLeft" ghost="true">Stamina:</object> 1072 <object size="0 0 100% 16" name="staminaLabel" type="text" style="StatsTextLeft" ghost="true"> 1073 <translatableAttribute id="tooltip">Stamina:</translatableAttribute> 1074 </object> 977 1075 <object size="0 0 100% 16" name="staminaStats" type="text" style="StatsTextRight" ghost="true"/> 978 1076 <object size="1 16 100% 23" name="stamina" type="image"> 979 1077 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> … … 998 1096 999 1097 <object size="0 60 100% 96" type="image" sprite="edgedPanelShader"> 1000 1098 <!-- Attack and Armor --> 1001 <object size="90 -2 126 34" name="attackAndArmorStats" type="image" sprite="stretched:session/icons/stances/defensive.png" tooltip="Attack and Armor" tooltip_style="sessionToolTip"/> 1099 <object size="90 -2 126 34" name="attackAndArmorStats" type="image" sprite="stretched:session/icons/stances/defensive.png" tooltip_style="sessionToolTip"> 1100 <translatableAttribute id="tooltip">Attack and Armor</translatableAttribute> 1101 </object> 1002 1102 1003 1103 <!-- Resource carrying icon/counter --> 1004 1104 <!-- Used also for number of gatherers/builders --> … … 1011 1111 <object size="1 1 100%-1 100%-1" type="image" name="icon" ghost="true"/> 1012 1112 1013 1113 <!-- Experience bar --> 1014 <object size="2 2 6 100%-2" type="image" name="experience" tooltip="Experience" tooltip_style="sessionToolTip"> 1015 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 1016 <object type="image" sprite="experienceBackground" ghost="true"/> 1017 <object type="image" sprite="experienceForeground" ghost="true" name="experienceBar"/> 1018 <object type="image" sprite="statsBarShaderVertical" ghost="true"/> 1114 <object size="2 2 6 100%-2" type="image" name="experience" tooltip_style="sessionToolTip"> 1115 <translatableAttribute id="tooltip">Experience</translatableAttribute> 1116 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 1117 <object type="image" sprite="experienceBackground" ghost="true"/> 1118 <object type="image" sprite="experienceForeground" ghost="true" name="experienceBar"/> 1119 <object type="image" sprite="statsBarShaderVertical" ghost="true"/> 1019 1120 </object> 1020 1121 1021 <object z="20" size="4 4 20 20" name="rankIcon" type="image" tooltip="Rank" tooltip_style="sessionToolTip"/> 1122 <object z="20" size="4 4 20 20" name="rankIcon" type="image" tooltip_style="sessionToolTip"> 1123 <translatableAttribute id="tooltip">Rank</translatableAttribute> 1124 </object> 1022 1125 </object> 1023 1126 </object> 1024 1127 … … 1076 1179 <!-- Stats Bars --> 1077 1180 <object size= "100%-38 50 100%-18 100%-44" type="image" tooltip_style="sessionToolTip"> 1078 1181 <!-- Health bar --> 1079 <object size="4 0 11 100%" type="image" name="healthMultiple" tooltip="Hitpoints" tooltip_style="sessionToolTip"> 1182 <object size="4 0 11 100%" type="image" name="healthMultiple" tooltip_style="sessionToolTip"> 1183 <translatableAttribute id="tooltip">Hitpoints</translatableAttribute> 1080 1184 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 1081 1185 <object type="image" sprite="healthBackground" ghost="true"/> 1082 1186 <object type="image" sprite="healthForeground" ghost="true" name="healthBarMultiple"/> … … 1084 1188 </object> 1085 1189 1086 1190 <!-- Stamina bar --> 1087 <object size="15 0 22 100%" type="image" name="staminaMultiple" tooltip="Stamina" tooltip_style="sessionToolTipBold"> 1191 <object size="15 0 22 100%" type="image" name="staminaMultiple" tooltip_style="sessionToolTipBold"> 1192 <translatableAttribute id="tooltip">Stamina</translatableAttribute> 1088 1193 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 1089 1194 <object type="image" sprite="staminaBackground" ghost="true"/> 1090 1195 <object type="image" sprite="staminaForeground" ghost="true" name="staminaBarMultiple"/> … … 1250 1355 size="50%-84 50%+128 50%+84 50%+160" 1251 1356 tooltip_style="sessionToolTip" 1252 1357 > 1253 <object size="0 0 100% 100%" type="text" style="CenteredButtonText" name="disconnectedExitButtonText" ghost="true">Return to Main Menu</object> 1358 <object size="0 0 100% 100%" type="text" style="CenteredButtonText" name="disconnectedExitButtonText" ghost="true"> 1359 <translatableAttribute id="caption">Return to Main Menu</translatableAttribute> 1360 </object> 1254 1361 <action on="Press">leaveGame()</action> 1255 1362 </object> 1256 1363 -
binaries/data/mods/public/gui/session/unit_commands.js
diff --git a/binaries/data/mods/public/gui/session/unit_commands.js b/binaries/data/mods/public/gui/session/unit_commands.js index c9d1e64..2977139 100644
a b const BARTER_RESOURCES = ["food", "wood", "stone", "metal"]; 27 27 const BARTER_ACTIONS = ["Sell", "Buy"]; 28 28 29 29 // Gate constants 30 const GATE_ACTIONS = [" Lock", "Unlock"];30 const GATE_ACTIONS = ["lock", "unlock"]; 31 31 32 32 // The number of currently visible buttons (used to optimise showing/hiding) 33 33 var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Training": 0, "Research": 0, "Barter": 0, "Trading": 0, "Construction": 0, "Command": 0, "Stance": 0, "Gate": 0, "Pack": 0}; … … function formatLimitString(trainEntLimit, trainEntCount) 146 146 { 147 147 if (trainEntLimit == undefined) 148 148 return ""; 149 var text = "\n\n Current Count: " + trainEntCount + ", Limit: " + trainEntLimit + ".";149 var text = "\n\n" + sprintf(translate("Current Count: %(count)s, Limit: %(limit)s."), { count: trainEntCount, limit: trainEntLimit }); 150 150 if (trainEntCount >= trainEntLimit) 151 151 text = "[color=\"red\"]" + text + "[/color]"; 152 152 return text; … … function formatBatchTrainingString(buildingsCountToTrainFullBatch, fullBatchSize 174 174 if (buildingsCountToTrainFullBatch > 0) 175 175 { 176 176 if (buildingsCountToTrainFullBatch > 1) 177 fullBatchesString += buildingsCountToTrainFullBatch + "*"; 178 fullBatchesString += fullBatchSize; 177 fullBatchesString = sprintf(translate("%(buildings)s*%(batchSize)s"), { 178 buildings: buildingsCountToTrainFullBatch, 179 batchSize: fullBatchSize 180 }); 181 else 182 fullBatchesString = fullBatchSize; 179 183 } 180 184 var remainderBatchString = remainderBatch > 0 ? remainderBatch : ""; 181 185 var batchDetailsString = ""; 186 var action = "[font=\"serif-bold-13\"]" + translate("Shift-click") + "[/font][font=\"serif-13\"]" 187 182 188 // We need to display the batch details part if there is either more than 183 189 // one building with full batch or one building with the full batch and 184 190 // another with a partial batch 185 191 if (buildingsCountToTrainFullBatch > 1 || 186 192 (buildingsCountToTrainFullBatch == 1 && remainderBatch > 0)) 187 193 { 188 batchDetailsString += " (" + fullBatchesString; 189 if (remainderBatchString != "") 190 batchDetailsString += " + " + remainderBatchString; 191 batchDetailsString += ")"; 194 if (remainderBatch > 0) 195 return "\n[font=\"serif-13\"]" + sprintf(translate("%(action)s to train %(number)s (%(fullBatch)s + %(remainderBatch)s)."), { 196 action: action, 197 number: totalBatchTrainingCount, 198 fullBatch: fullBatchesString, 199 remainderBatch: remainderBatch 200 }) + "[/font]"; 201 202 return "\n[font=\"serif-13\"]" + sprintf(translate("%(action)s to train %(number)s (%(fullBatch)s)."), { 203 action: action, 204 number: totalBatchTrainingCount, 205 fullBatch: fullBatchesString 206 }) + "[/font]"; 192 207 } 193 208 194 return "\n[font=\"serif-bold-13\"]Shift-click[/font][font=\"serif-13\"] to train " 195 + totalBatchTrainingCount + batchDetailsString + ".[/font]"; 209 return "\n[font=\"serif-13\"]" + sprintf(translate("%(action)s to train %(number)s."), { 210 action: action, 211 number: totalBatchTrainingCount 212 }) + "[/font]"; 213 } 214 215 function getStanceDisplayName(name) 216 { 217 var displayName; 218 switch(name) 219 { 220 case "violent": 221 displayName = translate("Violent"); 222 break; 223 case "aggressive": 224 displayName = translate("Aggressive"); 225 break; 226 case "passive": 227 displayName = translate("Passive"); 228 break; 229 case "defensive": 230 displayName = translate("Defensive"); 231 break; 232 case "standground": 233 displayName = translate("Standground"); 234 break; 235 default: 236 warn(sprintf(translate("Internationalization: Unexpected stance found with code ‘%(stance)s’. This stance must be internationalized."), { stance: name })); 237 displayName = name; 238 break; 239 } 240 return displayName; 196 241 } 197 242 198 243 /** … … function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c 374 419 break; 375 420 } 376 421 422 377 423 switch (guiName) 378 424 { 379 425 case SELECTION: … … function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c 386 432 case QUEUE: 387 433 var tooltip = getEntityNames(template); 388 434 if (item.neededSlots) 389 tooltip += "\n[color=\"red\"] Insufficient population capacity:\n[/color]"+getCostComponentDisplayName("population")+" "+item.neededSlots;435 tooltip += "\n[color=\"red\"]" + translate("Insufficient population capacity:") + "\n[/color]" + sprintf(translate("%(population)s %(neededSlots)s"), { population: getCostComponentDisplayName("population"), neededSlots: item.neededSlots }); 390 436 391 437 var progress = Math.round(item.progress*100) + "%"; 392 438 getGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = (item.count > 1 ? item.count : ""); … … function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c 404 450 405 451 case GARRISON: 406 452 var name = getEntityNames(template); 407 var tooltip = "Unload " + name + "\nSingle-click to unload 1. Shift-click to unload all of this type.";453 var tooltip = sprintf(translate("Unload %(name)s"), { name: name })+ "\n" + translate("Single-click to unload 1. Shift-click to unload all of this type."); 408 454 var count = garrisonGroups.getCount(item); 409 455 getGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = (count > 1 ? count : ""); 410 456 break; … … function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c 440 486 break; 441 487 442 488 case STANCE: 489 var tooltip = getStanceDisplayName(item); 490 break; 491 443 492 case FORMATION: 444 var tooltip = t oTitleCase(item);493 var tooltip = translate(item); 445 494 break; 446 495 447 496 case TRAINING: … … function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c 517 566 break; 518 567 } 519 568 569 520 570 // Button 521 571 var button = getGUIObjectByName("unit"+guiName+"Button["+i+"]"); 522 572 var button1 = getGUIObjectByName("unit"+guiName+"Button["+(i+rowLength)+"]"); … … function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c 588 638 "formationName": item 589 639 }); 590 640 591 button.tooltip += " (disabled)";641 button.tooltip = sprintf(translate("%(formation)s (disabled)"), { formation: button.tooltip }); 592 642 if (requirements.count > 1) 593 button.tooltip += "\n" + requirements.count + " units required";643 button.tooltip += "\n" + sprintf(translate("%(number)s units required"), { number: requirements.count }); 594 644 if (requirements.classesRequired) 595 645 { 596 button.tooltip += "\nOnly units of type"; 597 for each (var classRequired in requirements.classesRequired) 598 { 599 button.tooltip += " " + classRequired; 600 } 601 button.tooltip += " allowed."; 646 button.tooltip += "\n" + sprintf(translate("Only units of type %(unitType)s allowed."), { unitType: Engine.translateArray(requirements.classesRequired).join(translateWithContext("classSeparator", " ")) }); 602 647 } 603 648 } 604 649 … … function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c 631 676 // If already a gate, show locking actions 632 677 if (item.gate) 633 678 { 634 gateIcon = "icons/lock_" + GATE_ACTIONS[item.locked ? 0 : 1] .toLowerCase()+ "ed.png";679 gateIcon = "icons/lock_" + GATE_ACTIONS[item.locked ? 0 : 1] + "ed.png"; 635 680 guiSelection.hidden = item.gate.locked === undefined ? false : item.gate.locked != item.locked; 636 681 } 637 682 // otherwise show gate upgrade icon … … function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c 670 715 { 671 716 button.enabled = false; 672 717 var techName = getEntityNames(GetTechnologyData(template.requiredTechnology)); 673 button.tooltip += "\n Requires " + techName;718 button.tooltip += "\n" + sprintf(translate("Requires %(technology)s"), { technology: techName }); 674 719 grayscale = "grayscale:"; 675 720 affordableMask.hidden = false; 676 721 affordableMask.sprite = "colour: 0 0 0 127"; … … function setupUnitTradingPanel(usedPanels, unitEntState, selection) 911 956 var selectTradingPreferredGoodsData = { "entities": selection, "preferredGoods": resource }; 912 957 button.onpress = (function(e){ return function() { selectTradingPreferredGoods(e); } })(selectTradingPreferredGoodsData); 913 958 button.enabled = true; 914 button.tooltip = "Set " + resource + " as trading goods";959 button.tooltip = sprintf(translate("Set %(resource)s as trading goods"), { resource: resource }); 915 960 var icon = getGUIObjectByName("unitTradingIcon["+i+"]"); 916 961 var preferredGoods = unitEntState.trader.preferredGoods; 917 962 var selected = getGUIObjectByName("unitTradingSelection["+i+"]"); … … function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, s 1098 1143 var gateTemplate = getWallGateTemplate(state.id); 1099 1144 if (gateTemplate) 1100 1145 { 1101 var wallName = GetTemplateData(state.template).name.generic; 1102 var gateName = GetTemplateData(gateTemplate).name.generic; 1146 var wallName = GetTemplateDataWithoutLocalization(state.template).name.generic; 1147 var gateName = GetTemplateDataWithoutLocalization(gateTemplate).name.generic; 1148 var tooltipString; 1149 1150 // For internationalization purposes, when possible, available combinations should be provided 1151 // as placeholder-free strings as below. 1152 // 1153 // The placeholder implementation is provided only so that undetected new combinations of wall 1154 // and gate names are not simply printed in English, but as close to a perfect translation as 1155 // possible. 1156 1157 if (wallName === "Wooden Wall" && gateName === "Wooden Gate") 1158 { 1159 tooltipString = translate("Convert Wooden Wall into Wooden Gate"); 1160 } 1161 else if (wallName === "Stone Wall" && gateName === "City Gate") 1162 { 1163 tooltipString = translate("Convert Store Wall into City Gate"); 1164 } 1165 else if (wallName === "Siege Wall" && gateName === "Siege Wall Gate") 1166 { 1167 tooltipString = translate("Convert Siege Wall into Siege Wall Gate"); 1168 } 1169 else 1170 { 1171 warn(sprintf(translate("Internationalization: Unexpected combination of ‘%(localizedWall)s’ (%(englishWall)s) and ‘%(localizedGate)s’ (%(englishGate)s). This combination of wall and gate types must be internationalized."), { localizedWall: translate(wallName), englishWall: wallName, localizedGate: translate(gateName), englishGate: gateName })); 1172 tooltipString = sprintf(translate("Convert %(wall)s into %(gate)s"), { wall: translate(wallName), gate: translate(gateName) }); 1173 } 1103 1174 1104 1175 walls.push({ 1105 "tooltip": "Convert " + wallName + " to " + gateName,1176 "tooltip": tooltipString, 1106 1177 "template": gateTemplate, 1107 1178 "callback": function (item) { transformWallToGate(item.template); } 1108 1179 }); … … function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, s 1112 1183 longWallTypes[state.template] = true; 1113 1184 } 1114 1185 else if (state.gate && !gates.length) 1115 for (var j = 0; j < GATE_ACTIONS.length; ++j) 1116 gates.push({ 1117 "gate": state.gate, 1118 "tooltip": GATE_ACTIONS[j] + " gate", 1119 "locked": j == 0, 1120 "callback": function (item) { lockGate(item.locked); } 1121 }); 1186 { 1187 gates.push({ 1188 "gate": state.gate, 1189 "tooltip": translate("Lock Gate"), 1190 "locked": true, 1191 "callback": function (item) { lockGate(item.locked); } 1192 }); 1193 gates.push({ 1194 "gate": state.gate, 1195 "tooltip": translate("Unlock Gate"), 1196 "locked": false, 1197 "callback": function (item) { lockGate(item.locked); } 1198 }); 1199 } 1122 1200 // Show both 'locked' and 'unlocked' as active if the selected gates have both lock states. 1123 1201 else if (state.gate && state.gate.locked != gates[0].gate.locked) 1124 1202 for (var j = 0; j < gates.length; ++j) … … function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, s 1163 1241 } 1164 1242 } 1165 1243 if (packButton) 1166 items.push({ "packing": false, "packed": false, "tooltip": "Pack", "callback": function() { packUnit(true); } });1244 items.push({ "packing": false, "packed": false, "tooltip": translate("Pack"), "callback": function() { packUnit(true); } }); 1167 1245 if (unpackButton) 1168 items.push({ "packing": false, "packed": true, "tooltip": "Unpack", "callback": function() { packUnit(false); } });1246 items.push({ "packing": false, "packed": true, "tooltip": translate("Unpack"), "callback": function() { packUnit(false); } }); 1169 1247 if (packCancelButton) 1170 items.push({ "packing": true, "packed": false, "tooltip": "Cancel packing", "callback": function() { cancelPackUnit(true); } });1248 items.push({ "packing": true, "packed": false, "tooltip": translate("Cancel Packing"), "callback": function() { cancelPackUnit(true); } }); 1171 1249 if (unpackCancelButton) 1172 items.push({ "packing": true, "packed": true, "tooltip": "Cancel unpacking", "callback": function() { cancelPackUnit(false); } });1250 items.push({ "packing": true, "packed": true, "tooltip": translate("Cancel Unpacking"), "callback": function() { cancelPackUnit(false); } }); 1173 1251 1174 1252 if (items.length) 1175 1253 setupUnitPanel(PACK, usedPanels, entState, playerState, items); -
binaries/data/mods/public/gui/session/utility_functions.js
diff --git a/binaries/data/mods/public/gui/session/utility_functions.js b/binaries/data/mods/public/gui/session/utility_functions.js index ace9cc5..bbdd25b 100644
a b function damageValues(dmg) 151 151 // For the unit details panel 152 152 function damageTypeDetails(dmg) 153 153 { 154 if (dmg) 155 { 156 var dmgArray = []; 157 if (dmg.hack) dmgArray.push(dmg.hack + "[font=\"sans-10\"][color=\"orange\"] Hack[/color][/font]"); 158 if (dmg.pierce) dmgArray.push(dmg.pierce + "[font=\"sans-10\"][color=\"orange\"] Pierce[/color][/font]"); 159 if (dmg.crush) dmgArray.push(dmg.crush + "[font=\"sans-10\"][color=\"orange\"] Crush[/color][/font]"); 154 if (!dmg) 155 return "[font=\"serif-12\"]" + translate("(None)") + "[/font]"; 160 156 161 return dmgArray.join(", "); 162 } 163 else 164 { 165 return "[font=\"serif-12\"](None)[/font]"; 166 } 157 var dmgArray = []; 158 if (dmg.hack) 159 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s"), { 160 damage: dmg.hack, 161 damageType: "[font=\"sans-10\"][color=\"orange\"]" + translate("Hack") + "[/color][/font]" 162 })); 163 if (dmg.pierce) 164 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s"), { 165 damage: dmg.pierce, 166 damageType: "[font=\"sans-10\"][color=\"orange\"]" + translate("Pierce") + "[/color][/font]" 167 })); 168 if (dmg.crush) 169 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s"), { 170 damage: dmg.crush, 171 damageType: "[font=\"sans-10\"][color=\"orange\"]" + translate("Crush") + "[/color][/font]" 172 })); 173 174 return dmgArray.join(translate(", ")); 167 175 } 168 176 169 177 // Converts an armor level into the actual reduction percentage 170 function armorLevelToPercentage (level)178 function armorLevelToPercentageString(level) 171 179 { 172 return 100 - Math.round(Math.pow(0.9, level) * 100); 180 return (100 - Math.round(Math.pow(0.9, level) * 100)) + "%"; 181 // return sprintf(translate("%(armorPercentage)s%"), { armorPercentage: (100 - Math.round(Math.pow(0.9, level) * 100)) }); // Not supported by our sprintf implementation. 173 182 } 174 183 175 184 // Also for the unit details panel 176 185 function armorTypeDetails(dmg) 177 186 { 178 if (dmg) 179 { 180 var dmgArray = []; 181 if (dmg.hack) 182 { 183 dmgArray.push(dmg.hack + "[font=\"sans-10\"][color=\"orange\"] Hack[/color][/font] " + 184 " [font=\"sans-10\"](" + armorLevelToPercentage(dmg.hack) + "%)[/font]"); 185 } 186 if (dmg.pierce) 187 { 188 dmgArray.push(dmg.pierce + "[font=\"sans-10\"][color=\"orange\"] Pierce[/color][/font] " + 189 " [font=\"sans-10\"](" + armorLevelToPercentage(dmg.pierce) + "%)[/font]"); 190 } 191 if (dmg.crush) 192 { 193 dmgArray.push(dmg.crush + "[font=\"sans-10\"][color=\"orange\"] Crush[/color][/font] " + 194 " [font=\"sans-10\"](" + armorLevelToPercentage(dmg.crush) + "%)[/font]"); 195 } 187 if (!dmg) 188 return "[font=\"serif-12\"]" + translate("(None)") + "[/font]"; 196 189 197 return dmgArray.join(", "); 198 } 199 else 200 { 201 return "[font=\"serif-12\"](None)[/font]"; 202 } 190 var dmgArray = []; 191 if (dmg.hack) 192 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), { 193 damage: dmg.hack, 194 damageType: "[font=\"sans-10\"][color=\"orange\"]" + translate("Hack") + "[/color][/font]", 195 armorPercentage: "[font=\"sans-10\"]" + sprintf(translate("(%(armorPercentage)s)"), { armorPercentage: armorLevelToPercentageString(dmg.hack) }) + "[/font]" 196 })); 197 if (dmg.pierce) 198 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), { 199 damage: dmg.pierce, 200 damageType: "[font=\"sans-10\"][color=\"orange\"]" + translate("Pierce") + "[/color][/font]", 201 armorPercentage: "[font=\"sans-10\"]" + sprintf(translate("(%(armorPercentage)s)"), { armorPercentage: armorLevelToPercentageString(dmg.pierce) }) + "[/font]" 202 })); 203 if (dmg.crush) 204 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), { 205 damage: dmg.crush, 206 damageType: "[font=\"sans-10\"][color=\"orange\"]" + translate("Crush") + "[/color][/font]", 207 armorPercentage: "[font=\"sans-10\"]" + sprintf(translate("(%(armorPercentage)s)"), { armorPercentage: armorLevelToPercentageString(dmg.crush) }) + "[/font]" 208 })); 209 210 return dmgArray.join(translate(", ")); 203 211 } 204 212 205 213 // For the training tooltip 206 214 function damageTypesToText(dmg) 207 215 { 208 216 if (!dmg) 209 return "[font=\"serif-12\"](None)[/font]"; 210 211 var hackLabel = "[font=\"serif-12\"] Hack[/font]"; 212 var pierceLabel = "[font=\"serif-12\"] Pierce[/font]"; 213 var crushLabel = "[font=\"serif-12\"] Crush[/font]"; 214 var hackDamage = dmg.hack; 215 var pierceDamage = dmg.pierce; 216 var crushDamage = dmg.crush; 217 return "[font=\"serif-12\"]" + translate("(None)") + "[/font]"; 217 218 218 219 var dmgArray = []; 219 if (hackDamage) dmgArray.push(Math.round(hackDamage) + hackLabel); 220 if (pierceDamage) dmgArray.push(Math.round(pierceDamage) + pierceLabel); 221 if (crushDamage) dmgArray.push(Math.round(crushDamage) + crushLabel); 222 223 return dmgArray.join("[font=\"serif-12\"], [/font]"); 220 if (dmg.hack) 221 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s"), { 222 damage: dmg.hack, 223 damageType: "[font=\"serif-12\"]" + translate("Hack") + "[/font]" 224 })); 225 if (dmg.pierce) 226 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s"), { 227 damage: dmg.pierce, 228 damageType: "[font=\"serif-12\"]" + translate("Pierce") + "[/font]" 229 })); 230 if (dmg.crush) 231 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s"), { 232 damage: dmg.crush, 233 damageType: "[font=\"serif-12\"]" + translate("Crush") + "[/font]" 234 })); 235 236 return dmgArray.join("[font=\"serif-12\"]" + translate(", ") + "[/font]"); 224 237 } 225 238 226 239 // Also for the training tooltip 227 240 function armorTypesToText(dmg) 228 241 { 229 242 if (!dmg) 230 return "[font=\"serif-12\"](None)[/font]"; 231 232 var hackDamage = dmg.hack; 233 var pierceDamage = dmg.pierce; 234 var crushDamage = dmg.crush; 235 var hackLabel = "[font=\"serif-12\"] Hack (" + armorLevelToPercentage(hackDamage) + "%)[/font]"; 236 var pierceLabel = "[font=\"serif-12\"] Pierce (" + armorLevelToPercentage(pierceDamage) + "%)[/font]"; 237 var crushLabel = "[font=\"serif-12\"] Crush (" + armorLevelToPercentage(crushDamage) + "%)[/font]"; 243 return "[font=\"serif-12\"]" + translate("(None)") + "[/font]"; 238 244 239 245 var dmgArray = []; 240 if (hackDamage) dmgArray.push(hackDamage + hackLabel); 241 if (pierceDamage) dmgArray.push(pierceDamage + pierceLabel); 242 if (crushDamage) dmgArray.push(crushDamage + crushLabel); 243 244 return dmgArray.join("[font=\"serif-12\"], [/font]"); 246 if (dmg.hack) 247 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), { 248 damage: dmg.hack, 249 damageType: "[font=\"serif-12\"]" + translate("Hack") + "[/font]", 250 armorPercentage: "[font=\"sans-10\"]" + sprintf(translate("(%(armorPercentage)s)"), { armorPercentage: armorLevelToPercentageString(dmg.hack) }) + "[/font]" 251 })); 252 if (dmg.pierce) 253 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), { 254 damage: dmg.pierce, 255 damageType: "[font=\"serif-12\"]" + translate("Pierce") + "[/font]", 256 armorPercentage: "[font=\"sans-10\"]" + sprintf(translate("(%(armorPercentage)s)"), { armorPercentage: armorLevelToPercentageString(dmg.pierce) }) + "[/font]" 257 })); 258 if (dmg.crush) 259 dmgArray.push(sprintf(translate("%(damage)s %(damageType)s %(armorPercentage)s"), { 260 damage: dmg.crush, 261 damageType: "[font=\"serif-12\"]" + translate("Crush") + "[/font]", 262 armorPercentage: "[font=\"sans-10\"]" + sprintf(translate("(%(armorPercentage)s)"), { armorPercentage: armorLevelToPercentageString(dmg.crush) }) + "[/font]" 263 })); 264 265 return dmgArray.join("[font=\"serif-12\"]" + translate(", ") + "[/font]"); 245 266 } 246 267 247 268 function getEntityCommandsList(entState) … … function getEntityCommandsList(entState) 251 272 { 252 273 commands.push({ 253 274 "name": "unload-all", 254 "tooltip": "Unload All",275 "tooltip": translate("Unload All"), 255 276 "icon": "garrison-out.png" 256 277 }); 257 278 } 258 279 259 280 commands.push({ 260 281 "name": "delete", 261 "tooltip": "Delete",282 "tooltip": translate("Delete"), 262 283 "icon": "kill_small.png" 263 284 }); 264 285 … … function getEntityCommandsList(entState) 266 287 { 267 288 commands.push({ 268 289 "name": "stop", 269 "tooltip": "Stop",290 "tooltip": translate("Stop"), 270 291 "icon": "stop.png" 271 292 }); 272 293 commands.push({ 273 294 "name": "garrison", 274 "tooltip": "Garrison",295 "tooltip": translate("Garrison"), 275 296 "icon": "garrison.png" 276 297 }); 277 298 } … … function getEntityCommandsList(entState) 280 301 { 281 302 commands.push({ 282 303 "name": "repair", 283 "tooltip": "Repair",304 "tooltip": translate("Repair"), 284 305 "icon": "repair.png" 285 306 }); 286 307 } … … function getEntityCommandsList(entState) 289 310 { 290 311 commands.push({ 291 312 "name": "focus-rally", 292 "tooltip": "Focus on Rally Point",313 "tooltip": translate("Focus on Rally Point"), 293 314 "icon": "focus-rally.png" 294 315 }); 295 316 } 296 317 297 318 if (entState.unitAI && entState.unitAI.lastWorkOrder) 298 319 { 299 320 commands.push({ 300 321 "name": "back-to-work", 301 "tooltip": "Back to Work",322 "tooltip": translate("Back to Work"), 302 323 "icon": "production.png" 303 324 }); 304 325 } … … function getEntityCostComponentsTooltipString(template, trainNum, entity) 339 360 totalCosts.time = Math.ceil(template.cost.time * (entity ? Engine.GuiInterfaceCall("GetBatchTime", {"entity": entity, "batchSize": trainNum}) : 1)); 340 361 341 362 var costs = []; 342 if (totalCosts.food) costs.push( getCostComponentDisplayName("food") + " " + totalCosts.food);343 if (totalCosts.wood) costs.push( getCostComponentDisplayName("wood") + " " + totalCosts.wood);344 if (totalCosts.metal) costs.push( getCostComponentDisplayName("metal") + " " + totalCosts.metal);345 if (totalCosts.stone) costs.push( getCostComponentDisplayName("stone") + " " + totalCosts.stone);346 if (totalCosts.population) costs.push( getCostComponentDisplayName("population") + " " + totalCosts.population);347 if (totalCosts.time) costs.push( getCostComponentDisplayName("time") + " " + totalCosts.time);363 if (totalCosts.food) costs.push(sprintf(translate("%(component)s %(cost)s"), { component: getCostComponentDisplayName("food"), cost: totalCosts.food })); 364 if (totalCosts.wood) costs.push(sprintf(translate("%(component)s %(cost)s"), { component: getCostComponentDisplayName("wood"), cost: totalCosts.wood })); 365 if (totalCosts.metal) costs.push(sprintf(translate("%(component)s %(cost)s"), { component: getCostComponentDisplayName("metal"), cost: totalCosts.metal })); 366 if (totalCosts.stone) costs.push(sprintf(translate("%(component)s %(cost)s"), { component: getCostComponentDisplayName("stone"), cost: totalCosts.stone })); 367 if (totalCosts.population) costs.push(sprintf(translate("%(component)s %(cost)s"), { component: getCostComponentDisplayName("population"), cost: totalCosts.population })); 368 if (totalCosts.time) costs.push(sprintf(translate("%(component)s %(cost)s"), { component: getCostComponentDisplayName("time"), cost: totalCosts.time })); 348 369 return costs; 349 370 } 350 371 … … function getWallPieceTooltip(wallTypes) 360 381 361 382 // Initialize the acceptable types for '$x to $y $resource' mode. 362 383 for (var resource in wallTypes[0].cost) 384 { 363 385 if (wallTypes[0].cost[resource]) 364 386 resourceCount[resource] = [wallTypes[0].cost[resource]]; 387 } 365 388 366 389 var sameTypes = true; 367 390 for (var i = 1; i < wallTypes.length; ++i) … … function getEntityCostTooltip(template, trainNum, entity) 425 448 var wallCosts = getWallPieceTooltip([templateShort, templateMedium, templateLong]); 426 449 var towerCosts = getEntityCostComponentsTooltipString(templateTower); 427 450 428 cost += "\n"; 429 cost += " Walls: " + wallCosts.join(" ") + "\n"; 430 cost += " Towers: " + towerCosts.join(" "); 451 cost += " " + sprintf(translate("Walls: %(costs)s"), { costs: wallCosts.join(translate(" ")) }) + "\n"; 452 cost += " " + sprintf(translate("Towers: %(costs)s"), { costs: towerCosts.join(translate(" ")) }); 431 453 } 432 454 else if (template.cost) 433 455 { 434 456 var costs = getEntityCostComponentsTooltipString(template, trainNum, entity); 435 cost += costs.join(" ");457 cost = costs.join(translate(" ")); 436 458 } 437 459 else 438 460 { … … function getPopulationBonusTooltip(template) 449 471 { 450 472 var popBonus = ""; 451 473 if (template.cost && template.cost.populationBonus) 452 popBonus = "\n[font=\"serif-bold-13\"]Population Bonus:[/font] " + template.cost.populationBonus; 474 popBonus = "\n" + sprintf(translate("%(label)s %(populationBonus)s"), { 475 label: "[font=\"serif-bold-13\"]" + translate("Population Bonus:") + "[/font]", 476 populationBonus: template.cost.populationBonus 477 }); 453 478 return popBonus; 454 479 } 455 480 … … function getNeededResourcesTooltip(resources) 460 485 { 461 486 var formatted = []; 462 487 for (var resource in resources) 463 formatted.push("[font=\"serif-12\"]" + getCostComponentDisplayName(resource) + "[/font] " + resources[resource]); 488 formatted.push(sprintf(translate("%(component)s %(cost)s"), { 489 component: "[font=\"serif-12\"]" + getCostComponentDisplayName(resource) + "[/font]", 490 cost: resources[resource] 491 })); 464 492 465 return "\n\n[font=\"serif-bold-13\"][color=\"red\"] Insufficient resources:[/color][/font]\n" + formatted.join(" ");493 return "\n\n[font=\"serif-bold-13\"][color=\"red\"]" + translate("Insufficient resources:") + "[/color][/font]\n" + formatted.join(translate(" ")); 466 494 } 467 495 468 496 function getEntitySpeed(template) … … function getEntitySpeed(template) 470 498 var speed = ""; 471 499 if (template.speed) 472 500 { 473 speed += "[font=\"serif-bold-13\"]Speed:[/font] ";501 var label = "[font=\"serif-bold-13\"]" + translate("Speed:") + "[/font]" 474 502 var speeds = []; 475 if (template.speed.walk) speeds.push( template.speed.walk + " [font=\"serif-12\"]Walk[/font]");476 if (template.speed.run) speeds.push( template.speed.run + " [font=\"serif-12\"]Run[/font]");503 if (template.speed.walk) speeds.push(sprintf(translate("%(speed)s %(movementType)s"), { speed: template.speed.walk, movementType: "[font=\"serif-12\"]" + translate("Walk") + "[/font]"})); 504 if (template.speed.run) speeds.push(sprintf(translate("%(speed)s %(movementType)s"), { speed: template.speed.run, movementType: "[font=\"serif-12\"]" + translate("Run") + "[/font]"})); 477 505 478 speed += speeds.join(", ");506 speed = sprintf(translate("%(label)s %(speeds)s"), { label: label, speeds: speeds.join(translate(", ")) }) 479 507 } 480 508 return speed; 481 509 } … … function getEntityAttack(template) 489 517 delete template.attack['Slaughter']; 490 518 for (var type in template.attack) 491 519 { 492 var attack = " [font=\"serif-bold-13\"]" + type + " Attack:[/font] " + damageTypesToText(template.attack[type]);493 // Show max attack range if ranged attack, also convert to tiles (4m per tile)520 var attack = ""; 521 var attackLabel = "[font=\"serif-bold-13\"]" + getAttackTypeLabel(type) + "[/font]"; 494 522 if (type == "Ranged") 495 attack += ", [font=\"serif-bold-13\"]Range:[/font] "+Math.round(template.attack[type].maxRange/4); 523 { 524 // Show max attack range if ranged attack, also convert to tiles (4m per tile) 525 attack = sprintf(translate("%(attackLabel)s %(damageTypes)s, %(rangeLabel)s %(range)s"), { 526 attackLabel: attackLabel, 527 damageTypes: damageTypesToText(template.attack[type]), 528 rangeLabel: "[font=\"serif-bold-13\"]" + translate("Range:") + "[/font]", 529 range: Math.round(template.attack[type].maxRange/4) 530 }); 531 } 532 else 533 { 534 attack = sprintf(translate("%(attackLabel)s %(damageTypes)s"), { 535 attackLabel: attackLabel, 536 damageTypes: damageTypesToText(template.attack[type]) 537 }); 538 } 496 539 attacks.push(attack); 497 540 } 498 541 } … … function getEntityAttack(template) 501 544 502 545 function getEntityName(template) 503 546 { 504 return template.name.specific || template.name.generic || "???"; 547 if (template.name.specific) 548 return translate(template.name.specific); 549 if (template.name.generic) 550 return translate(template.name.generic); 551 552 warn(translate("Entity name requested on an entity without a name, specific or generic.")); 553 return translate("???"); 505 554 } 506 555 507 556 function getEntityNames(template) 508 557 { 509 var names = [];510 558 if (template.name.specific) 511 { 512 names.push(template.name.specific); 513 if (template.name.generic && names[0] != template.name.generic) 514 names.push("(" + template.name.generic + ")"); 515 } 516 else if (template.name.generic) 517 names.push(template.name.generic); 518 519 return (names.length) ? names.join(" ") : "???"; 559 { 560 if (template.name.generic && template.name.specific != template.name.generic) 561 return sprintf(translate("%(specificName)s (%(genericName)s)"), { 562 specificName: translate(template.name.specific), 563 genericName: translate(template.name.generic) 564 }); 565 return translate(template.name.specific); 566 } 567 if (template.name.generic) 568 return translate(template.name.generic); 569 570 warn(translate("Entity name requested on an entity without a name, specific or generic.")); 571 return translate("???"); 520 572 } 521 573 522 574 function getEntityNamesFormatted(template) … … function getEntityRankedName(entState) 546 598 var template = GetTemplateData(entState.template) 547 599 var rank = entState.identity.rank; 548 600 if (rank) 549 return rank + " " + template.name.specific;601 return sprintf(translate("%(rank)s %(name)s"), { rank: rank, name: template.name.specific }); 550 602 else 551 603 return template.name.specific; 552 604 } … … function getRankIconSprite(entState) 568 620 */ 569 621 function getTradingTooltip(gain) 570 622 { 571 var tooltip= gain.traderGain;623 var gainString = gain.traderGain; 572 624 if (gain.market1Gain && gain.market1Owner == gain.traderOwner) 573 tooltip += "+"+ gain.market1Gain;625 gainString += translate("+") + gain.market1Gain; 574 626 if (gain.market2Gain && gain.market2Owner == gain.traderOwner) 575 tooltip += "+" + gain.market2Gain; 576 tooltip += " (you)"; 627 gainString += translate("+") + gain.market2Gain; 628 629 var tooltip = sprintf(translate("%(gain)s (%(player)s)"), { 630 gain: gainString, 631 player: translate("you") 632 }); 577 633 578 634 if (gain.market1Gain && gain.market1Owner != gain.traderOwner) 579 tooltip += ", " + gain.market1Gain + " (player " + gain.market1Owner + ")"; 635 tooltip += translate(", ") + sprintf(translate("%(gain)s (%(player)s)"), { 636 gain: gain.market1Gain, 637 player: sprintf(translate("player %(name)s"), { name: gain.market1Owner }) 638 }); 580 639 if (gain.market2Gain && gain.market2Owner != gain.traderOwner) 581 tooltip += ", " + gain.market2Gain + " (player " + gain.market2Owner + ")"; 640 tooltip += translate(", ") + sprintf(translate("%(gain)s (%(player)s)"), { 641 gain: gain.market2Gain, 642 player: sprintf(translate("player %(name)s"), { name: gain.market2Owner }) 643 }); 582 644 583 645 return tooltip; 584 646 } 585 647 648 function getAttackTypeLabel(type) 649 { 650 if (type === "Charge") return translate("Charge Attack:"); 651 if (type === "Melee") return translate("Melee Attack:"); 652 if (type === "Ranged") return translate("Ranged Attack:"); 653 654 warn(sprintf(translate("Internationalization: Unexpected attack type found with code ‘%(attackType)s’. This attack type must be internationalized."), { attackType: type })); 655 return translate("Attack:"); 656 } 657 586 658 /** 587 659 * Returns the entity itself except when garrisoned where it returns its garrisonHolder 588 660 */ -
binaries/data/mods/public/gui/splashscreen/splashscreen.js
diff --git a/binaries/data/mods/public/gui/splashscreen/splashscreen.js b/binaries/data/mods/public/gui/splashscreen/splashscreen.js index abd975e..15ff54a 100644
a b 1 1 function init(data) 2 2 { 3 getGUIObjectByName("mainText").caption = readFile("gui/splashscreen/" + data.page + ".txt");3 getGUIObjectByName("mainText").caption = Engine.translateLines(readFile("gui/splashscreen/" + data.page + ".txt")); 4 4 } -
binaries/data/mods/public/gui/splashscreen/splashscreen.xml
diff --git a/binaries/data/mods/public/gui/splashscreen/splashscreen.xml b/binaries/data/mods/public/gui/splashscreen/splashscreen.xml index 226d621..05b9328 100644
a b 8 8 <object type="image" z="0" style="TranslucentPanel"/> 9 9 10 10 <object type="image" style="StoneDialog" size="50%-300 50%-200 50%+300 50%+200"> 11 <object type="text" style="TitleText" size="50%-128 0%-16 50%+128 16">Welcome to 0 A.D. !</object> 11 <object type="text" style="TitleText" size="50%-128 0%-16 50%+128 16"> 12 <translatableAttribute id="caption">Welcome to 0 A.D. !</translatableAttribute> 13 </object> 12 14 13 15 <object type="image" sprite="BackgroundTranslucent" size="20 20 100%-20 100%-52"> 14 16 <object name="openFundraiserPage" type="button" style="fundraiserButton" size="5 5 100% 150"> … … 21 23 </object> 22 24 </object> 23 25 <object name="btnOK" type="button" style="StoneButton" tooltip_style="snToolTip" size="24 100%-52 188 100%-24"> 24 OK26 <translatableAttribute id="caption">OK</translatableAttribute> 25 27 <action on="Press"><![CDATA[ 26 28 Engine.SetSplashScreenEnabled(!getGUIObjectByName("displaySplashScreen").checked); 27 29 Engine.PopGuiPage(); 28 30 ]]></action> 29 31 </object> 30 32 <object name="btnFundraiser" type="button" style="StoneButton" tooltip_style="snToolTip" size="196 100%-52 360 100%-24"> 31 Visit Fundraiser33 <translatableAttribute id="caption">Visit Fundraiser</translatableAttribute> 32 34 <action on="Press"><![CDATA[ 33 35 Engine.OpenURL("http://play0ad.com/fundraiser"); 34 36 ]]></action> 35 37 </object> 36 38 <object size="368 100%-52 100%-32 100%-24"> 37 39 <object size="0 0 100% 100%"> 38 <object name="displaySplashScreenText" size="0 0 100%-32 100%" type="text" style="RightLabelText">Don't show this again</object> 40 <object name="displaySplashScreenText" size="0 0 100%-32 100%" type="text" style="RightLabelText"> 41 <translatableAttribute id="caption">Don't show this again</translatableAttribute> 42 </object> 39 43 <object name="displaySplashScreen" checked="false" size="100%-16 50%-8 100% 50%+8" type="checkbox" style="StoneCrossBox"/> 40 44 </object> 41 45 </object> -
binaries/data/mods/public/gui/summary/summary.js
diff --git a/binaries/data/mods/public/gui/summary/summary.js b/binaries/data/mods/public/gui/summary/summary.js index 81129a3..8b9b4f5 100644
a b function adjustTabDividers(tabSize) 37 37 function init(data) 38 38 { 39 39 var civData = loadCivData(); 40 var map Size = "Scenario";40 var mapDisplayType = translate("Scenario"); 41 41 42 getGUIObjectByName("timeElapsed").caption = "Time elapsed: " + timeToString(data.timeElapsed);42 getGUIObjectByName("timeElapsed").caption = sprintf(translate("Time elapsed: %(time)s"), { time: timeToString(data.timeElapsed) }); 43 43 44 44 getGUIObjectByName("summaryText").caption = data.gameResult; 45 45 … … function init(data) 54 54 { 55 55 if (mapSizes.tiles[mapSizeIndex] == data.mapSettings.Size) 56 56 { 57 map Size = mapSizes.names[mapSizeIndex];57 mapDisplayType = mapSizes.names[mapSizeIndex]; 58 58 break; 59 59 } 60 60 } 61 61 } 62 62 63 getGUIObjectByName("mapName").caption = data.mapSettings.Name + " - " + mapSize;63 getGUIObjectByName("mapName").caption = sprintf(translate("%(mapName)s - %(mapType)s"), { mapName: data.mapSettings.Name, mapType: mapDisplayType}); 64 64 65 65 // Space player boxes 66 66 var boxSpacing = 32; -
binaries/data/mods/public/gui/summary/summary.xml
diff --git a/binaries/data/mods/public/gui/summary/summary.xml b/binaries/data/mods/public/gui/summary/summary.xml index 4e50416..6fbc09e 100644
a b 20 20 </action> 21 21 22 22 <object style="TitleText" type="text" size="50%-128 4 50%+128 36"> 23 Summary23 <translatableAttribute id="caption">Summary</translatableAttribute> 24 24 </object> 25 25 26 26 <object type="image" sprite="ForegroundBody" size="20 20 100%-20 70"> … … 59 59 60 60 <object name="scorePanelButton" type="button" sprite="ForegroundTab" size="20 95 170 120"> 61 61 <action on="Press">selectPanel(0);</action> 62 <object type="text" style="TitleText" ghost="true">Score</object> 62 <object type="text" style="TitleText" ghost="true"> 63 <translatableAttribute id="caption">Score</translatableAttribute> 64 </object> 63 65 </object> 64 66 65 67 <object name="unitsBuildingsPanelButton" type="button" sprite="BackgroundTab" size="176 95 326 120"> 66 68 <action on="Press">selectPanel(1);</action> 67 <object type="text" style="TitleText" ghost="true">Units/buildings</object> 69 <object type="text" style="TitleText" ghost="true"> 70 <translatableAttribute id="caption">Units/buildings</translatableAttribute> 71 </object> 68 72 </object> 69 73 70 74 <object name="conquestPanelButton" type="button" sprite="BackgroundTab" size="332 95 480 120"> 71 75 <action on="Press">selectPanel(2);</action> 72 <object type="text" style="TitleText" ghost="true">Conquest</object> 76 <object type="text" style="TitleText" ghost="true"> 77 <translatableAttribute id="caption">Conquest</translatableAttribute> 78 </object> 73 79 </object> 74 80 75 81 <object name="resourcesPanelButton" type="button" sprite="BackgroundTab" size="486 95 636 120"> 76 82 <action on="Press">selectPanel(3);</action> 77 <object type="text" style="TitleText" ghost="true">Resources</object> 83 <object type="text" style="TitleText" ghost="true"> 84 <translatableAttribute id="caption">Resources</translatableAttribute> 85 </object> 78 86 </object> 79 87 80 88 <object name="marketPanelButton" type="button" sprite="BackgroundTab" size="642 95 792 120"> 81 89 <action on="Press">selectPanel(4);</action> 82 <object type="text" style="TitleText" ghost="true">Market</object> 90 <object type="text" style="TitleText" ghost="true"> 91 <translatableAttribute id="caption">Market</translatableAttribute> 92 </object> 83 93 </object> 84 94 85 95 <object name="scorePanel" type="image" sprite="ForegroundBody" size="20 120 100%-20 100%-58"> 86 96 87 97 <object size="0 0 100% 100%-50"> 88 98 <object name="playerName0Heading" type="text" style="LeftTabLabelText"> 89 Player name99 <translatableAttribute id="caption">Player name</translatableAttribute> 90 100 </object> 91 101 <object name="economyScoreHeading" type="text" style="CenteredTabLabelText"> 92 Economy score102 <translatableAttribute id="caption">Economy score</translatableAttribute> 93 103 </object> 94 104 <object name="militaryScoreHeading" type="text" style="CenteredTabLabelText"> 95 Military score105 <translatableAttribute id="caption">Military score</translatableAttribute> 96 106 </object> 97 107 <object name="explorationScoreHeading" type="text" style="CenteredTabLabelText"> 98 Exploration score108 <translatableAttribute id="caption">Exploration score</translatableAttribute> 99 109 </object> 100 110 <object name="totalScoreHeading" type="text" style="CenteredTabLabelText"> 101 Total score111 <translatableAttribute id="caption">Total score</translatableAttribute> 102 112 </object> 103 113 </object> 104 114 … … 121 131 122 132 <object size="0 0 100% 100%-50"> 123 133 <object name="playerName1Heading" type="text" style="LeftTabLabelText"> 124 Player name134 <translatableAttribute id="caption">Player name</translatableAttribute> 125 135 </object> 126 136 <object name="unitsTrainedHeading" type="text" style="CenteredTabLabelText"> 127 Units trained137 <translatableAttribute id="caption">Units trained</translatableAttribute> 128 138 </object> 129 139 <object name="unitsLostHeading" type="text" style="CenteredTabLabelText"> 130 Units lost140 <translatableAttribute id="caption">Units lost</translatableAttribute> 131 141 </object> 132 142 <object name="enemyUnitsKilledHeading" type="text" style="CenteredTabLabelText"> 133 Enemy units killed143 <translatableAttribute id="caption">Enemy units killed</translatableAttribute> 134 144 </object> 135 145 <object name="buildingsConstructedHeading" type="text" style="CenteredTabLabelText"> 136 Buildings constructed146 <translatableAttribute id="caption">Buildings constructed</translatableAttribute> 137 147 </object> 138 148 <object name="buildingsLostHeading" type="text" style="CenteredTabLabelText"> 139 Buildings lost149 <translatableAttribute id="caption">Buildings lost</translatableAttribute> 140 150 </object> 141 151 <object name="enemyBuildingsDestroyedHeading" type="text" style="CenteredTabLabelText"> 142 Enemy buildings destroyed152 <translatableAttribute id="caption">Enemy buildings destroyed</translatableAttribute> 143 153 </object> 144 154 </object> 145 155 … … 164 174 165 175 <object size="0 0 100% 100%-50"> 166 176 <object name="playerName2Heading" type="text" style="LeftTabLabelText"> 167 Player name177 <translatableAttribute id="caption">Player name</translatableAttribute> 168 178 </object> 169 179 <object name="civCentresBuiltHeading" type="text" style="CenteredTabLabelText"> 170 Civ centres built180 <translatableAttribute id="caption">Civ centres built</translatableAttribute> 171 181 </object> 172 182 <object name="enemyCivCentresDestroyedHeading" type="text" style="CenteredTabLabelText"> 173 Enemy civ centres destroyed183 <translatableAttribute id="caption">Enemy civ centres destroyed</translatableAttribute> 174 184 </object> 175 185 <object name="mapExplorationHeading" type="text" style="CenteredTabLabelText"> 176 Map exploration186 <translatableAttribute id="caption">Map exploration</translatableAttribute> 177 187 </object> 178 188 </object> 179 189 … … 195 205 196 206 <object size="0 0 100% 100%-50"> 197 207 <object name="playerName3Heading" type="text" style="LeftTabLabelText"> 198 Player name208 <translatableAttribute id="caption">Player name</translatableAttribute> 199 209 </object> 200 210 <object name="resourceHeading" type="text" style="CenteredTabLabelText"> 201 Resource Statistics (Gathered / Used)211 <translatableAttribute id="caption">Resource Statistics (Gathered / Used)</translatableAttribute> 202 212 </object> 203 213 <object name="foodGatheredHeading" type="text" style="CenteredTabLabelText"> 204 Food214 <translatableAttribute id="caption">Food</translatableAttribute> 205 215 </object> 206 216 <object name="woodGatheredHeading" type="text" style="CenteredTabLabelText"> 207 Wood217 <translatableAttribute id="caption">Wood</translatableAttribute> 208 218 </object> 209 219 <object name="stoneGatheredHeading" type="text" style="CenteredTabLabelText"> 210 Stone220 <translatableAttribute id="caption">Stone</translatableAttribute> 211 221 </object> 212 222 <object name="metalGatheredHeading" type="text" style="CenteredTabLabelText"> 213 Metal223 <translatableAttribute id="caption">Metal</translatableAttribute> 214 224 </object> 215 225 <object name="vegetarianRatioHeading" type="text" style="CenteredTabLabelText"> 216 Vegetarian ratio226 <translatableAttribute id="caption">Vegetarian ratio</translatableAttribute> 217 227 </object> 218 228 <object name="treasuresCollectedHeading" type="text" style="CenteredTabLabelText"> 219 Treasures collected229 <translatableAttribute id="caption">Treasures collected</translatableAttribute> 220 230 </object> 221 231 <object name="resourcesTributedHeading" type="text" style="CenteredTabLabelText"> 222 Tributes (Sent / Received)232 <translatableAttribute id="caption">Tributes (Sent / Received)</translatableAttribute> 223 233 </object> 224 234 </object> 225 235 … … 245 255 246 256 <object size="0 0 100% 100%-50"> 247 257 <object name="playerName4Heading" type="text" style="LeftTabLabelText"> 248 Player name258 <translatableAttribute id="caption">Player name</translatableAttribute> 249 259 </object> 250 260 <object name="exchangedFoodHeading" type="text" style="CenteredTabLabelText"> 251 Food exchanged261 <translatableAttribute id="caption">Food exchanged</translatableAttribute> 252 262 </object> 253 263 <object name="exchangedWoodHeading" type="text" style="CenteredTabLabelText"> 254 Wood exchanged264 <translatableAttribute id="caption">Wood exchanged</translatableAttribute> 255 265 </object> 256 266 <object name="exchangedStoneHeading" type="text" style="CenteredTabLabelText"> 257 Stone exchanged267 <translatableAttribute id="caption">Stone exchanged</translatableAttribute> 258 268 </object> 259 269 <object name="exchangedMetalHeading" type="text" style="CenteredTabLabelText"> 260 Metal exchanged270 <translatableAttribute id="caption">Metal exchanged</translatableAttribute> 261 271 </object> 262 272 <object name="barterEfficiencyHeading" type="text" style="CenteredTabLabelText"> 263 Barter efficiency273 <translatableAttribute id="caption">Barter efficiency</translatableAttribute> 264 274 </object> 265 275 <object name="tradeIncomeHeading" type="text" style="CenteredTabLabelText"> 266 Trade income276 <translatableAttribute id="caption">Trade income</translatableAttribute> 267 277 </object> 268 278 </object> 269 279 … … 286 296 </object> 287 297 288 298 <object type="button" style="StoneButton" size="100%-164 100%-52 100%-24 100%-24"> 289 Continue299 <translatableAttribute id="caption">Continue</translatableAttribute> 290 300 <action on="Press"> 291 301 Engine.SwitchGuiPage("page_pregame.xml"); 292 302 </action>