872baef2-b296-fbb9-b399-ad5a165a4670_script.lsl 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. //
  2. // The line above should be left blank to avoid script errors in OpenSim.
  3. // Standard translation script for Sloodle.
  4. // Contains the common, re-usable words and phrases.
  5. //
  6. // The "locstrings" list is pairs of strings.
  7. // The first of each pair is the name, and second is the translation.
  8. //
  9. // This script is part of the Sloodle project.
  10. // Copyright (c) 2008 Sloodle (various contributors)
  11. // Released under the GNU GPL v3
  12. //
  13. // Contributors:
  14. // Peter R. Bloomfield
  15. //
  16. // Note: where a translation string contains {{x}} (where x is a number),
  17. // it means that a parameter can be inserted. Please make sure to include these
  18. // parameters in the appropriate location in your translation.
  19. // It may be sensible to add comments after your string to indicate what its parameters mean.
  20. // NOTE: parameter numbering starts at 0 (unlike previous versions, which started at 1).
  21. // Translations can be requested by sending a link message on the SLOODLE_CHANNEL_TRANSLATION_REQUEST channel.
  22. // It is advisable simply to use the "sloodle_translation_request" function provided in this script.
  23. ///// TRANSLATION /////
  24. // Localization batch - indicates the purpose of this file
  25. string mybatch = "set"; // Sloodle Set
  26. // List of string names and translation pairs.
  27. // The name is the first of each pair, and should not be translated.
  28. // The second of each pair is the translation.
  29. // Additional comments are sometimes given afterward to aid translations.
  30. list locstrings = [
  31. // Sloodle Set
  32. "sloodleset:cmddialog_simple", "Sloodle Set Menu\n\n{{0}} = Reset\n{{1}} = Rez an object", // Parameter: button label
  33. "sloodleset:cmddialog_mothership", "Sloodle Set Menu\n\n{{0}} = Reset\n{{1}} = Rez an object\n{{2}} = Manage layouts of multiple objects\n{{3}} = Destroy all objects", // Parameter: button label
  34. "sloodleset:objectmenu", "Sloodle Set.\nSelect object to rez:\n\n{{0}}", // The parameter should be a set of button labels and object names, e.g. "1 = WebIntercom, 2 = MetaGloss"
  35. "rezzingobject", "Rezzing Object:\n\"{{0}}\"", // Parameter should give the name of the object being rezzed
  36. "reztimeout", "Timeout while attempting to rez \"{{0}}\",", // Parameter should give the name of the object
  37. "sloodleset:noobjects", "Sorry {{0}}. This Sloodle Set does not contain any objects to be rezzed.", // Parameter: avatar name
  38. "notininventory", "Unable to rez \"{{0}}\". Item is not in inventory.", // Parameter: name of an object
  39. "notobject", "Unable to rez \"{{0}}\". Item is not an object.", // Parameter: name of an object
  40. // Layouts
  41. "layout:failedretrying", "Failed to store layout position. Retrying...",
  42. "layout:failedaborting", "Failed to store layout position. Aborting.",
  43. "layout:toofar", "Failed to store layout position - too far from rezzer.",
  44. "layout:storedobject", "Object stored in layout.",
  45. "layout:noneavailable", "Sorry {{0}}. There are no layouts available.", // Parameter: name of avatar
  46. "layout:loadmenu", "Sloodle Set.\nSelect layout to load:\n\n{{0}}", // The parameter should be a set of button labels and layout names, e.g. "1 = blah, 2 = foobar"
  47. "layout:savemenu", "Sloodle Set.\nSelect layout to save:\n\n{{0}}", // The parameter should be a set of button labels and layout names, e.g. "1 = blah, 2 = foobar"
  48. "layout:cmdmenu", "Sloodle Set.\nWhat layout action would you like to perform?\n\n{{0}} = Load layout\n{{1}} = Save layout\n{{2}} = Save layout as...\n{{3}} = Cancel", // Parameters: button labels
  49. "layout:nolayouttosave", "Sorry {{0}}. There is no current layout to save to. Please Save As a new layout or Load an existing layout first.", // Parameter: avatar name
  50. "layout:chatlayoutname", "Please chat the name of the new layout on channel 0 or 1. Touch the layout manager to cancel the operation.",
  51. "layout:layoutnametimeout", "Timeout waiting for layout name. Cancelling operation.",
  52. "layout:cancelsave", "Cancelling save operation.",
  53. "layout:saving", "Saving layout \"{{0}}\".", // Parameter: name of a layout
  54. "layout:loading", "Loading layout \"{{0}}\".", // Parameter: name of a layout
  55. "layout:nopermission", "Sorry {{0}}, you do not have permission to use layouts on this course.", // Parameter: avatar name
  56. "layout:savefailed", "Failed to save layout.",
  57. "layout:notexist", "That layout does not exist.",
  58. "layout:alreadyexists", "That layout already exists.",
  59. "layoutcaption:saving", "Saving...",
  60. "layoutcaption:savingas", "Saving As...",
  61. "layoutcaption:loading", "Loading...",
  62. "layoutcaption:layout", "Current Layout:\n{{0}}" // Parameter: name of layout
  63. ];
  64. ///// ----------- /////
  65. // Link message channels
  66. integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
  67. integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
  68. // Translation output methods
  69. string SLOODLE_TRANSLATE_LINK = "link"; // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
  70. string SLOODLE_TRANSLATE_SAY = "say"; // 1 output parameter: chat channel number
  71. string SLOODLE_TRANSLATE_WHISPER = "whisper"; // 1 output parameter: chat channel number
  72. string SLOODLE_TRANSLATE_SHOUT = "shout"; // 1 output parameter: chat channel number
  73. string SLOODLE_TRANSLATE_REGION_SAY = "regionsay"; // 1 output parameter: chat channel number
  74. string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay"; // No output parameters
  75. string SLOODLE_TRANSLATE_DIALOG = "dialog"; // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
  76. string SLOODLE_TRANSLATE_LOAD_URL = "loadurl"; // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
  77. string SLOODLE_TRANSLATE_LOAD_URL_PARALLEL = "loadurlpar"; // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
  78. string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext"; // 2 output parameters: colour <r,g,b>, and alpha value
  79. string SLOODLE_TRANSLATE_IM = "instantmessage"; // Recipient avatar should be identified in link message keyval. No output parameters.
  80. // Used for sending parallel URL loading messages
  81. integer SLOODLE_CHANNEL_OBJECT_LOAD_URL = -1639270041;
  82. ///// FUNCTIONS /////
  83. // Send a translation request link message
  84. // (Here for reference only)
  85. // Parameter: output_method = should identify an output method, as given by the "SLOODLE_TRANSLATE_..." constants above
  86. // Parameter: output_params = a list of parameters which controls the output, such as chat channel or buttons for a dialog
  87. // Parameter: string_name = the name of the localization string to output
  88. // Parameter: string_params = a list of parameters which will be included in the translated string (or an empty list if none)
  89. // Parameter: keyval = a key to send in the link message
  90. // Parameter: batch = the name of the localization batch which should handle this request
  91. sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
  92. {
  93. llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
  94. }
  95. // Send a translation response link message
  96. sloodle_translation_response(integer target, string name, string translation)
  97. {
  98. llMessageLinked(target, SLOODLE_CHANNEL_TRANSLATION_RESPONSE, name + "|" + translation + "|" + mybatch, NULL_KEY);
  99. }
  100. // Get the translation of a particular string
  101. string sloodle_get_string(string name)
  102. {
  103. // Attempt to find the string name
  104. integer numstrings = llGetListLength(locstrings);
  105. integer pos = llListFindList(locstrings, [name]);
  106. // IMPORTANT: we must be careful not to match a translations instead of a name.
  107. // If this was an even number, then we have a string name.
  108. if ((pos % 2) == 0) {
  109. // Make sure there is a subsequent translation in the list
  110. if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
  111. // The translation is not there
  112. pos = -1;
  113. }
  114. // If we could not find the string, then return a placeholder
  115. if (pos < 0) return "[[" + name + "]]";
  116. // If we got here, then we matched a translation instead of a string name.
  117. // As such, we need to resort to searching through the list manually (which can be very slow).
  118. // To saved time, we can start from the position just beyond where we got to.
  119. // We advance by 2 each time to skip the translations completely.
  120. pos += 1;
  121. for (pos=pos; pos < numstrings; pos += 2) {
  122. // Do we have a match?
  123. if (llList2String(locstrings, pos) == name) {
  124. // Yes - make sure there is a translation following it
  125. if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
  126. // The translation is not there - skip the rest of the search
  127. pos = numstrings;
  128. }
  129. }
  130. // If we reached this point, then the string is not available. Return a placeholder.
  131. return "[[" + name + "]]";
  132. }
  133. // Send a debug link message
  134. sloodle_debug(string msg)
  135. {
  136. llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
  137. }
  138. // Get a formatted translation of a string
  139. string sloodle_get_string_f(string name, list params)
  140. {
  141. // Get the string itself
  142. string str = sloodle_get_string(name);
  143. // How many parameters do we have?
  144. integer numparams = llGetListLength(params);
  145. // Go through each parameter we have been provided
  146. integer curparamnum;
  147. string curparamtok = "{{x}}";
  148. integer curparamtoklength = 0;
  149. string curparamstr = "";
  150. integer tokpos = -1;
  151. for (curparamnum=0; curparamnum < numparams; curparamnum++) {
  152. // Construct this parameter token
  153. curparamtok = "{{" + (string)(curparamnum) + "}}";
  154. curparamtoklength = llStringLength(curparamtok);
  155. // Fetch the parameter text
  156. curparamstr = llList2String(params, curparamnum);
  157. // Ensure the parameter text does NOT contain double braces (this avoids an infinite loop!)
  158. if (llSubStringIndex(curparamstr, "{{") < 0 && llSubStringIndex(curparamstr, "}}") < 0) {
  159. // Go through every instance of this parameter's token
  160. while ((tokpos = llSubStringIndex(str, curparamtok)) >= 0) {
  161. // Replace the token with the parameter string
  162. str = llDeleteSubString(str, tokpos, tokpos + curparamtoklength - 1);
  163. str = llInsertString(str, tokpos, curparamstr);
  164. }
  165. }
  166. }
  167. return str;
  168. }
  169. ///// STATES /////
  170. default
  171. {
  172. state_entry()
  173. {
  174. }
  175. link_message(integer sender_num, integer num, string str, key id)
  176. {
  177. // Check the channel
  178. if (num == SLOODLE_CHANNEL_TRANSLATION_REQUEST) {
  179. // // PROCESS REQUEST // //
  180. // Split the incoming message into fields
  181. list fields = llParseStringKeepNulls(str, ["|"], []);
  182. integer numfields = llGetListLength(fields);
  183. // Extract and check the localization batch
  184. string batch = "";
  185. if (numfields > 4) batch = llList2String(fields, 4);
  186. if (batch != mybatch) return;
  187. // We expect at least 3 fields
  188. // ... or 4 if there are insertion parameters...
  189. // ... or 5 if there is a language code
  190. // ... anybody up for a 6th parameter? :)
  191. if (numfields < 3) {
  192. sloodle_debug("ERROR: Insufficient fields for translation of string.");
  193. return;
  194. }
  195. // Extract the key parts of the request
  196. string output_method = llList2String(fields, 0);
  197. list output_params = llCSV2List(llList2String(fields, 1));
  198. integer num_output_params = llGetListLength(output_params);
  199. string string_name = llList2String(fields, 2);
  200. list string_params = [];
  201. if (numfields > 3) {
  202. // Extract the string parameters (extra text added to the output)
  203. string string_param_text = llList2String(fields, 3);
  204. if (string_param_text != "") string_params = llCSV2List(string_param_text);
  205. }
  206. // // TRANSLATE STRING // //
  207. // This string will store the translation
  208. string trans = "";
  209. // Do nothing if the string name is empty
  210. if (string_name != "") {
  211. // If there are no string parameters, then it is only a basic translation
  212. if (llGetListLength(string_params) == 0) {
  213. // Get the basic translation
  214. trans = sloodle_get_string(string_name);
  215. } else {
  216. // Construct the formatted string
  217. trans = sloodle_get_string_f(string_name, string_params);
  218. }
  219. }
  220. // // OUTPUT STRING // //
  221. // Check what output method has been requested
  222. if (output_method == SLOODLE_TRANSLATE_LINK) {
  223. // Return the string via link message
  224. sloodle_translation_response(sender_num, string_name, trans);
  225. } else if (output_method == SLOODLE_TRANSLATE_SAY) {
  226. // Say the string
  227. if (num_output_params > 0) llSay(llList2Integer(output_params, 0), trans);
  228. else sloodle_debug("ERROR: Insufficient output parameters to say string \"" + string_name + "\".");
  229. } else if (output_method == SLOODLE_TRANSLATE_WHISPER) {
  230. // Whisper the string
  231. if (num_output_params > 0) llWhisper(llList2Integer(output_params, 0), trans);
  232. else sloodle_debug("ERROR: Insufficient output parameters to whisper string \"" + string_name + "\".");
  233. } else if (output_method == SLOODLE_TRANSLATE_SHOUT) {
  234. // Shout the string
  235. if (num_output_params > 0) llShout(llList2Integer(output_params, 0), trans);
  236. else sloodle_debug("ERROR: Insufficient output parameters to shout string \"" + string_name + "\".");
  237. } else if (output_method == SLOODLE_TRANSLATE_REGION_SAY) {
  238. // RegionSay the string
  239. if (num_output_params > 0) llRegionSay(llList2Integer(output_params, 0), trans);
  240. else sloodle_debug("ERROR: Insufficient output parameters to region-say string \"" + string_name + "\".");
  241. } else if (output_method == SLOODLE_TRANSLATE_OWNER_SAY) {
  242. // Ownersay the string
  243. llOwnerSay(trans);
  244. } else if (output_method == SLOODLE_TRANSLATE_DIALOG) {
  245. // Display a dialog - we need a valid key
  246. if (id == NULL_KEY) {
  247. sloodle_debug("ERROR: Non-null key value required to show dialog with string \"" + string_name + "\".");
  248. return;
  249. }
  250. // We need at least 2 additional output parameters (channel, and at least 1 button)
  251. if (num_output_params >= 2) {
  252. // Extract the channel number
  253. integer channel = llList2Integer(output_params, 0);
  254. // Extract up to 12 button values
  255. list buttons = llList2List(output_params, 1, 12);
  256. // Display the dialog
  257. llDialog(id, trans, buttons, channel);
  258. } else sloodle_debug("ERROR: Insufficient output parameters to show dialog with string \"" + string_name + "\".");
  259. } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL) {
  260. // Display a URL - we need a valid key
  261. if (id == NULL_KEY) {
  262. sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
  263. return;
  264. }
  265. // We need 1 additional parameter, containing the URL to load
  266. if (num_output_params >= 1) llLoadURL(id, trans, llList2String(output_params, 0));
  267. else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
  268. } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL_PARALLEL) {
  269. // Display a URL - we need a valid key
  270. if (id == NULL_KEY) {
  271. sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
  272. return;
  273. }
  274. // NOTE: currently the parallel URL loaders will drop any text.
  275. // TODO: make parallel URL loaders use text as well.
  276. // We need 1 additional parameter, containing the URL to load
  277. if (num_output_params >= 1) llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_LOAD_URL, llList2String(output_params, 0), id);
  278. else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
  279. } else if (output_method == SLOODLE_TRANSLATE_HOVER_TEXT) {
  280. // We need 1 additional parameter, containing the URL to load
  281. if (num_output_params >= 2) llSetText(trans, (vector)llList2String(output_params, 0), (float)llList2String(output_params, 1));
  282. else sloodle_debug("ERROR: Insufficient output parameters to show hover text with string \"" + string_name + "\".");
  283. } else if (output_method == SLOODLE_TRANSLATE_IM) {
  284. // Send an IM - we need a valid key
  285. if (id == NULL_KEY) {
  286. sloodle_debug("ERROR: Non-null key value required to send IM with string \"" + string_name + "\".");
  287. return;
  288. }
  289. // Send the IM
  290. llInstantMessage(id, trans);
  291. } else {
  292. // Don't know the output method
  293. sloodle_debug("ERROR: unrecognised output method \"" + output_method + "\".");
  294. }
  295. }
  296. }
  297. }
  298. // Please leave the following line intact to show where the script lives in Git:
  299. // SLOODLE LSL Script Git Location: mod/set-1.0/objects/default/assets/sloodle_translation_set_en.lslp