not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

296 lines
8.8 KiB

  1. /*
  2. Translation library v0.2
  3. */
  4. // Extend jQuery
  5. (function ($) {
  6. // Get the URL query string and parse it
  7. jQuery.query = function() {
  8. var r = {length:0};
  9. var q = location.search;
  10. if(q && q != '#'){
  11. // remove the leading ? and trailing &
  12. q = q.replace(/^\?/,'').replace(/\&$/,'');
  13. jQuery.each(q.split('&'), function(){
  14. var key = this.split('=')[0];
  15. var val = this.split('=')[1];
  16. if(/^[0-9.]+$/.test(val)) val = parseFloat(val); // convert floats
  17. r[key] = val;
  18. r['length']++;
  19. });
  20. }
  21. return r;
  22. };
  23. function Translator(inp){
  24. this.q = $.query();
  25. this.id = (inp && typeof inp.id==="string") ? inp.id : 'form';
  26. this.master = (inp && typeof inp.master==="string") ? inp.master : '';
  27. this.json = (inp && typeof inp.json==="string") ? inp.json : '';
  28. this.langs = (inp && typeof inp.langs==="object") ? inp.langs : { 'en':'English' };
  29. // Load the master language config file
  30. this.setLanguage()
  31. this.lang = this.q.lang;
  32. if(!this.lang) this.lang = "en";
  33. this.page = $('#'+this.id);
  34. html = "<form id=\"langchoice\"><label>Select language (not all are complete):</label><select name=\"lang\">"
  35. for(var l in this.langs) html += '<option name="'+l+'" value="'+l+'"'+(this.lang==l ? " selected" : "")+'>'+this.langs[l]+'</option>';
  36. html += "</select></form>";
  37. if($('#translate_chooser').length == 0) this.page.prepend('<div id="translate_chooser"></div>');
  38. if($('#translation').length == 0) this.page.append('<div id="translation"></div>')
  39. $('#translate_chooser').html(html).find('#langchoice select').bind('change',{me:this},function(e){ e.data.me.setLanguage($(this).find("option:selected").val()); });
  40. this.setLanguage(this.lang);
  41. return this;
  42. }
  43. Translator.prototype.setLanguage = function(lang){
  44. if(lang) this.lang = lang;
  45. this.loadLanguage(this.lang,function(e){
  46. if(e.lang){
  47. this.lang = e.lang;
  48. this.phrasebook = (e.data) ? e.data : { 'language': {'name':'','code':e.lang } };
  49. }else{
  50. this.masterbook = e.data;
  51. }
  52. this.rebuildForm();
  53. if(e.lang){
  54. var href = $('a.langlink').attr('href');
  55. $('a.langlink').attr('href',href.substring(0,href.indexOf('?'))+'?lang='+this.lang);
  56. $('.langname').html(this.phrasebook.language.name);
  57. }
  58. });
  59. return this;
  60. }
  61. Translator.prototype.loadLanguage = function(lang,callback,langdummy){
  62. var url = (lang) ? this.json.replace('%LANG%',lang) : this.master;
  63. if(typeof langdummy=="string") lang = langdummy;
  64. if(lang) this.lang = lang;
  65. $.ajax({
  66. url: url,
  67. method: 'GET',
  68. dataType: 'json',
  69. context: this,
  70. error: function(){
  71. // We couldn't find this language so load the English version
  72. // so there is something to work from.
  73. console.log("Couldn't load "+lang)
  74. if(lang != "en") this.loadLanguage('en',callback,lang);
  75. },
  76. success: function(data){
  77. // Update the language code and name
  78. if(data && data.language && typeof data.language.code==="string") data.language.code = lang;
  79. if(data && data.language && typeof data.language.code==="string") data.language.name = this.langs[lang];
  80. if(typeof callback==="function") callback.call(this,{data:data,lang:lang});
  81. }
  82. });
  83. }
  84. Translator.prototype.rebuildForm = function(){
  85. var html = "<form id=\"language\">";
  86. html += this.buildForm(this.masterbook,this.phrasebook,"");
  87. html += "</form>";
  88. $('#translation').html(html);
  89. $('#translation input, #translation textarea, #translation select').attr('dir',(this.phrasebook && this.phrasebook.language && this.phrasebook.language.alignment=="right" ? "rtl" : "ltr")).unbind().bind('change',{me:this},function(e){
  90. e.data.me.getOutput();
  91. e.data.me.percentComplete();
  92. });
  93. // Update the text direction when the appropriate select box changes
  94. $('#translation select[name=".language.alignment"]').on('change',function(e){
  95. $('#translation input, #translation textarea, #translation select').attr('dir',($(this).val()=="right" ? "rtl" : "ltr" ));
  96. });
  97. this.getOutput();
  98. this.percentComplete();
  99. return this;
  100. }
  101. Translator.prototype.buildForm = function(m,p,k){
  102. var html = "";
  103. var newk = "";
  104. var inp = "";
  105. var arr = false;
  106. var n;
  107. var css;
  108. if(!k) k = "";
  109. for(key in m){
  110. n = parseInt(key);
  111. newk = k+"."+key;
  112. if(typeof m[key]==="object"){
  113. if(n >= 0 && this.previousgroup != n) html += '</div>';
  114. if(m[key]._text && m[key]._type){
  115. inp = "";
  116. if(m[key]._type=="textarea"){
  117. css = (m[key]._height) ? ' style="height:'+m[key]._height+'"' : "";
  118. inp = '<textarea name="'+newk+'"'+css+'>'+sanitize((p ? p[key] : ""))+'</textarea>';
  119. }else if(m[key]._type=="noedit"){
  120. inp = '<input type="hidden" name="'+newk+'" value="'+sanitize((p ? p[key] : ""))+'" />'+sanitize((p ? p[key] : ""));
  121. }else if(m[key]._type=="select"){
  122. inp = '<select name="'+newk+'">';
  123. for(var o = 0; o < m[key]._options.length ; o++){
  124. var sel = (p && m[key]._options[o].value==p[key]) ? ' selected="selected"' : '';
  125. inp += '<option value="'+m[key]._options[o].value+'"'+sel+'>'+m[key]._options[o].name+'</option>'
  126. }
  127. inp += '</select>';
  128. }else if(m[key]._type=="string"){
  129. inp = '<input type="text" name="'+newk+'" value="'+sanitize((p && p[key] ? p[key] : ""))+'" />';
  130. }
  131. html += this.row((m[key]._title ? m[key]._title : key),m[key]._text,inp);
  132. }else{
  133. // If this section has a title
  134. if(m[key]._title) html += '<h2>'+m[key]._title+'</h2>';
  135. if(n >= 0) html += '<div class="group">';
  136. html += this.buildForm(m[key],(p) ? p[key] : {}, newk);
  137. this.previousgroup = n;
  138. }
  139. }
  140. }
  141. return html;
  142. }
  143. Translator.prototype.percentComplete = function(){
  144. var percent = 100;
  145. if(this.lang!="en"){
  146. var total = 0;
  147. var diff = 0;
  148. /*
  149. for(var i = 0 in this.chromo.phrasebook){
  150. if(i!="alignment" && i!="code" && i != "lang" && i!="helpmenu" && i!="gal" && i!="eq" && i!="version"){
  151. total++;
  152. var val = converter($("#"+i).val()).replace(/&amp;/g,"&");
  153. if(this.q.debug) console.log(i,val,this.english[i])
  154. if(val && val != this.english[i]){
  155. diff++;
  156. // $("#fs_"+i).removeClass('same');
  157. }else{
  158. // $("#fs_"+i).addClass('same');
  159. }
  160. }
  161. }
  162. */
  163. percent = Math.floor(100*diff/total);
  164. }
  165. $("#complete").html(percent);
  166. }
  167. Translator.prototype.row = function(title,desc,field){
  168. var id = field.indexOf("id=\"");
  169. id = field.substr(id+4);
  170. id = id.substr(0,id.indexOf("\""));
  171. var html = " <fieldset>";// id=\"fs"+id+"\">";
  172. html += " <legend>"+title+"</legend>";
  173. html += " <div class=\"twocol\">";
  174. html += " <p>"+desc+"</p>";
  175. html += " </div>";
  176. html += " <div class=\"fourcol\">";
  177. html += " "+field;
  178. html += " </div>";
  179. html += " </fieldset>";
  180. return html;
  181. }
  182. Translator.prototype.getOutput = function(){
  183. var json = sanitize($("form#language").formToJSON(this));
  184. //json = json.substring(0,json.length-4).substring(17).replace(/\n\t\t/g,'\n\t')+'}';
  185. var css = (json) ? ' style="height:'+(json.split("\n").length + 5)+'em;font-family:monospace;"' : ''
  186. var output = '<textarea onfocus="this.select()"'+css+' wrap="off">'+json+"</textarea>";
  187. if($('#output').length == 0) $('#translation').after('<div id="output"></div>')
  188. $('#output').html(output);
  189. }
  190. /* From http://exceptionallyexceptionalexceptions.blogspot.co.uk/2011/12/convert-html-form-to-json.html */
  191. $.fn.formToJSON = function(t) {
  192. function setValue(object, path, value) {
  193. var a = path.split('.');
  194. var o = object;
  195. for (var i = 0; i < a.length - 1; i++) {
  196. var n = a[i];
  197. if (n in o) {
  198. o = o[n];
  199. } else {
  200. o[n] = {};
  201. o = o[n];
  202. }
  203. }
  204. o[a[a.length - 1]] = value;
  205. }
  206. if(t.phrasebook){
  207. // First of all we need to get a copy of the original JSON structure
  208. // otherwise we loose arrays
  209. var objectG = JSON.parse(JSON.stringify(t.phrasebook));
  210. //loop through all of the input/textarea elements of the form
  211. var el = this.find('input, textarea, select').each(function(i){
  212. //ignore the submit button
  213. if($(this).attr('name') != 'submit') setValue(objectG,$(this).attr('name').substr(1),converter($(this).val()))
  214. })
  215. }
  216. return JSON.stringify(objectG,null, " ");
  217. };
  218. function converter(tstr) {
  219. if(!tstr) return "";
  220. var bstr = '';
  221. for(var i=0; i<tstr.length; i++){
  222. if(tstr.charCodeAt(i)>127) bstr += '&amp;#' + tstr.charCodeAt(i) + ';';
  223. else bstr += tstr.charAt(i);
  224. }
  225. return bstr;
  226. }
  227. function sanitize(str){
  228. if(str){
  229. str = str.replace(/</g,"&lt;");
  230. str = str.replace(/>/g,"&gt;");
  231. str = str.replace(/"/g,"&quot;");
  232. }
  233. return str;
  234. }
  235. $.translator = function(placeholder,input) {
  236. if(typeof input=="object") input.container = placeholder;
  237. else {
  238. if(typeof placeholder=="string") input = { container: placeholder };
  239. else input = placeholder;
  240. }
  241. input.plugins = $.translator.plugins;
  242. return new Translator(input);
  243. };
  244. $.translator.plugins = [];
  245. })(jQuery);