8f57bd0a-0824-d8ad-ca21-40bab36b6f6c_script.lsl 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. //
  2. // The line above should be left blank to avoid script errors in OpenSim.
  3. // Translation strings for the Sloodle Quiz object(s).
  4. //
  5. // The "locstrings" list is pairs of strings.
  6. // The first of each pair is the name, and second is the translation.
  7. //
  8. // This script is part of the Sloodle project.
  9. // Copyright (c) 2008 Sloodle (various contributors)
  10. // Released under the GNU GPL v3
  11. //
  12. // Contributors:
  13. // Peter R. Bloomfield
  14. //
  15. // Note: where a translation string contains {{x}} (where x is a number),
  16. // it means that a parameter can be inserted. Please make sure to include these
  17. // parameters in the appropriate location in your translation.
  18. // It may be sensible to add comments after your string to indicate what its parameters mean.
  19. // NOTE: parameter numbering starts at 0 (unlike previous versions, which started at 1).
  20. // Translations can be requested by sending a link message on the SLOODLE_CHANNEL_TRANSLATION_REQUEST channel.
  21. // It is advisable simply to use the "sloodle_translation_request" function provided in this script.
  22. ///// TRANSLATION /////
  23. // Localization batch - indicates the purpose of this file
  24. string mybatch = "quiz";
  25. // List of string names and translation pairs.
  26. // The name is the first of each pair, and should not be translated.
  27. // The second of each pair is the translation.
  28. // Additional comments are sometimes given afterward to aid translations.
  29. list locstrings = [
  30. "invalidchoice", "Sorry {{0}}. Your selection was not in the list of available choices. Please try again.", // Parameter: avatar name
  31. "invalidtype", "Error: this object cannot handle quiz questions of type: {{0}}", // Parameter: question type name
  32. "complete", "Quiz complete {{0}}. Your final score was {{1}}.", // Parameters: avatar name, score
  33. "repeating", "Repeating...",
  34. "starting", "Starting quiz for {{0}}", // Parameter: avatar name
  35. "noquestions", "ERROR: there are no questions available",
  36. "notenrolled", "ERROR: It appears you are not enrolled in this class. Please make sure you are enrolled AND your avatar is linked to your Moodle account.",
  37. "noattemptsleft", "Sorry {{0}}. You are not allowed to attempt this quiz again.", // Parameter: avatar name
  38. "fetchingquiz", "Fetching quiz data...",
  39. "ready", "Ready to attempt: {{0}}.", // Parameter: name of quiz
  40. "correct", "Correct {{0}}.", // Parameter: name of avatar
  41. "usedialogs", "Error: You attempted to answer a multiple choice, or a true/false answer by typing on the chat line instead of using the dialog {{0}}.", // Parameter: name of avatar
  42. "incorrect", "Incorrect {{0}}." // Parameter: name of avatar
  43. ];
  44. ///// ----------- /////
  45. // Link message channels
  46. integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
  47. integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
  48. // Translation output methods
  49. string SLOODLE_TRANSLATE_LINK = "link"; // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
  50. string SLOODLE_TRANSLATE_SAY = "say"; // 1 output parameter: chat channel number
  51. string SLOODLE_TRANSLATE_WHISPER = "whisper"; // 1 output parameter: chat channel number
  52. string SLOODLE_TRANSLATE_SHOUT = "shout"; // 1 output parameter: chat channel number
  53. string SLOODLE_TRANSLATE_REGION_SAY = "regionsay"; // 1 output parameter: chat channel number
  54. string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay"; // No output parameters
  55. 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.
  56. string SLOODLE_TRANSLATE_LOAD_URL = "loadurl"; // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
  57. string SLOODLE_TRANSLATE_LOAD_URL_PARALLEL = "loadurlpar"; // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
  58. string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext"; // 2 output parameters: colour <r,g,b>, and alpha value
  59. string SLOODLE_TRANSLATE_IM = "instantmessage"; // Recipient avatar should be identified in link message keyval. No output parameters.
  60. // Used for sending parallel URL loading messages
  61. integer SLOODLE_CHANNEL_OBJECT_LOAD_URL = -1639270041;
  62. ///// FUNCTIONS /////
  63. // Send a translation request link message
  64. // (Here for reference only)
  65. // Parameter: output_method = should identify an output method, as given by the "SLOODLE_TRANSLATE_..." constants above
  66. // Parameter: output_params = a list of parameters which controls the output, such as chat channel or buttons for a dialog
  67. // Parameter: string_name = the name of the localization string to output
  68. // Parameter: string_params = a list of parameters which will be included in the translated string (or an empty list if none)
  69. // Parameter: keyval = a key to send in the link message
  70. // Parameter: batch = the name of the localization batch which should handle this request
  71. sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
  72. {
  73. llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
  74. }
  75. // Send a translation response link message
  76. sloodle_translation_response(integer target, string name, string translation)
  77. {
  78. llMessageLinked(target, SLOODLE_CHANNEL_TRANSLATION_RESPONSE, name + "|" + translation + "|" + mybatch, NULL_KEY);
  79. }
  80. // Get the translation of a particular string
  81. string sloodle_get_string(string name)
  82. {
  83. // Attempt to find the string name
  84. integer numstrings = llGetListLength(locstrings);
  85. integer pos = llListFindList(locstrings, [name]);
  86. // IMPORTANT: we must be careful not to match a translations instead of a name.
  87. // If this was an even number, then we have a string name.
  88. if ((pos % 2) == 0) {
  89. // Make sure there is a subsequent translation in the list
  90. if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
  91. // The translation is not there
  92. pos = -1;
  93. }
  94. // If we could not find the string, then return a placeholder
  95. if (pos < 0) return "[[" + name + "]]";
  96. // If we got here, then we matched a translation instead of a string name.
  97. // As such, we need to resort to searching through the list manually (which can be very slow).
  98. // To saved time, we can start from the position just beyond where we got to.
  99. // We advance by 2 each time to skip the translations completely.
  100. pos += 1;
  101. for (; pos < numstrings; pos += 2) {
  102. // Do we have a match?
  103. if (llList2String(locstrings, pos) == name) {
  104. // Yes - make sure there is a translation following it
  105. if ((pos + 1) < numstrings) return llList2String(locstrings, pos + 1);
  106. // The translation is not there - skip the rest of the search
  107. pos = numstrings;
  108. }
  109. }
  110. // If we reached this point, then the string is not available. Return a placeholder.
  111. return "[[" + name + "]]";
  112. }
  113. // Send a debug link message
  114. sloodle_debug(string msg)
  115. {
  116. llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
  117. }
  118. // Get a formatted translation of a string
  119. string sloodle_get_string_f(string name, list params)
  120. {
  121. // Get the string itself
  122. string str = sloodle_get_string(name);
  123. // How many parameters do we have?
  124. integer numparams = llGetListLength(params);
  125. // Go through each parameter we have been provided
  126. integer curparamnum = 0;
  127. string curparamtok = "{{x}}";
  128. integer curparamtoklength = 0;
  129. string curparamstr = "";
  130. integer tokpos = -1;
  131. for (; curparamnum < numparams; curparamnum++) {
  132. // Construct this parameter token
  133. curparamtok = "{{" + (string)(curparamnum) + "}}";
  134. curparamtoklength = llStringLength(curparamtok);
  135. // Fetch the parameter text
  136. curparamstr = llList2String(params, curparamnum);
  137. // Ensure the parameter text does NOT contain double braces (this avoids an infinite loop!)
  138. if (llSubStringIndex(curparamstr, "{{") < 0 && llSubStringIndex(curparamstr, "}}") < 0) {
  139. // Go through every instance of this parameter's token
  140. while ((tokpos = llSubStringIndex(str, curparamtok)) >= 0) {
  141. // Replace the token with the parameter string
  142. str = llDeleteSubString(str, tokpos, tokpos + curparamtoklength - 1);
  143. str = llInsertString(str, tokpos, curparamstr);
  144. }
  145. }
  146. }
  147. return str;
  148. }
  149. ///// STATES /////
  150. default
  151. {
  152. state_entry()
  153. {
  154. }
  155. link_message(integer sender_num, integer num, string str, key id)
  156. {
  157. // Check the channel
  158. if (num == SLOODLE_CHANNEL_TRANSLATION_REQUEST) {
  159. // // PROCESS REQUEST // //
  160. // Split the incoming message into fields
  161. list fields = llParseStringKeepNulls(str, ["|"], []);
  162. integer numfields = llGetListLength(fields);
  163. // Extract and check the localization batch
  164. string batch = "";
  165. if (numfields > 4) batch = llList2String(fields, 4);
  166. if (batch != mybatch) return;
  167. // We expect at least 3 fields
  168. // ... or 4 if there are insertion parameters...
  169. // ... anybody up for a 6th parameter? :)
  170. if (numfields < 3) {
  171. sloodle_debug("ERROR: Insufficient fields for translation of string.");
  172. return;
  173. }
  174. // Extract the key parts of the request
  175. string output_method = llList2String(fields, 0);
  176. list output_params = llCSV2List(llList2String(fields, 1));
  177. integer num_output_params = llGetListLength(output_params);
  178. string string_name = llList2String(fields, 2);
  179. list string_params = [];
  180. if (numfields > 3) {
  181. // Extract the string parameters (extra text added to the output)
  182. string string_param_text = llList2String(fields, 3);
  183. if (string_param_text != "") string_params = llCSV2List(string_param_text);
  184. }
  185. // // TRANSLATE STRING // //
  186. // This string will store the translation
  187. string trans = "";
  188. // Do nothing if the string name is empty
  189. if (string_name != "") {
  190. // If there are no string parameters, then it is only a basic translation
  191. if (llGetListLength(string_params) == 0) {
  192. // Get the basic translation
  193. trans = sloodle_get_string(string_name);
  194. } else {
  195. // Construct the formatted string
  196. trans = sloodle_get_string_f(string_name, string_params);
  197. }
  198. }
  199. // // OUTPUT STRING // //
  200. // Check what output method has been requested
  201. if (output_method == SLOODLE_TRANSLATE_LINK) {
  202. // Return the string via link message
  203. sloodle_translation_response(sender_num, string_name, trans);
  204. } else if (output_method == SLOODLE_TRANSLATE_SAY) {
  205. // Say the string
  206. if (num_output_params > 0) llSay(llList2Integer(output_params, 0), trans);
  207. else sloodle_debug("ERROR: Insufficient output parameters to say string \"" + string_name + "\".");
  208. } else if (output_method == SLOODLE_TRANSLATE_WHISPER) {
  209. // Whisper the string
  210. if (num_output_params > 0) llWhisper(llList2Integer(output_params, 0), trans);
  211. else sloodle_debug("ERROR: Insufficient output parameters to whisper string \"" + string_name + "\".");
  212. } else if (output_method == SLOODLE_TRANSLATE_SHOUT) {
  213. // Shout the string
  214. if (num_output_params > 0) llShout(llList2Integer(output_params, 0), trans);
  215. else sloodle_debug("ERROR: Insufficient output parameters to shout string \"" + string_name + "\".");
  216. } else if (output_method == SLOODLE_TRANSLATE_REGION_SAY) {
  217. // RegionSay the string
  218. if (num_output_params > 0) llRegionSay(llList2Integer(output_params, 0), trans);
  219. else sloodle_debug("ERROR: Insufficient output parameters to region-say string \"" + string_name + "\".");
  220. } else if (output_method == SLOODLE_TRANSLATE_OWNER_SAY) {
  221. // Ownersay the string
  222. llOwnerSay(trans);
  223. } else if (output_method == SLOODLE_TRANSLATE_DIALOG) {
  224. // Display a dialog - we need a valid key
  225. if (id == NULL_KEY) {
  226. sloodle_debug("ERROR: Non-null key value required to show dialog with string \"" + string_name + "\".");
  227. return;
  228. }
  229. // We need at least 2 additional output parameters (channel, and at least 1 button)
  230. if (num_output_params >= 2) {
  231. // Extract the channel number
  232. integer channel = llList2Integer(output_params, 0);
  233. // Extract up to 12 button values
  234. list buttons = llList2List(output_params, 1, 12);
  235. // Display the dialog
  236. llDialog(id, trans, buttons, channel);
  237. } else sloodle_debug("ERROR: Insufficient output parameters to show dialog with string \"" + string_name + "\".");
  238. } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL) {
  239. // Display a URL - we need a valid key
  240. if (id == NULL_KEY) {
  241. sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
  242. return;
  243. }
  244. // We need 1 additional parameter, containing the URL to load
  245. if (num_output_params >= 1) llLoadURL(id, trans, llList2String(output_params, 0));
  246. else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
  247. } else if (output_method == SLOODLE_TRANSLATE_LOAD_URL_PARALLEL) {
  248. // Display a URL - we need a valid key
  249. if (id == NULL_KEY) {
  250. sloodle_debug("ERROR: Non-null key value required to load URL with string \"" + string_name + "\".");
  251. return;
  252. }
  253. // NOTE: currently the parallel URL loaders will drop any text.
  254. // TODO: make parallel URL loaders use text as well.
  255. // We need 1 additional parameter, containing the URL to load
  256. if (num_output_params >= 1) llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_LOAD_URL, llList2String(output_params, 0), id);
  257. else sloodle_debug("ERROR: Insufficient output parameters to load URL with string \"" + string_name + "\".");
  258. } else if (output_method == SLOODLE_TRANSLATE_HOVER_TEXT) {
  259. // We need 1 additional parameter, containing the URL to load
  260. if (num_output_params >= 2) llSetText(trans, (vector)llList2String(output_params, 0), (float)llList2String(output_params, 1));
  261. else sloodle_debug("ERROR: Insufficient output parameters to show hover text with string \"" + string_name + "\".");
  262. } else if (output_method == SLOODLE_TRANSLATE_IM) {
  263. // Send an IM - we need a valid key
  264. if (id == NULL_KEY) {
  265. sloodle_debug("ERROR: Non-null key value required to send IM with string \"" + string_name + "\".");
  266. return;
  267. }
  268. // Send the IM
  269. llInstantMessage(id, trans);
  270. } else {
  271. // Don't know the output method
  272. sloodle_debug("ERROR: unrecognised output method \"" + output_method + "\".");
  273. }
  274. }
  275. }
  276. }
  277. // Please leave the following line intact to show where the script lives in Git:
  278. // SLOODLE LSL Script Git Location: mod/quiz-1.0/objects/default/assets/lang/en/sloodle_translation_quiz_en.lslp