lit 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|