lit 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +1 -1
- data/README.md +8 -5
- data/app/assets/images/lit/jquery-te.png +0 -0
- data/app/assets/javascripts/lit/application.js +1 -0
- data/app/assets/javascripts/lit/jquery-te-1.4.0.min.js +9 -0
- data/app/assets/javascripts/lit/localizations.js.coffee +7 -4
- data/app/assets/stylesheets/lit/application.css +1 -0
- data/app/assets/stylesheets/lit/jquery-te-1.4.0.css.scss +457 -0
- data/app/controllers/lit/localization_keys_controller.rb +47 -8
- data/app/models/lit/localization_key.rb +17 -1
- data/app/views/lit/localization_keys/index.html.erb +14 -9
- data/app/views/lit/localizations/_form.html.erb +5 -0
- data/app/views/lit/localizations/{edit.html.erb → edit.js.erb} +4 -1
- data/app/views/lit/sources/_form.html.erb +1 -1
- data/lib/lit/cache.rb +38 -5
- data/lib/lit/i18n_backend.rb +14 -6
- data/lib/lit/version.rb +1 -1
- metadata +8 -4
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Lost in translation
|
2
2
|
### Rails i18n web interface
|
3
3
|
|
4
|
-
Translate your apps with pleasure (sort of...) and for free. It's simple i18n
|
5
|
-
web interface, build on top of twitter bootstrap, that one may find helpful in
|
6
|
-
translating app by non-technicals.
|
4
|
+
Translate your apps with pleasure (sort of...) and for free. It's simple i18n
|
5
|
+
web interface, build on top of twitter bootstrap, that one may find helpful in
|
6
|
+
translating app by non-technicals.
|
7
7
|
|
8
8
|
Highly inspired by Copycopter by thoughtbot.
|
9
9
|
|
@@ -15,6 +15,7 @@ Highly inspired by Copycopter by thoughtbot.
|
|
15
15
|
4. Possibility to synchronize between environments or even apps
|
16
16
|
5. Easy to install - works as an engine, comes with simple generator
|
17
17
|
6. You can always export all translations to plain old YAML file
|
18
|
+
7. Has build in wysiwyg editor ([jQuery TE](http://jqueryte.com/))
|
18
19
|
|
19
20
|
### Screenshots
|
20
21
|
|
@@ -30,6 +31,7 @@ gem "lit"
|
|
30
31
|
2. run `bundle install`
|
31
32
|
|
32
33
|
3. run installation generator `bundle exec rails g lit:install`
|
34
|
+
(for production/staging environment `redis` is suggested as key value engine. `hash` will not work in multi process environment)
|
33
35
|
|
34
36
|
4. After doing above and restarting app, point your browser to ```http://app/lit```
|
35
37
|
|
@@ -41,17 +43,18 @@ You may want to take a look at generated initializer in `config/initializers/lit
|
|
41
43
|
|
42
44
|
### ToDo
|
43
45
|
|
44
|
-
* ~~Versioning~~
|
46
|
+
* ~~Versioning~~
|
45
47
|
* ~~API~~
|
46
48
|
* ~~Synchronization between environments~~
|
47
49
|
* Rewrite initializer
|
48
50
|
* Rewrite exporter (which is now code from copycopter)
|
49
51
|
* ~~Support for array types (ie. `date.abbr_day_names`)~~
|
50
52
|
* ~~Generator~~
|
51
|
-
* Support for wysiwyg
|
53
|
+
* ~~Support for wysiwyg~~
|
52
54
|
* Better cache
|
53
55
|
* ~~Support for other key value providers (ie. Redis does not support Array types in easy way)~~ (not applicable, as array storage works now with redis).
|
54
56
|
* Integration with ActiveAdmin
|
57
|
+
* Support for Proc defaults (like in `I18n.t("not_exising_keys", :default=> lambda{|_, options| "text"})` )
|
55
58
|
|
56
59
|
|
57
60
|
### License
|
Binary file
|
@@ -0,0 +1,9 @@
|
|
1
|
+
/*!
|
2
|
+
*
|
3
|
+
* jQuery TE 1.4.0 , http://jqueryte.com/
|
4
|
+
* Copyright (C) 2013, Fatih Koca (fattih@fattih.com), (http://jqueryte.com/about)
|
5
|
+
|
6
|
+
* jQuery TE is provided under the MIT LICENSE.
|
7
|
+
*
|
8
|
+
*/
|
9
|
+
(function(e){e.fn.jqte=function(t){function l(e,t,n,r,i){var s=f.length+1;return f.push({name:e,cls:s,command:t,key:n,tag:r,emphasis:i})}var n=[{title:"Text Format"},{title:"Font Size"},{title:"Color"},{title:"Bold",hotkey:"B"},{title:"Italic",hotkey:"I"},{title:"Underline",hotkey:"U"},{title:"Ordered List",hotkey:"."},{title:"Unordered List",hotkey:","},{title:"Subscript",hotkey:"down arrow"},{title:"Superscript",hotkey:"up arrow"},{title:"Outdent",hotkey:"left arrow"},{title:"Indent",hotkey:"right arrow"},{title:"Justify Left"},{title:"Justify Center"},{title:"Justify Right"},{title:"Strike Through",hotkey:"K"},{title:"Add Link",hotkey:"L"},{title:"Remove Link"},{title:"Cleaner Style",hotkey:"Delete"},{title:"Horizontal Rule",hotkey:"H"},{title:"Source"}];var r=[["p","Normal"],["h1","Header 1"],["h2","Header 2"],["h3","Header 3"],["h4","Header 4"],["h5","Header 5"],["h6","Header 6"],["pre","Preformatted"]];var i=["10","12","16","18","20","24","28"];var s=["0,0,0","68,68,68","102,102,102","153,153,153","204,204,204","238,238,238","243,243,243","255,255,255",null,"255,0,0","255,153,0","255,255,0","0,255,0","0,255,255","0,0,255","153,0,255","255,0,255",null,"244,204,204","252,229,205","255,242,204","217,234,211","208,224,227","207,226,243","217,210,233","234,209,220","234,153,153","249,203,156","255,229,153","182,215,168","162,196,201","159,197,232","180,167,214","213,166,189","224,102,102","246,178,107","255,217,102","147,196,125","118,165,175","111,168,220","142,124,195","194,123,160","204,0,0","230,145,56","241,194,50","106,168,79","69,129,142","61,133,198","103,78,167","166,77,121","153,0,0","180,95,6","191,144,0","56,118,29","19,79,92","11,83,148","53,28,117","116,27,71","102,0,0","120,63,4","127,96,0","39,78,19","12,52,61","7,55,99","32,18,77","76,17,48"];var o=["Web Address","E-mail Address","Picture URL"];var u=e.extend({status:true,css:"jqte",title:true,titletext:n,button:"OK",format:true,formats:r,fsize:true,fsizes:i,funit:"px",color:true,linktypes:o,b:true,i:true,u:true,ol:true,ul:true,sub:true,sup:true,outdent:true,indent:true,left:true,center:true,right:true,strike:true,link:true,unlink:true,remove:true,rule:true,source:true,placeholder:false,br:true,p:true,change:"",focus:"",blur:""},t);e.fn.jqteVal=function(t){e(this).closest("."+u.css).find("."+u.css+"_editor").html(t)};var a=navigator.userAgent.toLowerCase();if(/msie [1-7]./.test(a))u.title=false;var f=[];l("format","formats","","",false);l("fsize","fSize","","",false);l("color","colors","","",false);l("b","Bold","B",["b","strong"],true);l("i","Italic","I",["i","em"],true);l("u","Underline","U",["u"],true);l("ol","insertorderedlist","¾",["ol"],true);l("ul","insertunorderedlist","¼",["ul"],true);l("sub","subscript","(",["sub"],true);l("sup","superscript","&",["sup"],true);l("outdent","outdent","%",["blockquote"],false);l("indent","indent","'",["blockquote"],true);l("left","justifyLeft","","",false);l("center","justifyCenter","","",false);l("right","justifyRight","","",false);l("strike","strikeThrough","K",["strike"],true);l("link","linkcreator","L",["a"],true);l("unlink","unlink","",["a"],false);l("remove","removeformat",".","",false);l("rule","inserthorizontalrule","H",["hr"],false);l("source","displaysource","","",false);return this.each(function(){function B(){if(window.getSelection)return window.getSelection();else if(document.selection&&document.selection.createRange&&document.selection.type!="None")return document.selection.createRange()}function j(e,t){var n,r=B();if(window.getSelection){if(r.anchorNode&&r.getRangeAt)n=r.getRangeAt(0);if(n){r.removeAllRanges();r.addRange(n)}if(!a.match(/msie/))document.execCommand("StyleWithCSS",false,false);document.execCommand(e,false,t)}else if(document.selection&&document.selection.createRange&&document.selection.type!="None"){n=document.selection.createRange();n.execCommand(e,false,t)}q(false,false)}function F(t,n,r){if(v.not(":focus"))v.focus();if(window.getSelection){var i=B(),s,o,u;if(i.anchorNode&&i.getRangeAt){s=i.getRangeAt(0);o=document.createElement(t);e(o).attr(n,r);u=s.extractContents();o.appendChild(u);s.insertNode(o);i.removeAllRanges();if(n=="style")q(e(o),r);else q(e(o),false)}}else if(document.selection&&document.selection.createRange&&document.selection.type!="None"){var a=document.selection.createRange();var f=a.htmlText;var l="<"+t+" "+n+'="'+r+'">'+f+"</"+t+">";document.selection.createRange().pasteHTML(l)}}function q(e,t){var n=I();n=n?n:e;if(n&&t==false){if(n.parent().is("[style]"))n.attr("style",n.parent().attr("style"));if(n.is("[style]"))n.find("*").attr("style",n.attr("style"))}else if(e&&t&&e.is("[style]")){var r=t.split(";");r=r[0].split(":");if(e.is("[style*="+r[0]+"]"))e.find("*").css(r[0],r[1]);R(e)}}function R(t){if(t){var t=t[0];if(document.body.createTextRange){var n=document.body.createTextRange();n.moveToElementText(t);n.select()}else if(window.getSelection){var r=window.getSelection();var n=document.createRange();if(t!="undefined"&&t!=null){n.selectNodeContents(t);r.removeAllRanges();r.addRange(n);if(e(t).is(":empty")){e(t).append(" ");R(e(t))}}}}}function U(){if(!p.data("sourceOpened")){var t=I();var n="http://";W(true);if(t){var r=t.prop("tagName").toLowerCase();if(r=="a"&&t.is("[href]")){n=t.attr("href");t.attr(S,"")}else F("a",S,"")}else y.val(n).focus();g.click(function(t){if(e(t.target).hasClass(u.css+"_linktypetext")||e(t.target).hasClass(u.css+"_linktypearrow"))X(true)});w.find("a").click(function(){var t=e(this).attr(u.css+"-linktype");w.data("linktype",t);E.find("."+u.css+"_linktypetext").html(w.find("a:eq("+w.data("linktype")+")").text());V(n);X()});V(n);y.focus().val(n).bind("keypress keyup",function(e){if(e.keyCode==13){z(h.find("["+S+"]"));return false}});b.click(function(){z(h.find("["+S+"]"))})}else W(false)}function z(t){y.focus();R(t);t.removeAttr(S);if(w.data("linktype")!="2")j("createlink",y.val());else{j("insertImage",y.val());v.find("img").each(function(){var t=e(this).prev("a");var n=e(this).next("a");if(t.length>0&&t.html()=="")t.remove();else if(n.length>0&&n.html()=="")n.remove()})}W();v.trigger("change")}function W(e){Q("["+S+"]:not([href])");h.find("["+S+"][href]").removeAttr(S);if(e){p.data("linkOpened",true);d.show()}else{p.data("linkOpened",false);d.hide()}X()}function X(e){if(e)w.show();else w.hide()}function V(e){var t=w.data("linktype");if(t=="1"&&(y.val()=="http://"||y.is("[value^=http://]")||!y.is("[value^=mailto]")))y.val("mailto:");else if(t!="1"&&!y.is("[value^=http://]"))y.val("http://");else y.val(e)}function J(t){if(!p.data("sourceOpened")){if(t=="fSize")styleField=P;else if(t=="colors")styleField=H;K(styleField,true);styleField.find("a").unbind("click").click(function(){var n=e(this).attr(u.css+"-styleval");if(t=="fSize"){styleType="font-size";n=n+u.funit}else if(t=="colors"){styleType="color";n="rgb("+n+")"}var r=G(styleType);F("span","style",styleType+":"+n+";"+r);K("",false);e("."+u.css+"_title").remove();v.trigger("change")})}else K(styleField,false);W(false)}function K(e,t){var n="",r=[{d:"fsizeOpened",f:P},{d:"cpallOpened",f:H}];if(e!=""){for(var i=0;i<r.length;i++){if(e==r[i]["f"])n=r[i]}}if(t){p.data(n["d"],true);n["f"].slideDown(100);for(var i=0;i<r.length;i++){if(n["d"]!=r[i]["d"]){p.data(r[i]["d"],false);r[i]["f"].slideUp(100)}}}else{for(var i=0;i<r.length;i++){p.data(r[i]["d"],false);r[i]["f"].slideUp(100)}}}function Q(t){h.find(t).each(function(){e(this).before(e(this).html()).remove()})}function G(e){var t=I();if(t&&t.is("[style]")&&t.css(e)!=""){var n=t.css(e);t.css(e,"");var r=t.attr("style");t.css(e,n);return r}else return""}function Y(){Z(true);D.find("a").click(function(){e("*",this).click(function(e){e.preventDefault();return false});et(e(this).text());var t=e(this).attr(u.css+"-formatval");j("formatBlock","<"+t+">");Z(false)})}function Z(e){var t=e?true:false;t=e&&D.data("status")?true:false;if(t||!e)D.data("status",false).slideUp(200);else D.data("status",true).slideDown(200)}function et(e){var t=D.closest("."+u.css+"_tool").find("."+u.css+"_tool_label").find("."+u.css+"_tool_text");if(e.length>10)e=e.substr(0,7)+"...";t.html(e)}function tt(e){var t,n,r;t=e.replace(/\n/gim,"").replace(/\r/gim,"").replace(/\t/gim,"").replace(/ /gim," ");n=[/\<span(|\s+.*?)><span(|\s+.*?)>(.*?)<\/span><\/span>/gim,/<(\w*[^p])\s*[^\/>]*>\s*<\/\1>/gim,/\<div(|\s+.*?)>(.*?)\<\/div>/gim,/\<strong(|\s+.*?)>(.*?)\<\/strong>/gim,/\<em(|\s+.*?)>(.*?)\<\/em>/gim];r=["<span$2>$3</span>","","<p$1>$2</p>","<b$1>$2</b>","<i$1>$2</i>"];for(A=0;A<5;A++){for(var i=0;i<n.length;i++){t=t.replace(n[i],r[i])}}if(!u.p)t=t.replace(/\<p(|\s+.*?)>(.*?)\<\/p>/ig,"<br/>$2");if(!u.br){n=[/\<br>(.*?)/ig,/\<br\/>(.*?)/ig];r=["<p>$1</p>","<p>$1</p>"];for(var i=0;i<n.length;i++){t=t.replace(n[i],r[i])}}if(!u.p&&!u.br)t=t.replace(/\<p>(.*?)\<\/p>/ig,"<div>$1</div>");return t}function nt(){var e=v.text()==""&&v.html().length<12?"":v.html();l.val(tt(e))}function rt(){v.html(tt(l.val()))}function it(t){var n=false,r=I(),i;if(r){e.each(t,function(t,s){i=r.prop("tagName").toLowerCase();if(i==s)n=true;else{r.parents().each(function(){i=e(this).prop("tagName").toLowerCase();if(i==s)n=true})}});return n}else return false}function st(t){for(var n=0;n<f.length;n++){if(u[f[n].name]&&f[n].emphasis&&f[n].tag!="")it(f[n].tag)?p.find("."+u.css+"_tool_"+f[n].cls).addClass(m):e("."+u.css+"_tool_"+f[n].cls).removeClass(m)}if(u.format&&e.isArray(u.formats)){var r=false;for(var i=0;i<u.formats.length;i++){var s=[];s[0]=u.formats[i][0];if(u.formats[i][0].length>0&&it(s)){et(u.formats[i][1]);r=true;break}}if(!r)et(u.formats[0][1])}K("",false);Z(false)}if(!e(this).data("jqte")||e(this).data("jqte")==null||e(this).data("jqte")=="undefined")e(this).data("jqte",true);else e(this).data("jqte",false);if(!u.status||!e(this).data("jqte")){if(e(this).closest("."+u.css).length>0){var t=e(this).closest("."+u.css).find("."+u.css+"_editor").html();var n="";e(e(this)[0].attributes).each(function(){if(this.nodeName!="style")n=n+" "+this.nodeName+'="'+this.nodeValue+'"'});var r=e(this).is("[data-origin]")&&e(this).attr("data-origin")!=""?e(this).attr("data-origin"):"textarea";var i=">"+t;if(r=="input"||r=="option"){t=t.replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">");i='value="'+t+'">'}var o=e(this).clone();e(this).data("jqte",false).closest("."+u.css).before(o).remove();o.replaceWith("<"+r+n+i+"</"+r+">")}return}var l=e(this);var r=e(this).prop("tagName").toLowerCase();e(this).attr("data-origin",r);var c=e(this).is("[value]")||r=="textarea"?e(this).val():e(this).html();c=c.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&");e(this).after('<div class="'+u.css+'"></div>');var h=e(this).next("."+u.css);h.html('<div class="'+u.css+"_toolbar"+'" role="toolbar" unselectable></div><div class="'+u.css+'_linkform" style="display:none" role="dialog"></div><div class="'+u.css+"_editor"+'"></div>');var p=h.find("."+u.css+"_toolbar");var d=h.find("."+u.css+"_linkform");var v=h.find("."+u.css+"_editor");var m=u.css+"_tool_depressed";d.append('<div class="'+u.css+'_linktypeselect" unselectable></div><input class="'+u.css+'_linkinput" type="text/css" value=""><div class="'+u.css+'_linkbutton" unselectable>'+u.button+'</div> <div style="height:1px;float:none;clear:both"></div>');var g=d.find("."+u.css+"_linktypeselect");var y=d.find("."+u.css+"_linkinput");var b=d.find("."+u.css+"_linkbutton");g.append('<div class="'+u.css+'_linktypeview" unselectable></div><div class="'+u.css+'_linktypes" role="menu" unselectable></div>');var w=g.find("."+u.css+"_linktypes");var E=g.find("."+u.css+"_linktypeview");var S=u.css+"-setlink";v.after('<div class="'+u.css+"_source "+u.css+'_hiddenField"></div>');var x=h.find("."+u.css+"_source");l.appendTo(x);if(r!="textarea"){var n="";e(l[0].attributes).each(function(){if(this.nodeName!="type"&&this.nodeName!="value")n=n+" "+this.nodeName+'="'+this.nodeValue+'"'});l.replaceWith("<textarea "+n+">"+c+"</textarea>");l=x.find("textarea")}v.attr("contenteditable","true").html(c);for(var T=0;T<f.length;T++){if(u[f[T].name]){var N=f[T].key.length>0?u.titletext[T].hotkey!=null&&u.titletext[T].hotkey!="undefined"&&u.titletext[T].hotkey!=""?" (Ctrl+"+u.titletext[T].hotkey+")":"":"";var C=u.titletext[T].title!=null&&u.titletext[T].title!="undefined"&&u.titletext[T].title!=""?u.titletext[T].title+N:"";p.append('<div class="'+u.css+"_tool "+u.css+"_tool_"+f[T].cls+'" role="button" data-tool="'+T+'" unselectable><a class="'+u.css+'_tool_icon" unselectable></a></div>');p.find("."+u.css+"_tool[data-tool="+T+"]").data({tag:f[T].tag,command:f[T].command,emphasis:f[T].emphasis,title:C});if(f[T].name=="format"&&e.isArray(u.formats)){var k=u.formats[0][1].length>0&&u.formats[0][1]!="undefined"?u.formats[0][1]:"";p.find("."+u.css+"_tool_"+f[T].cls).find("."+u.css+"_tool_icon").replaceWith('<a class="'+u.css+'_tool_label" unselectable><span class="'+u.css+'_tool_text" unselectable>'+k+'</span><span class="'+u.css+'_tool_icon" unselectable></span></a>');p.find("."+u.css+"_tool_"+f[T].cls).append('<div class="'+u.css+'_formats" unselectable></div>');for(var L=0;L<u.formats.length;L++){p.find("."+u.css+"_formats").append("<a "+u.css+'-formatval="'+u.formats[L][0]+'" class="'+u.css+"_format"+" "+u.css+"_format_"+L+'" role="menuitem" unselectable>'+u.formats[L][1]+"</a>")}p.find("."+u.css+"_formats").data("status",false)}else if(f[T].name=="fsize"&&e.isArray(u.fsizes)){p.find("."+u.css+"_tool_"+f[T].cls).append('<div class="'+u.css+'_fontsizes" unselectable></div>');for(var L=0;L<u.fsizes.length;L++){p.find("."+u.css+"_fontsizes").append("<a "+u.css+'-styleval="'+u.fsizes[L]+'" class="'+u.css+"_fontsize"+'" style="font-size:'+u.fsizes[L]+u.funit+'" role="menuitem" unselectable>Abcdefgh...</a>')}}else if(f[T].name=="color"&&e.isArray(s)){p.find("."+u.css+"_tool_"+f[T].cls).append('<div class="'+u.css+'_cpalette" unselectable></div>');for(var A=0;A<s.length;A++){if(s[A]!=null)p.find("."+u.css+"_cpalette").append("<a "+u.css+'-styleval="'+s[A]+'" class="'+u.css+"_color"+'" style="background-color: rgb('+s[A]+')" role="gridcell" unselectable></a>');else p.find("."+u.css+"_cpalette").append('<div class="'+u.css+"_colorSeperator"+'"></div>')}}}}w.data("linktype","0");for(var T=0;T<3;T++){w.append("<a "+u.css+'-linktype="'+T+'" unselectable>'+u.linktypes[T]+"</a>");E.html('<div class="'+u.css+'_linktypearrow" unselectable></div><div class="'+u.css+'_linktypetext">'+w.find("a:eq("+w.data("linktype")+")").text()+"</div>")}var O="";if(/msie/.test(a))O="-ms-";else if(/chrome/.test(a)||/safari/.test(a)||/yandex/.test(a))O="-webkit-";else if(/mozilla/.test(a))O="-moz-";else if(/opera/.test(a))O="-o-";else if(/konqueror/.test(a))O="-khtml-";else O="";if(u.placeholder&&u.placeholder!=""){h.prepend('<div class="'+u.css+'_placeholder" unselectable><div class="'+u.css+'_placeholder_text">'+u.placeholder+"</div></div>");var M=h.find("."+u.css+"_placeholder");M.click(function(){v.focus()})}h.find("[unselectable]").css(O+"user-select","none").addClass("unselectable").attr("unselectable","on").on("selectstart mousedown",false);var _=p.find("."+u.css+"_tool");var D=p.find("."+u.css+"_formats");var P=p.find("."+u.css+"_fontsizes");var H=p.find("."+u.css+"_cpalette");var I=function(){var t,n;if(window.getSelection){n=getSelection();t=n.anchorNode}if(!t&&document.selection&&document.selection.createRange&&document.selection.type!="None"){n=document.selection;var r=n.getRangeAt?n.getRangeAt(0):n.createRange();t=r.commonAncestorContainer?r.commonAncestorContainer:r.parentElement?r.parentElement():r.item(0)}if(t){return t.nodeName=="#text"?e(t.parentNode):e(t)}else return false};_.unbind("click").click(function(t){if(e(this).data("command")=="displaysource"&&!p.data("sourceOpened")){p.find("."+u.css+"_tool").addClass(u.css+"_hiddenField");e(this).removeClass(u.css+"_hiddenField");p.data("sourceOpened",true);l.css("height",v.outerHeight());x.removeClass(u.css+"_hiddenField");v.addClass(u.css+"_hiddenField");l.focus();W(false);K("",false);Z();if(u.placeholder&&u.placeholder!="")M.hide()}else{if(!p.data("sourceOpened")){if(e(this).data("command")=="linkcreator"){if(!p.data("linkOpened"))U();else{W(false);Z(false)}}else if(e(this).data("command")=="formats"){if(e(this).data("command")=="formats"&&!e(t.target).hasClass(u.css+"_format"))Y();K("",false);if(v.not(":focus"))v.focus()}else if(e(this).data("command")=="fSize"||e(this).data("command")=="colors"){if(e(this).data("command")=="fSize"&&!e(t.target).hasClass(u.css+"_fontsize")||e(this).data("command")=="colors"&&!e(t.target).hasClass(u.css+"_color"))J(e(this).data("command"));Z(false);if(v.not(":focus"))v.focus()}else{if(v.not(":focus"))v.focus();j(e(this).data("command"),null);K("",false);Z(false);X();e(this).data("emphasis")==true&&!e(this).hasClass(m)?e(this).addClass(m):e(this).removeClass(m);x.addClass(u.css+"_hiddenField");v.removeClass(u.css+"_hiddenField")}}else{p.data("sourceOpened",false);p.find("."+u.css+"_tool").removeClass(u.css+"_hiddenField");x.addClass(u.css+"_hiddenField");v.removeClass(u.css+"_hiddenField")}if(u.placeholder&&u.placeholder!="")v.html()!=""?M.hide():M.show()}v.trigger("change")}).hover(function(t){if(u.title&&e(this).data("title")!=""&&(e(t.target).hasClass(u.css+"_tool")||e(t.target).hasClass(u.css+"_tool_icon"))){e("."+u.css+"_title").remove();h.append('<div class="'+u.css+'_title"><div class="'+u.css+'_titleArrow"><div class="'+u.css+'_titleArrowIcon"></div></div><div class="'+u.css+'_titleText">'+e(this).data("title")+"</div></div>");var n=e("."+u.css+"_title:first");var r=n.find("."+u.css+"_titleArrowIcon");var i=e(this).position();var s=i.left+e(this).outerWidth()-n.outerWidth()/2-e(this).outerWidth()/2;var o=i.top+e(this).outerHeight()+5;n.delay(400).css({top:o,left:s}).fadeIn(200)}},function(){e("."+u.css+"_title").remove()});var ot=null;v.bind("keypress keyup keydown drop cut copy paste DOMCharacterDataModified DOMSubtreeModified",function(){if(!p.data("sourceOpened"))e(this).trigger("change");X();if(e.isFunction(u.change))u.change();if(u.placeholder&&u.placeholder!="")e(this).text()!=""?M.hide():M.show()}).bind("change",function(){if(!p.data("sourceOpened")){clearTimeout(ot);ot=setTimeout(nt,10)}}).keydown(function(e){if(e.ctrlKey){for(var t=0;t<f.length;t++){if(u[f[t].name]&&e.keyCode==f[t].key.charCodeAt(0)){if(f[t].command!=""&&f[t].command!="linkcreator")j(f[t].command,null);else if(f[t].command=="linkcreator")U();return false}}}}).bind("mouseup keyup",st).focus(function(){if(e.isFunction(u.focus))u.focus();h.addClass(u.css+"_focused");if(/opera/.test(a)){var t=document.createRange();t.selectNodeContents(v[0]);t.collapse(false);var n=window.getSelection();n.removeAllRanges();n.addRange(t)}}).focusout(function(){_.removeClass(m);K("",false);Z(false);X();if(e.isFunction(u.blur))u.blur();h.removeClass(u.css+"_focused");if(e.isArray(u.formats))et(u.formats[0][1])});l.bind("keydown keyup",function(){setTimeout(rt,0);e(this).height(e(this)[0].scrollHeight);if(e(this).val()=="")e(this).height(0)}).focus(function(){h.addClass(u.css+"_focused")}).focusout(function(){h.removeClass(u.css+"_focused")})})}})(jQuery)
|
@@ -2,10 +2,11 @@
|
|
2
2
|
$(document).ready ->
|
3
3
|
$('td.localization_row[data-editing=0]').on 'click', ->
|
4
4
|
$this = $(this)
|
5
|
-
|
6
|
-
|
7
|
-
$this.data('editing'
|
8
|
-
|
5
|
+
if parseInt($this.data('editing'))==0
|
6
|
+
edited_rows[$this.data('id')] = $this.html()
|
7
|
+
unless parseInt($this.data('editing'))
|
8
|
+
$this.data('editing', '1')
|
9
|
+
$.get $this.data('edit')
|
9
10
|
$('td.localization_row').on 'click', 'form button.cancel', (e)->
|
10
11
|
$this = $(this)
|
11
12
|
if $this[0].localName=='button'
|
@@ -19,3 +20,5 @@ $(document).ready ->
|
|
19
20
|
$parent = $this.parents('tr.localization_versions_row')
|
20
21
|
$parent.addClass('hidden')
|
21
22
|
$parent.children('td').html('')
|
23
|
+
$('tr.localization_key_row').on 'click', 'input.wysiwyg_switch', (e)->
|
24
|
+
$(this).parents('form').find("textarea").jqte()
|
@@ -0,0 +1,457 @@
|
|
1
|
+
/*!
|
2
|
+
*
|
3
|
+
* jQuery TE 1.4.0 , http://jqueryte.com/
|
4
|
+
* Copyright (C) 2013, Fatih Koca (fattih@fattih.com), (http://jqueryte.com/about)
|
5
|
+
|
6
|
+
* jQuery TE is provided under the MIT LICENSE.
|
7
|
+
*
|
8
|
+
*/
|
9
|
+
|
10
|
+
/* editor's general field */
|
11
|
+
.jqte {
|
12
|
+
/*margin:30px 0;
|
13
|
+
border:#000 1px solid;
|
14
|
+
border-radius:5px; -webkit-border-radius:5px; -moz-border-radius:5px;
|
15
|
+
box-shadow:0 0 3px #999; -webkit-box-shadow:0 0 3px #999; -moz-box-shadow:0 0 3px #999;
|
16
|
+
overflow:hidden;
|
17
|
+
transition:box-shadow 0.4s, border 0.4s; -webkit-transition:-webkit-box-shadow 0.4s, border 0.4s; -moz-transition:-moz-box-shadow 0.4s, border 0.4s; -o-transition:-o-box-shadow 0.4s, border 0.4s;
|
18
|
+
}
|
19
|
+
.jqte * {
|
20
|
+
color:#333;
|
21
|
+
font-family:Arial, Helvetica, sans-serif;
|
22
|
+
font-size:14px;
|
23
|
+
}
|
24
|
+
.jqte_focused {
|
25
|
+
border-color:#00AAE7;
|
26
|
+
box-shadow:0 0 10px #00BDFF; -webkit-box-shadow:0 0 10px #00BDFF; -moz-box-shadow:0 0 10px #00BDFF;
|
27
|
+
}
|
28
|
+
/* toolbar */
|
29
|
+
.jqte_toolbar {
|
30
|
+
overflow:auto;
|
31
|
+
padding:3px 4px;
|
32
|
+
background:#EEE;
|
33
|
+
border-bottom:#BBB 1px solid;
|
34
|
+
}
|
35
|
+
.jqte_tool {
|
36
|
+
float:left;
|
37
|
+
margin:0;
|
38
|
+
padding:0;
|
39
|
+
cursor:pointer;
|
40
|
+
}
|
41
|
+
.jqte_tool, .jqte_tool_icon, .jqte_tool_label {
|
42
|
+
border:#EEE 1px solid;
|
43
|
+
border-radius:3px; -webkit-border-radius:3px; -moz-border-radius:3px
|
44
|
+
}
|
45
|
+
.jqte_hiddenField {
|
46
|
+
display:none
|
47
|
+
}
|
48
|
+
.jqte_tool_icon {
|
49
|
+
display:block;
|
50
|
+
width:22px;
|
51
|
+
height:22px;
|
52
|
+
background:image-url('lit/jquery-te.png') no-repeat
|
53
|
+
}
|
54
|
+
.jqte_tool.jqte_tool_1 .jqte_tool_label {
|
55
|
+
position:relative;
|
56
|
+
display:block;
|
57
|
+
padding:3px;
|
58
|
+
width:70px;
|
59
|
+
height:16px;
|
60
|
+
overflow:hidden;
|
61
|
+
}
|
62
|
+
.jqte_tool.jqte_tool_1 .jqte_tool_text {
|
63
|
+
font:bold 13px Arial,sans-serif;
|
64
|
+
color:#222;
|
65
|
+
}
|
66
|
+
.jqte_tool.jqte_tool_1 .jqte_tool_icon {
|
67
|
+
position:absolute;
|
68
|
+
top:10px;
|
69
|
+
right:2px;
|
70
|
+
width:6px;
|
71
|
+
height:4px;
|
72
|
+
background-position:-19px -23px;
|
73
|
+
border:none;
|
74
|
+
border-radius:none; -webkit-border-radius:none; -moz-border-radius:none
|
75
|
+
}
|
76
|
+
.jqte_tool.jqte_tool_2 .jqte_tool_icon {
|
77
|
+
background-position:0 0
|
78
|
+
}
|
79
|
+
.jqte_tool.jqte_tool_3 .jqte_tool_icon {
|
80
|
+
background-position:-22px 0
|
81
|
+
}
|
82
|
+
.jqte_tool.jqte_tool_4 .jqte_tool_icon {
|
83
|
+
background-position:-44px 0
|
84
|
+
}
|
85
|
+
.jqte_tool.jqte_tool_5 .jqte_tool_icon {
|
86
|
+
background-position:-66px 0
|
87
|
+
}
|
88
|
+
.jqte_tool.jqte_tool_6 .jqte_tool_icon {
|
89
|
+
background-position:-88px 0
|
90
|
+
}
|
91
|
+
.jqte_tool.jqte_tool_7 .jqte_tool_icon {
|
92
|
+
background-position:-110px 0
|
93
|
+
}
|
94
|
+
.jqte_tool.jqte_tool_8 .jqte_tool_icon {
|
95
|
+
background-position:-132px 0
|
96
|
+
}
|
97
|
+
.jqte_tool.jqte_tool_9 .jqte_tool_icon {
|
98
|
+
background-position:-154px 0
|
99
|
+
}
|
100
|
+
.jqte_tool.jqte_tool_10 .jqte_tool_icon {
|
101
|
+
background-position:-176px 0
|
102
|
+
}
|
103
|
+
.jqte_tool.jqte_tool_11 .jqte_tool_icon {
|
104
|
+
background-position:-198px 0
|
105
|
+
}
|
106
|
+
.jqte_tool.jqte_tool_12 .jqte_tool_icon {
|
107
|
+
background-position:-220px 0
|
108
|
+
}
|
109
|
+
.jqte_tool.jqte_tool_13 .jqte_tool_icon {
|
110
|
+
background-position:-242px 0
|
111
|
+
}
|
112
|
+
.jqte_tool.jqte_tool_14 .jqte_tool_icon {
|
113
|
+
background-position:-264px 0
|
114
|
+
}
|
115
|
+
.jqte_tool.jqte_tool_15 .jqte_tool_icon {
|
116
|
+
background-position:-286px 0
|
117
|
+
}
|
118
|
+
.jqte_tool.jqte_tool_16 .jqte_tool_icon {
|
119
|
+
background-position:-308px 0
|
120
|
+
}
|
121
|
+
.jqte_tool.jqte_tool_17 .jqte_tool_icon {
|
122
|
+
background-position:-330px 0
|
123
|
+
}
|
124
|
+
.jqte_tool.jqte_tool_18 .jqte_tool_icon {
|
125
|
+
background-position:-352px 0
|
126
|
+
}
|
127
|
+
.jqte_tool.jqte_tool_19 .jqte_tool_icon {
|
128
|
+
background-position:-374px 0
|
129
|
+
}
|
130
|
+
.jqte_tool.jqte_tool_20 .jqte_tool_icon {
|
131
|
+
background-position:-396px 0
|
132
|
+
}
|
133
|
+
.jqte_tool.jqte_tool_21 .jqte_tool_icon {
|
134
|
+
background-position:-418px 0
|
135
|
+
}
|
136
|
+
.jqte_tool:hover {
|
137
|
+
background-color:#FFF;
|
138
|
+
border-color:#FFF
|
139
|
+
}
|
140
|
+
.jqte_tool:hover .jqte_tool_icon, .jqte_tool:hover .jqte_tool_label {
|
141
|
+
border:#AAA 1px solid
|
142
|
+
}
|
143
|
+
.jqte_tool:active .jqte_tool_icon, .jqte_tool:active .jqte_tool_label {
|
144
|
+
border:#777 1px solid
|
145
|
+
}
|
146
|
+
.jqte_tool.jqte_tool_1:hover .jqte_tool_icon, .jqte_tool.jqte_tool_1:active .jqte_tool_icon {
|
147
|
+
border:none
|
148
|
+
}
|
149
|
+
.jqte_tool_depressed {
|
150
|
+
background-color:#DDD;
|
151
|
+
border-color:#CCC
|
152
|
+
}
|
153
|
+
.jqte_tool_depressed .jqte_tool_icon {
|
154
|
+
border-color:#AAA
|
155
|
+
}
|
156
|
+
.jqte_tool_depressed:hover {
|
157
|
+
background-color:#EEE
|
158
|
+
}
|
159
|
+
/* link form area */
|
160
|
+
.jqte_linkform {
|
161
|
+
padding:5px 10px;
|
162
|
+
background:#DDD;
|
163
|
+
border-bottom:#BBB 1px solid;
|
164
|
+
}
|
165
|
+
.jqte_linktypeselect {
|
166
|
+
position:relative;
|
167
|
+
float:left;
|
168
|
+
width:130px;
|
169
|
+
background:#EEE;
|
170
|
+
cursor:pointer
|
171
|
+
}
|
172
|
+
.jqte_linktypeselect:Active {
|
173
|
+
background:#FFF
|
174
|
+
}
|
175
|
+
.jqte_linktypeview {
|
176
|
+
padding:3px 5px;
|
177
|
+
border:#333 1px solid;
|
178
|
+
color:#777;
|
179
|
+
border-radius:3px; -webkit-border-radius:3px; -moz-border-radius:3px;
|
180
|
+
outline:none
|
181
|
+
}
|
182
|
+
.jqte_linktypetext {
|
183
|
+
font-size:12px;
|
184
|
+
}
|
185
|
+
.jqte_linktypearrow {
|
186
|
+
position:absolute;
|
187
|
+
bottom:8px; right:6px;
|
188
|
+
width:7px;
|
189
|
+
height:6px;
|
190
|
+
margin:0 auto;
|
191
|
+
background:image-url('lit/jquery-te.png') -7px -23px no-repeat;
|
192
|
+
}
|
193
|
+
.jqte_linktypes {
|
194
|
+
display:none;
|
195
|
+
position:absolute;
|
196
|
+
top:22px; left:1px;
|
197
|
+
width:125px;
|
198
|
+
background:#FFF;
|
199
|
+
border:#333 1px solid;
|
200
|
+
box-shadow:0 1px 4px #AAA; -webkit-box-shadow:0 1px 4px #AAA; -moz-box-shadow:0 1px 4px #AAA
|
201
|
+
}
|
202
|
+
.jqte_linktypes a {
|
203
|
+
display:block;
|
204
|
+
padding:4px 5px;
|
205
|
+
font-size:12px;
|
206
|
+
}
|
207
|
+
.jqte_linktypes a:hover {
|
208
|
+
background:#DDD
|
209
|
+
}
|
210
|
+
.jqte_linkinput {
|
211
|
+
float:left;
|
212
|
+
margin:0 5px;
|
213
|
+
padding:3px 5px;
|
214
|
+
width:300px;
|
215
|
+
background:#EEE;
|
216
|
+
border:#333 1px solid;
|
217
|
+
color:#777;
|
218
|
+
font-size:12px;
|
219
|
+
border-radius:3px; -webkit-border-radius:3px; -moz-border-radius:3px;
|
220
|
+
outline:none;
|
221
|
+
}
|
222
|
+
.jqte_linkinput:focus, .jqte_linkinput:hover {
|
223
|
+
background:#FFF;
|
224
|
+
border-color:#000;
|
225
|
+
}
|
226
|
+
.jqte_linkbutton {
|
227
|
+
float:left;
|
228
|
+
padding:3px 12px;
|
229
|
+
background:#AAA;
|
230
|
+
border:#333 1px solid;
|
231
|
+
color:#FFF;
|
232
|
+
font-size:12px;
|
233
|
+
font-weight:bold;
|
234
|
+
cursor:pointer;
|
235
|
+
border-radius:3px; -webkit-border-radius:3px; -moz-border-radius:3px;
|
236
|
+
box-shadow:inset 0 1px #EEE; -webkit-box-shadow:inset 0 1px #EEE; -moz-box-shadow:inset 0 1px #EEE;
|
237
|
+
}
|
238
|
+
.jqte_linkbutton:hover {
|
239
|
+
background:#A1A1A1
|
240
|
+
}
|
241
|
+
.jqte_linkbutton:active {
|
242
|
+
box-shadow:inset 0 1px #CCC; -webkit-box-shadow:inset 0 1px #CCC; -moz-box-shadow:inset 0 1px #CCC;
|
243
|
+
background:#888;
|
244
|
+
}
|
245
|
+
|
246
|
+
/* text format menu */
|
247
|
+
.jqte_formats {
|
248
|
+
display:none;
|
249
|
+
position:absolute;
|
250
|
+
width:180px;
|
251
|
+
oveflow-x:hidden;
|
252
|
+
overflow-y:auto;
|
253
|
+
background:#FFF;
|
254
|
+
border:#AAA 1px solid;
|
255
|
+
box-shadow:0 0 5px #AAA; -webkit-box-shadow:0 0 5px #AAA; -moz-box-shadow:0 0 5px #AAA;
|
256
|
+
z-index:100;
|
257
|
+
}
|
258
|
+
.jqte_format {
|
259
|
+
display:block;
|
260
|
+
padding:4px 7px;
|
261
|
+
font-size:13px
|
262
|
+
}
|
263
|
+
.jqte_format:hover {
|
264
|
+
background:#DDD
|
265
|
+
}
|
266
|
+
.jqte_format_1, .jqte_format_2, .jqte_format_3, .jqte_format_4, .jqte_format_5, .jqte_format_6 {
|
267
|
+
font-weight:bold
|
268
|
+
}
|
269
|
+
.jqte_format_1 {
|
270
|
+
font-size:22px
|
271
|
+
}
|
272
|
+
.jqte_format_2 {
|
273
|
+
font-size:20px
|
274
|
+
}
|
275
|
+
.jqte_format_3 {
|
276
|
+
font-size:18px
|
277
|
+
}
|
278
|
+
.jqte_format_4 {
|
279
|
+
font-size:16px
|
280
|
+
}
|
281
|
+
.jqte_format_5 {
|
282
|
+
font-size:14px
|
283
|
+
}
|
284
|
+
.jqte_format_6 {
|
285
|
+
font-size:12px
|
286
|
+
}
|
287
|
+
.jqte_format_7 {
|
288
|
+
font-family:"Courier New", Courier, monospace
|
289
|
+
}
|
290
|
+
|
291
|
+
/* font size menu */
|
292
|
+
.jqte_fontsizes {
|
293
|
+
display:none;
|
294
|
+
position:absolute;
|
295
|
+
width:180px;
|
296
|
+
height:198px;
|
297
|
+
oveflow-x:hidden;
|
298
|
+
overflow-y:auto;
|
299
|
+
background:#FFF;
|
300
|
+
border:#AAA 1px solid;
|
301
|
+
box-shadow:0 0 5px #AAA; -webkit-box-shadow:0 0 5px #AAA; -moz-box-shadow:0 0 5px #AAA
|
302
|
+
}
|
303
|
+
.jqte_fontsize {
|
304
|
+
display:block;
|
305
|
+
padding:3px 7px;
|
306
|
+
}
|
307
|
+
.jqte_fontsize:hover {
|
308
|
+
background:#DDD
|
309
|
+
}
|
310
|
+
|
311
|
+
/* color pallette */
|
312
|
+
.jqte_cpalette {
|
313
|
+
display:none;
|
314
|
+
position:absolute;
|
315
|
+
padding:6px;
|
316
|
+
width:144px;
|
317
|
+
background:#FFF;
|
318
|
+
border:#AAA 1px solid;
|
319
|
+
box-shadow:0 0 5px #AAA; -webkit-box-shadow:0 0 5px #AAA; -moz-box-shadow:0 0 5px #AAA
|
320
|
+
}
|
321
|
+
.jqte_color {
|
322
|
+
display:block;
|
323
|
+
float:left;
|
324
|
+
width:16px;
|
325
|
+
height:16px;
|
326
|
+
border:#FFF 1px solid;
|
327
|
+
}
|
328
|
+
.jqte_color:hover {
|
329
|
+
border-color:#000
|
330
|
+
}
|
331
|
+
.jqte_colorSeperator {
|
332
|
+
float:none;
|
333
|
+
clear:both;
|
334
|
+
height:7px;
|
335
|
+
}
|
336
|
+
|
337
|
+
/* editor area */
|
338
|
+
.jqte_editor, .jqte_source {
|
339
|
+
padding:10px;
|
340
|
+
background:#FFF;
|
341
|
+
min-height:100px;
|
342
|
+
max-height:900px;
|
343
|
+
overflow:auto;
|
344
|
+
outline:none;
|
345
|
+
word-wrap:break-word; -ms-word-wrap:break-word;
|
346
|
+
resize:vertical
|
347
|
+
}
|
348
|
+
.jqte_editor div, .jqte_editor p {
|
349
|
+
margin:0 0 7px
|
350
|
+
}
|
351
|
+
.jqte_editor a:link, .jqte_editor a:link * {
|
352
|
+
color:#0066FF !important;
|
353
|
+
text-decoration:underline;
|
354
|
+
}
|
355
|
+
.jqte_editor blockquote {
|
356
|
+
margin-top:0;
|
357
|
+
margin-bottom:7px
|
358
|
+
}
|
359
|
+
.jqte_editor img {
|
360
|
+
float:left;
|
361
|
+
margin:0 10px 5px 0
|
362
|
+
}
|
363
|
+
.jqte_editor a[jqte-setlink], .jqte_editor a[jqte-setlink] * {
|
364
|
+
background:#3297FD !important;
|
365
|
+
color:#FFF !important
|
366
|
+
}
|
367
|
+
.jqte_editor h1, .jqte_editor h2, .jqte_editor h3, .jqte_editor h4, .jqte_editor h5, .jqte_editor h6, .jqte_editor pre {
|
368
|
+
display:block;
|
369
|
+
margin:0 0 3px;
|
370
|
+
}
|
371
|
+
.jqte_editor h1, .jqte_editor h1 * {
|
372
|
+
font-size:26px
|
373
|
+
}
|
374
|
+
.jqte_editor h2, .jqte_editor h2 * {
|
375
|
+
font-size:24px
|
376
|
+
}
|
377
|
+
.jqte_editor h3, .jqte_editor h3 * {
|
378
|
+
font-size:22px
|
379
|
+
}
|
380
|
+
.jqte_editor h4, .jqte_editor h4 * {
|
381
|
+
font-size:20px
|
382
|
+
}
|
383
|
+
.jqte_editor h5, .jqte_editor h5 * {
|
384
|
+
font-size:18px
|
385
|
+
}
|
386
|
+
.jqte_editor h6, .jqte_editor h6 * {
|
387
|
+
font-size:15px
|
388
|
+
}
|
389
|
+
.jqte_editor pre, .jqte_editor pre * {
|
390
|
+
font-family:"Courier New", Courier, monospace
|
391
|
+
}
|
392
|
+
|
393
|
+
/* source area */
|
394
|
+
.jqte_source, .jqte_source textarea {
|
395
|
+
background:#FFF1E8
|
396
|
+
}
|
397
|
+
.jqte_source textarea {
|
398
|
+
margin:0 !important;
|
399
|
+
padding:0 !important;
|
400
|
+
display:block !important;
|
401
|
+
width:100% !important;
|
402
|
+
min-height:100px;
|
403
|
+
font-family:Courier, Arial, sans-serif !important;
|
404
|
+
font-weight:normal;
|
405
|
+
font-size:15px;
|
406
|
+
overflow:hidden !important;
|
407
|
+
outline:none;
|
408
|
+
resize:none;
|
409
|
+
}
|
410
|
+
.jqte_source textarea, .jqte_source textarea:focus {
|
411
|
+
css_shadow:none !important;
|
412
|
+
background:none !important;
|
413
|
+
border:none !important;
|
414
|
+
}
|
415
|
+
|
416
|
+
/* title box */
|
417
|
+
.jqte_title {
|
418
|
+
display:none;
|
419
|
+
position:absolute;
|
420
|
+
z-index:9999;
|
421
|
+
}
|
422
|
+
.jqte_titleArrow {
|
423
|
+
position:relative;
|
424
|
+
}
|
425
|
+
.jqte_titleArrowIcon {
|
426
|
+
width:7px;
|
427
|
+
height:6px;
|
428
|
+
margin:0 auto;
|
429
|
+
background:image-url('lit/jquery-te.png') 0 -23px no-repeat;
|
430
|
+
}
|
431
|
+
.jqte_titleText {
|
432
|
+
padding:5px 7px;
|
433
|
+
margin-top:0;
|
434
|
+
min-width:5px;
|
435
|
+
min-height:1px;
|
436
|
+
max-width:400px;
|
437
|
+
background:#000;
|
438
|
+
border-radius:3px; -webkit-border-radius:3px; -moz-border-radius:3px;
|
439
|
+
word-wrap:break-word; -ms-word-wrap:break-word
|
440
|
+
}
|
441
|
+
.jqte_titleText, .jqte_titleText * {
|
442
|
+
color:#FFF;
|
443
|
+
font-size:11px
|
444
|
+
}
|
445
|
+
|
446
|
+
/* placeholder */
|
447
|
+
.jqte_placeholder {
|
448
|
+
position:relative;
|
449
|
+
display:none;
|
450
|
+
}
|
451
|
+
.jqte_placeholder_text {
|
452
|
+
position:absolute;
|
453
|
+
top:43px;
|
454
|
+
left:10px;
|
455
|
+
font-size:14px;
|
456
|
+
color:#CCC;
|
457
|
+
}
|
@@ -36,16 +36,12 @@ module Lit
|
|
36
36
|
def get_localization_scope
|
37
37
|
@search_options = params.slice(*valid_keys)
|
38
38
|
@search_options[:include_completed] = '1' if @search_options.empty?
|
39
|
-
@scope = LocalizationKey.uniq.search(@search_options)
|
39
|
+
@scope = LocalizationKey.uniq.preload(:localizations => :locale).search(@search_options)
|
40
40
|
end
|
41
41
|
|
42
42
|
def get_localization_keys
|
43
|
-
key_parts =
|
44
|
-
|
45
|
-
else
|
46
|
-
0
|
47
|
-
end
|
48
|
-
@prefixes = @scope.uniq.pluck(:localization_key).map{|lk| lk.split('.').shift(key_parts+1).join('.') }.uniq.sort
|
43
|
+
key_parts = @search_options[:key_prefix].to_s.split('.').length
|
44
|
+
@prefixes = @scope.reorder(nil).uniq.pluck(:localization_key).map{|lk| lk.split('.').shift(key_parts+1).join('.') }.uniq.sort
|
49
45
|
if @search_options[:key_prefix].present?
|
50
46
|
parts = @search_options[:key_prefix].split('.')
|
51
47
|
@parent_prefix = parts[0,parts.length-1].join('.')
|
@@ -58,8 +54,51 @@ module Lit
|
|
58
54
|
end
|
59
55
|
|
60
56
|
def valid_keys
|
61
|
-
%w( key include_completed key_prefix )
|
57
|
+
%w( key include_completed key_prefix order )
|
62
58
|
end
|
63
59
|
|
60
|
+
def grouped_localizations
|
61
|
+
@_grouped_localizations ||= begin
|
62
|
+
{}.tap do |hash|
|
63
|
+
@localization_keys.each do |lk|
|
64
|
+
hash[lk] = {}
|
65
|
+
lk.localizations.each do |l|
|
66
|
+
hash[lk][l.locale.locale.to_sym] = l
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def localization_for(locale, localization_key)
|
74
|
+
@_localization_for ||= {}
|
75
|
+
key = [locale, localization_key]
|
76
|
+
ret = @_localization_for[key]
|
77
|
+
if ret == false
|
78
|
+
nil
|
79
|
+
elsif ret.nil?
|
80
|
+
ret = grouped_localizations[localization_key][locale]
|
81
|
+
unless ret
|
82
|
+
Lit.init.cache.refresh_key("#{locale}.#{localization_key.localization_key}")
|
83
|
+
ret = localization_key.localizations.where(:locale_id=>Lit.init.cache.find_locale(locale).id).first
|
84
|
+
end
|
85
|
+
@_localization_for[key] = ret ? ret : false
|
86
|
+
else
|
87
|
+
ret
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
helper_method :localization_for
|
93
|
+
|
94
|
+
def has_versions?(localization)
|
95
|
+
@_versions ||= begin
|
96
|
+
ids = grouped_localizations.values.map(&:values).flatten.map(&:id)
|
97
|
+
Lit::Localization.where(:id => ids).joins(:versions).group("#{Lit::Localization.quoted_table_name}.id").count
|
98
|
+
end
|
99
|
+
@_versions[localization.id].to_i > 0
|
100
|
+
end
|
101
|
+
|
102
|
+
helper_method :has_versions?
|
64
103
|
end
|
65
104
|
end
|
@@ -52,8 +52,24 @@ module Lit
|
|
52
52
|
mark_completed!
|
53
53
|
end
|
54
54
|
|
55
|
+
def self.order_options
|
56
|
+
["localization_key asc", "localization_key desc", "created_at asc", "created_at desc"]
|
57
|
+
end
|
58
|
+
|
59
|
+
# it can be overridden in parent application, for example: {:order => "created_at desc"}
|
60
|
+
def self.default_search_options
|
61
|
+
{}
|
62
|
+
end
|
63
|
+
|
55
64
|
def self.search(options={})
|
56
|
-
|
65
|
+
options = options.reverse_merge(default_search_options)
|
66
|
+
s = self
|
67
|
+
if options[:order] && order_options.include?(options[:order])
|
68
|
+
column, order = options[:order].split(" ")
|
69
|
+
s = s.order("#{Lit::LocalizationKey.quoted_table_name}.#{connection.quote_column_name(column)} #{order}" )
|
70
|
+
else
|
71
|
+
s = s.ordered
|
72
|
+
end
|
57
73
|
if options[:key_prefix].present?
|
58
74
|
q = "#{options[:key_prefix]}%"
|
59
75
|
s = s.where('lit_localization_keys.localization_key like ?', q)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
<h3><%= t('.header', :default=>"Localization keys") %></h3>
|
2
|
+
<% available_locales = I18n.backend.available_locales %>
|
2
3
|
|
3
4
|
<table class="table">
|
4
5
|
<%- @localization_keys.each do |lk| %>
|
@@ -16,13 +17,9 @@
|
|
16
17
|
</div>
|
17
18
|
<div class="detail_wrapper">
|
18
19
|
<table class="table table-bordered table-striped">
|
19
|
-
<%-
|
20
|
-
<%- localization =
|
20
|
+
<%- available_locales.each do |locale| %>
|
21
|
+
<%- localization = localization_for(locale, lk) %>
|
21
22
|
<tr>
|
22
|
-
<% unless localization %>
|
23
|
-
<% Lit.init.cache.refresh_key("#{locale}.#{lk.localization_key}") %>
|
24
|
-
<%- localization = lk.localizations.where(:locale_id=>Lit.init.cache.find_locale(locale).id).first %>
|
25
|
-
<% end %>
|
26
23
|
<td class="localization_row" data-id="<%= localization.id%>" data-edit="<%= edit_localization_key_localization_path(lk, localization) %>" data-editing=0 data-content="">
|
27
24
|
<%= render :partial=>"localization_row", :locals=>{:localization=>Lit.init.cache["#{locale}.#{lk.localization_key}"]} %>
|
28
25
|
</td>
|
@@ -30,7 +27,7 @@
|
|
30
27
|
<%= image_tag "lit/famfamfam_flags/#{locale[0,2]}.png" %>
|
31
28
|
<%= locale %>
|
32
29
|
<% if localization %>
|
33
|
-
<%= link_to lit.previous_versions_localization_key_localization_path(lk, localization), :class=>"show_prev_versions #{'hidden'
|
30
|
+
<%= link_to lit.previous_versions_localization_key_localization_path(lk, localization), :class=>"show_prev_versions #{'hidden' unless has_versions?(localization)}", :remote=>true do %>
|
34
31
|
<%= draw_icon 'random', :title=>t('lit.common.previous_versions', :default=>"Previous versions") %>
|
35
32
|
<% end %>
|
36
33
|
<% end %>
|
@@ -78,10 +75,18 @@
|
|
78
75
|
starred
|
79
76
|
<% end %>
|
80
77
|
</li>
|
78
|
+
<li class="nav-header"><%= t(".order_by", :default => "Order by") %>:</li>
|
79
|
+
<% Lit::LocalizationKey.order_options.each do |order| %>
|
80
|
+
<li class="<%= "active" if order == @search_options[:order] %>">
|
81
|
+
<%= link_to url_for(@search_options.merge(:order => order)) do %>
|
82
|
+
<%= t("lit.order_options.#{order.gsub(" ", "_")}", :default => order.humanize) %>
|
83
|
+
<% end %>
|
84
|
+
</li>
|
85
|
+
<% end %>
|
81
86
|
<li class="nav-header">Narrow with prefix</li>
|
82
87
|
<% if @search_options[:key_prefix].present? %>
|
83
88
|
<li>
|
84
|
-
<%= link_to url_for(:key_prefix=>p
|
89
|
+
<%= link_to url_for(@search_options.merge(:key_prefix=>p)), :title=>(@parent_prefix.present? ? @parent_prefix : 'show all') do %>
|
85
90
|
<%= draw_icon('chevron-left') %>
|
86
91
|
<%= @parent_prefix.present? ? @parent_prefix.split('.').last : 'show all' %>
|
87
92
|
<% end %>
|
@@ -89,7 +94,7 @@
|
|
89
94
|
<% end %>
|
90
95
|
<% @prefixes.each do |p| %>
|
91
96
|
<li class="key_prefix">
|
92
|
-
<%= link_to url_for(:key_prefix=>p
|
97
|
+
<%= link_to url_for(@search_options.merge(:key_prefix=>p)) do %>
|
93
98
|
<%= draw_icon('chevron-right') %>
|
94
99
|
<%= p.split('.').last %>
|
95
100
|
<% end %>
|
@@ -8,7 +8,12 @@
|
|
8
8
|
</ul>
|
9
9
|
<% else %>
|
10
10
|
<%= f.text_area :translated_value, :size=>"40x2", :class=>"input-xxlarge" %>
|
11
|
+
<br />
|
12
|
+
<label>
|
13
|
+
<input type="checkbox" class="wysiwyg_switch" /> use wysiwyg editor
|
14
|
+
</label>
|
11
15
|
<% end %>
|
16
|
+
|
12
17
|
<button class="btn" type="submit"><%= t('lit.common.update', :default=>"Update") %></button>
|
13
18
|
<button class="btn cancel"><%= t('lit.common.cancel', :default=>'Cancel') %></button>
|
14
19
|
<% end %>
|
@@ -1,4 +1,7 @@
|
|
1
1
|
var $row = $('td.localization_row[data-id="<%= @localization.id %>"]');
|
2
2
|
$row.data('editing', 1);
|
3
3
|
$row.html("<%= ejs render(:partial=>'form') %>");
|
4
|
-
$row.find('textarea').focus();
|
4
|
+
$row.find('textarea').focus();
|
5
|
+
<% if @localization.full_key.ends_with?('_html') -%>
|
6
|
+
$row.find('.wysiwyg_switch').click();
|
7
|
+
<% end %>
|
data/lib/lit/cache.rb
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
module I18n
|
2
|
+
class << self
|
3
|
+
@@cache_store = nil
|
4
|
+
|
5
|
+
def cache_store
|
6
|
+
@@cache_store || I18n.backend.cache
|
7
|
+
end
|
8
|
+
|
9
|
+
def cache_store=(store)
|
10
|
+
@@cache_store = store
|
11
|
+
end
|
12
|
+
|
13
|
+
def perform_caching?
|
14
|
+
!cache_store.nil?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
1
19
|
module Lit
|
2
20
|
class Cache
|
3
21
|
|
@@ -42,6 +60,13 @@ module Lit
|
|
42
60
|
@localizations[key] = localization.get_value if localization
|
43
61
|
end
|
44
62
|
|
63
|
+
def delete_locale(key)
|
64
|
+
key = key.to_s
|
65
|
+
locale_key, key_without_locale = split_key(key)
|
66
|
+
locale = find_locale(locale_key)
|
67
|
+
delete_localization(locale, key_without_locale)
|
68
|
+
end
|
69
|
+
|
45
70
|
def load_all_translations(oninit=false)
|
46
71
|
doinit = false
|
47
72
|
first = Localization.order('id ASC').first
|
@@ -83,6 +108,8 @@ module Lit
|
|
83
108
|
load_all_translations
|
84
109
|
end
|
85
110
|
|
111
|
+
alias_method :clear, :reset
|
112
|
+
|
86
113
|
def find_locale(locale_key)
|
87
114
|
locale_key = locale_key.to_s
|
88
115
|
@locale_cache ||= {}
|
@@ -178,6 +205,15 @@ module Lit
|
|
178
205
|
end
|
179
206
|
end
|
180
207
|
|
208
|
+
def delete_localization(locale, key_without_locale)
|
209
|
+
localization = find_localization(locale, key_without_locale)
|
210
|
+
if localization.persisted?
|
211
|
+
@localizations.delete("#{locale.locale}.#{key_without_locale}")
|
212
|
+
@localization_keys.delete(key_without_locale)
|
213
|
+
localization.destroy # or localization.default_value = nil; localization.save!
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
181
217
|
## checks parameter type and returns value basing on it
|
182
218
|
## symbols are beeing looked up in db
|
183
219
|
## string are returned directly
|
@@ -196,7 +232,7 @@ module Lit
|
|
196
232
|
when String then
|
197
233
|
new_value = v
|
198
234
|
when Proc then
|
199
|
-
new_value = v.call
|
235
|
+
new_value = nil # was v.call - requires more love
|
200
236
|
else
|
201
237
|
new_value = v.to_s
|
202
238
|
end
|
@@ -213,10 +249,7 @@ module Lit
|
|
213
249
|
end
|
214
250
|
|
215
251
|
def split_key(key)
|
216
|
-
|
217
|
-
locale_key = key_split.first
|
218
|
-
key_without_locale = key_split[1..-1].join('.')
|
219
|
-
[locale_key, key_without_locale]
|
252
|
+
key.split('.', 2)
|
220
253
|
end
|
221
254
|
|
222
255
|
def find_or_create_localization_key(key_without_locale)
|
data/lib/lit/i18n_backend.rb
CHANGED
@@ -4,6 +4,8 @@ module Lit
|
|
4
4
|
class I18nBackend
|
5
5
|
include I18n::Backend::Simple::Implementation
|
6
6
|
|
7
|
+
attr_reader :cache
|
8
|
+
|
7
9
|
def initialize(cache)
|
8
10
|
@cache = cache
|
9
11
|
end
|
@@ -18,7 +20,7 @@ module Lit
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def available_locales
|
21
|
-
Lit::Locale.ordered.visible.
|
23
|
+
Lit::Locale.ordered.visible.map{|l| l.locale.to_sym }
|
22
24
|
end
|
23
25
|
|
24
26
|
# Stores the given translations.
|
@@ -39,6 +41,8 @@ module Lit
|
|
39
41
|
|
40
42
|
## check in cache or in simple backend
|
41
43
|
content = @cache[key_with_locale] || super
|
44
|
+
return content if parts.size <= 1
|
45
|
+
|
42
46
|
newly_created = false
|
43
47
|
unless @cache.has_key?(key_with_locale)
|
44
48
|
@cache.init_key_with_value(key_with_locale, content)
|
@@ -59,25 +63,29 @@ module Lit
|
|
59
63
|
end
|
60
64
|
elsif data.respond_to?(:to_str)
|
61
65
|
key = ([locale] + scope).join('.')
|
62
|
-
@cache[key]
|
66
|
+
@cache[key] ||= data
|
67
|
+
elsif data.nil?
|
68
|
+
key = ([locale] + scope).join('.')
|
69
|
+
@cache.delete_locale(key)
|
63
70
|
end
|
64
71
|
end
|
65
72
|
|
66
73
|
def load_translations(*filenames)
|
67
|
-
super
|
68
74
|
@cache.load_all_translations
|
75
|
+
super
|
69
76
|
end
|
70
77
|
|
71
78
|
def default(locale, object, subject, options = {})
|
72
79
|
content = super(locale, object, subject, options)
|
73
80
|
if content.respond_to?(:to_str)
|
74
81
|
parts = I18n.normalize_keys(locale, object, options[:scope], options[:separator])
|
75
|
-
|
76
|
-
|
82
|
+
if parts.size > 1
|
83
|
+
key = parts.join('.')
|
84
|
+
@cache[key] = content
|
85
|
+
end
|
77
86
|
end
|
78
87
|
content
|
79
88
|
end
|
80
89
|
|
81
|
-
attr_reader :cache
|
82
90
|
end
|
83
91
|
end
|
data/lib/lit/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-10-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -381,13 +381,16 @@ files:
|
|
381
381
|
- app/assets/images/lit/famfamfam_flags/za.png
|
382
382
|
- app/assets/images/lit/famfamfam_flags/zm.png
|
383
383
|
- app/assets/images/lit/famfamfam_flags/zw.png
|
384
|
+
- app/assets/images/lit/jquery-te.png
|
384
385
|
- app/assets/javascripts/lit/application.js
|
385
386
|
- app/assets/javascripts/lit/bootstrap.js.coffee
|
386
387
|
- app/assets/javascripts/lit/dashboard.js
|
388
|
+
- app/assets/javascripts/lit/jquery-te-1.4.0.min.js
|
387
389
|
- app/assets/javascripts/lit/localizations.js.coffee
|
388
390
|
- app/assets/stylesheets/lit/application.css
|
389
391
|
- app/assets/stylesheets/lit/bootstrap_and_overrides.css.scss
|
390
392
|
- app/assets/stylesheets/lit/dashboard.css
|
393
|
+
- app/assets/stylesheets/lit/jquery-te-1.4.0.css.scss
|
391
394
|
- app/controllers/lit/api/v1/base_controller.rb
|
392
395
|
- app/controllers/lit/api/v1/locales_controller.rb
|
393
396
|
- app/controllers/lit/api/v1/localization_keys_controller.rb
|
@@ -430,7 +433,7 @@ files:
|
|
430
433
|
- app/views/lit/localization_keys/star.js.erb
|
431
434
|
- app/views/lit/localizations/_form.html.erb
|
432
435
|
- app/views/lit/localizations/_previous_versions_rows.html.erb
|
433
|
-
- app/views/lit/localizations/edit.
|
436
|
+
- app/views/lit/localizations/edit.js.erb
|
434
437
|
- app/views/lit/localizations/previous_versions.js.erb
|
435
438
|
- app/views/lit/localizations/update.js.erb
|
436
439
|
- app/views/lit/sources/_form.html.erb
|
@@ -464,7 +467,8 @@ files:
|
|
464
467
|
- Rakefile
|
465
468
|
- README.md
|
466
469
|
homepage: https://github.com/prograils/lit
|
467
|
-
licenses:
|
470
|
+
licenses:
|
471
|
+
- MIT
|
468
472
|
post_install_message:
|
469
473
|
rdoc_options: []
|
470
474
|
require_paths:
|