Automatic Translate Addon For Loco Translate - Version 1.5

Version Description

Download this release

Release Info

Developer Narinder singh
Plugin Icon 128x128 Automatic Translate Addon For Loco Translate
Version 1.5
Comparing to
See all releases

Code changes from version 1.4.1 to 1.5

assets/images/google-api.png ADDED
Binary file
assets/js/atlt-custom.js ADDED
@@ -0,0 +1,601 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var TotalCharacters=0;
2
+ var HtmlStrings = 0;
3
+ var requestChars=0;
4
+
5
+ let event = document.createEvent('event');
6
+ event.initEvent('atlt_translated');
7
+ createSettingsPopup();
8
+
9
+ $('#atlt-dialog .atlt-ok.button').on('click',function(){
10
+ // hide dialog container by finding main parent DOM
11
+ localStorage.removeItem('unSavedString');
12
+ $("#atlt-dialog").parent('.ui-dialog').hide();
13
+ });
14
+
15
+
16
+
17
+ /*
18
+ |--------------------------------------------------------------------------
19
+ | Auto Translator Custom Code
20
+ |--------------------------------------------------------------------------
21
+ */
22
+ //encode URL query string
23
+ function createEncodedString(allStringText){
24
+ const queryString=allStringText.map((item)=>{
25
+ return "&text="+ encodeURIComponent(item.source);
26
+ }).join(",");
27
+
28
+ return queryString;
29
+ }
30
+
31
+ function validLicenseKey(licenseKey){
32
+ return licenseKey;
33
+ }
34
+
35
+ $(document).ready(function(){
36
+ const locoRawData=conf.podata;
37
+ if(locoRawData!=undefined && locoRawData.length>0 ){
38
+ // called auto traslate button
39
+ addAutoTranslationBtn();
40
+ }
41
+
42
+ $(document).on("click", "#cool-auto-translate-btn", function() {
43
+ $('#atlt-dialog').dialog({width:320,height:300});
44
+ });
45
+ /* $("#atlt-settings-form").submit(function( event ) {
46
+ event.preventDefault();
47
+ let type = $("input[name='translationtype']:checked").val();
48
+ console.log(type);
49
+ }); */
50
+ // main translate handler
51
+
52
+ $("#atlt-settings-form").submit(function( event ) {
53
+ event.preventDefault();
54
+ let strType = $("input[name='translationtype']:checked").val();
55
+ let apiType = $("input[name='api_type']:checked").val();
56
+ let mainBtn=$("#cool-auto-translate-btn");
57
+ var thisBtn=$("#cool-auto-translate-start");
58
+
59
+ var todayLimit= mainBtn.data('today-limit');
60
+ var totalLimit= mainBtn.data('total-limit');
61
+ // const targetLang=conf.locale.lang;
62
+ const apiKey = ATLT["api_key"]["atlt_api-key"];
63
+
64
+ if(locoRawData!=undefined && locoRawData.length>0 && apiKey!='' ){
65
+ let plainStrArr=[];
66
+ let htmlStrArr=[];
67
+ let orgStrArr=[];
68
+ orgStrArr=locoRawData.filter((item,index)=>{
69
+ if((item.target===undefined || item.target=="")){
70
+ return true;
71
+ }
72
+ });
73
+
74
+ htmlStrArr=locoRawData.filter((item,index)=>{
75
+ if( (item.target===undefined || item.target=="" && item.source!="" && item.source!==undefined)){
76
+ if( ValidURL(item.source)){
77
+ return false;
78
+ }else if(isContainChars(item.source)){
79
+ return false;
80
+ } else if(isHTML(item.source)){
81
+ return true;
82
+ }else if(isAllowedChars(item.source)){
83
+ return true;
84
+ }else{
85
+ return false;
86
+ }
87
+ }
88
+ });
89
+
90
+ plainStrArr=locoRawData.filter((item,index)=>{
91
+ if( (item.target===undefined || item.target=="") && item.source!=""){
92
+ if(isHTML(item.source) || ValidURL(item.source)){
93
+ return false;
94
+ }else if(isSpecialChars(item.source)){
95
+ return false;
96
+ }
97
+ else if( item.source.includes('#') == true)
98
+ {
99
+ return false;
100
+ }else{
101
+ return true;
102
+ }
103
+ }
104
+ });
105
+
106
+ var countChars=0;
107
+ if(strType=="plain"){
108
+ if (plainStrArr !== null) {
109
+ plainStrArr.map(function(index){
110
+ countChars +=index.source.length;
111
+ });
112
+ }
113
+ }else{
114
+ if (htmlStrArr !== null) {
115
+ plainStrArr.map(function(index){
116
+ countChars +=index.length;
117
+ });
118
+ }
119
+ }
120
+
121
+ if (htmlStrArr !== null || plainStrArr !== null ) {
122
+ if(countChars>parseInt(todayLimit)){
123
+ alert('Your translation string are larger then available free limit.In order to extend limit Buy Pro license key');
124
+ }else{
125
+
126
+ if(strType=="plain"){
127
+ if(plainStrArr.length==0){
128
+ $("#atlt-dialog").parent('.ui-dialog').hide();
129
+ mainBtn.attr('disabled','disabled');
130
+ alert("You have no untransalted strings");
131
+ window.location.reload();
132
+ return;
133
+ }
134
+ dataObj = {
135
+ textToTranslateArr:plainStrArr,
136
+ thisBtn:$(this),
137
+ strType:"plain",
138
+ apiType:apiType
139
+ };
140
+ }else{
141
+ if(htmlStrArr.length==0){
142
+ $("#atlt-dialog").parent('.ui-dialog').hide();
143
+ mainBtn.attr('disabled','disabled');
144
+ alert("You have no untransalted HTML strings");
145
+ window.location.reload();
146
+ return;
147
+ }
148
+ dataObj = {
149
+ textToTranslateArr:htmlStrArr,
150
+ thisBtn:$(this),
151
+ strType:"html",
152
+ apiType:apiType
153
+ };
154
+ }
155
+ dataObj.orgStrArr= orgStrArr;
156
+ thisBtn.val('Translating...');
157
+ mainBtn.text("Translating..");
158
+ $("#atlt_preloader").show();
159
+
160
+ window.locoEditorStats.dataObj = dataObj;
161
+ jQuery(document).trigger('atlt_translated');
162
+
163
+ // load raw message data
164
+
165
+ } //
166
+
167
+ } // else close
168
+ }
169
+
170
+ });
171
+
172
+ });
173
+
174
+ jQuery(document).on('atlt_translated',function(){
175
+ let textToTranslate = window.locoEditorStats.dataObj.textToTranslateArr
176
+ let totalTranslated = window.locoEditorStats.totalTranslated
177
+ const apiKey = ATLT["api_key"]["atlt_api-key"];
178
+ const nonce=ATLT["nonce"];
179
+ const saveBtn=$('[data-loco="save"]');
180
+ const orignalstringArr=window.locoEditorStats.dataObj.orgStrArr;
181
+ const targetLang=conf['locale']["lang"];
182
+ let indexRequest = 50;
183
+ if( ATLT.api_key['atlt_index-per-request'] != "" && typeof ATLT.api_key['atlt_index-per-request'] != "undefined" ){
184
+ indexRequest = ATLT.api_key['atlt_index-per-request'];
185
+ }
186
+
187
+ if( typeof textToTranslate == "object" && textToTranslate.length >= 1 ){
188
+ let translationO = {
189
+ textToTranslateArr:textToTranslate.slice(indexRequest),
190
+ thisBtn:window.locoEditorStats.dataObj.thisBtn,
191
+ strType:window.locoEditorStats.dataObj.strType,
192
+ orgStrArr:window.locoEditorStats.dataObj.orgStrArr,
193
+ apiType:window.locoEditorStats.dataObj.apiType
194
+ };
195
+ window.locoEditorStats.dataObj = translationO;
196
+
197
+ // partial data request
198
+ let data = {
199
+ sourceLang:'en',
200
+ targetLang:targetLang,
201
+ textToTranslateArr:textToTranslate.slice(0,indexRequest),
202
+ orginalArr:orignalstringArr,
203
+ apiKey:apiKey,
204
+ thisBtn:window.locoEditorStats.dataObj.thisBtn,
205
+ strType:window.locoEditorStats.dataObj.strType,
206
+ apiType:window.locoEditorStats.dataObj.apiType,
207
+ saveBtn:saveBtn,
208
+ nonce:nonce
209
+ };
210
+
211
+ textToTranslate.slice(0,indexRequest).map(function(value,index){
212
+ TotalCharacters += (value.source).length;
213
+ requestChars+=(value.source).length;
214
+ })
215
+ atlt_translate(data);
216
+ }
217
+ })
218
+
219
+ // Translate
220
+ function atlt_translate(data) {
221
+
222
+ atlt_ajax_translation_request(data, "POST").success(function(
223
+ resp
224
+ ) {
225
+ const json_resp = JSON.parse(resp);
226
+ if( json_resp == false ){
227
+ data.thisBtn.hide('slow');
228
+ $("#cool-auto-translate-btn").attr('disabled','disabled');
229
+ $("#cool-auto-translate-btn").text('Translation').attr('disabled','disabled');
230
+ alert('Unable to make request to the server at the moment. Try again later.');
231
+ }else if( typeof json_resp['code'] === undefined || json_resp['code'] != 200 ){
232
+ let error = '';
233
+ switch(json_resp['code']){
234
+ case 401:
235
+ error = 'Yendex API Key is invalid!';
236
+ break;
237
+ case 402:
238
+ error = 'Provided Yendex API Key has been blocked!';
239
+ break;
240
+ case 404:
241
+ error = 'Exceeded the daily limit for Yendex API on the amount of translated text.';
242
+ break;
243
+ case 422:
244
+ error = 'The text cannot be translated by Yendex API.';
245
+ break;
246
+ case 501:
247
+ error = 'Yendex API does not support the specified translation direction.';
248
+ break;
249
+ default:
250
+ error = json_resp['message'];
251
+ }
252
+ if( error != '' && (data.textToTranslateArr).length != 0 ){
253
+ $('#atlt-dialog .atlt-final-message').html("<strong>"+error+"</strong>");
254
+ $('#atlt-dialog .atlt-ok.button').show();
255
+
256
+ $("#cool-auto-translate-btn").text('Error').attr('disabled','disabled');
257
+ //data.thisBtn.attr('disabled','disabled');
258
+ $("#atlt_preloader").hide();
259
+ }
260
+ return;
261
+ }
262
+
263
+ let totalTranslated = window.locoEditorStats.totalTranslated;
264
+
265
+ var response = json_resp['translatedString'];
266
+ let unSavedStr=[];
267
+ if(response!==undefined){
268
+ for(i=0;i< response.length;i++){
269
+ var text = response[i];
270
+ if( data.textToTranslateArr[i] === undefined ){
271
+ break;
272
+ }
273
+ data.textToTranslateArr[i].target = text ;
274
+ }
275
+ }
276
+
277
+ let translatedStrArr=data['textToTranslateArr'];
278
+ var mergeTranslatedText = atlt_arrayUnique(translatedStrArr.concat(data['orginalArr']) );
279
+
280
+ let Emptytargets = [];
281
+ for(var x=0; x<translatedStrArr.length;++x){
282
+ if(translatedStrArr[x].target !='' ){
283
+ Emptytargets[x]=translatedStrArr[x].source;
284
+ }
285
+ }
286
+
287
+ let items;
288
+ if (localStorage.getItem('unSavedString')) {
289
+ items = JSON.parse(localStorage.getItem('unSavedString'))
290
+ } else {
291
+ items = []
292
+ }
293
+ var unSavedStrArr = items.concat(Emptytargets);
294
+ localStorage.setItem('unSavedString', JSON.stringify(unSavedStrArr));
295
+
296
+
297
+ messages = loco.po.init( locale ).wrap( conf.powrap );
298
+ // ready to render editor
299
+ messages.load(mergeTranslatedText);
300
+
301
+ // editor event behaviours
302
+ editor
303
+ .on('poUnsaved', function(){
304
+ window.onbeforeunload = onUnloadWarning;
305
+ } )
306
+ .on('poSave', function(){
307
+ updateStatus();
308
+ window.onbeforeunload = null;
309
+ } )
310
+ .on( 'poUpdate', updateStatus );
311
+
312
+ // ready to render editor
313
+ editor.load(messages);
314
+ data.saveBtn.addClass( 'button-primary loco-flagged' ).removeAttr("disabled");
315
+ updateStatus();
316
+ // run through DOM and mark *(STAR) for newly translated
317
+ markUnsavedString();
318
+
319
+ requestChars=0;
320
+ // update progress bar
321
+ $('#atlt-dialog .translated-label').text('Translated');
322
+ $('#atlt-dialog .translated-text').text(window.locoEditorStats.totalTranslated);
323
+
324
+ $('#atlt-dialog .atlt-progress-bar-value').width(window.locoEditorStats.totalTranslated);
325
+ if(json_resp!==undefined){
326
+ if(json_resp['stats']['time_saved']!==undefined){
327
+ var saved_time_msg = '<br/><br/><span style="border: 3px solid #14b75d;display: inline-block;padding: 3px;">Wahooo! You have saved your <strong>'+json_resp['stats']['time_saved']+'</strong> via auto translating '+parseInt(json_resp['stats']['totalChars'])+ ' characters using <strong><a href="https://wordpress.org/support/plugin/automatic-translator-addon-for-loco-translate/reviews/#new-post" target="_new">Loco Automatic Translate Addon</a></strong>.</span><br/><br/>';
328
+ }
329
+ }
330
+ switch( window.locoEditorStats.totalTranslated ){
331
+ case "0%":
332
+ $('#atlt-dialog .translated-label').text('Translating...');
333
+ $('#atlt-dialog .translated-text').text('');
334
+ break;
335
+ case "100%":
336
+ data.thisBtn.text('Translated');
337
+
338
+ data.thisBtn.attr('disabled','disabled').hide('slow');
339
+ $("#cool-auto-translate-btn").text('Translated - SAVE NOW').attr('disabled','disabled');
340
+ // change cursor to 'default' state
341
+ $('#atlt-dialog .atlt-final-message').html("<strong style='font-size:18px;display:inline-block;margin:5px auto;'>Translation Complete!</strong><br/>(Close this popup & Click <strong>Save</strong>)"+saved_time_msg);
342
+ $('#atlt-dialog .atlt-ok.button').show();
343
+ return;
344
+ break;
345
+ }
346
+ $("#cool-auto-translate-btn").text("Translated");
347
+ // run through DOM and mark *(STAR) for newly translated
348
+ for(var x=0;x<=Emptytargets.length;x++){
349
+ var source = Emptytargets[x];
350
+ jQuery("#po-list-tbody div[for='po-list-col-source'] div").filter(function(index){
351
+ return jQuery(this).text() == source
352
+ }).addClass('po-unsaved');
353
+ }
354
+
355
+ if( (window.locoEditorStats.dataObj.textToTranslateArr).length == 0){
356
+ data.thisBtn.text('Translated');
357
+ $("#atlt_preloader").hide();
358
+ data.thisBtn.attr('disabled','disabled').hide('slow');
359
+ $("#cool-auto-translate-btn").text('Translated - SAVE NOW').attr('disabled','disabled');
360
+ // change cursor to 'default' state
361
+ $('#atlt-dialog .atlt-final-message').html("<strong style='font-size:18px;display:inline-block;margin:5px auto;'>Translation Complete!</strong><br/>(Close this popup & Click <strong>Save</strong>)."+saved_time_msg);
362
+ $('#atlt-dialog .atlt-ok.button').show();
363
+ return;
364
+ }
365
+
366
+ jQuery(document).trigger('atlt_translated');
367
+
368
+ });
369
+
370
+ }
371
+
372
+ // find unique index in array
373
+ function atlt_arrayUnique(array) {
374
+ var a = array.concat();
375
+ for(var i=0; i<a.length; ++i) {
376
+ for(var j=i+1; j<a.length; ++j) {
377
+ if(a[i] === a[j])
378
+ a.splice(j--, 1);
379
+ }
380
+ }
381
+
382
+ return a;
383
+ }
384
+
385
+
386
+ // auto traslator button in editor
387
+ function addAutoTranslationBtn(){
388
+ if($("#loco-toolbar").find("#cool-auto-translate-btn").length>0){
389
+ $("#loco-toolbar").find("#cool-auto-translate-btn").remove();
390
+ }
391
+
392
+ const inActiveBtn='<fieldset><button title="Add API key to enable this feature." id="cool-auto-translate-btn" disabled class="button has-icon icon-translate">Auto Translate</button> <a style="font-size:9px;display:block;margin-left:8px;" target="_blank" href="https://tech.yandex.com/translate/">Get Free API Key</a></fieldset>';
393
+ const otherBtn='<fieldset><button class="button" id="atlt_reload" title="Reload">Reload</button><button class="button" id="atlt_reset_all">Reset All String</button></fieldset>'
394
+ const disabledBtn='<fieldset><button title="Buy PRO." id="cool-auto-translate-btn" disabled class="button has-icon icon-translate">Auto Translate</button><div style="max-width:320px; display:inline-block;margin-top: 4px;"><span style="font-size:12px;display:inline-block;margin-left:8px;">You have exceeded free translation limit. In order to extend the limit - <a target="_blank" style="font-size:14px;display:inline-block;margin-left:8px;" target="_blank" href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/">Buy Premium License</a></span></div></fieldset>';
395
+ const apiKey=ATLT["api_key"]["atlt_api-key"];
396
+ const userType=ATLT["info"].type;
397
+ const allowed=ATLT["info"].allowed;
398
+ const today=ATLT["info"].today;
399
+ const total=ATLT["info"].total;
400
+ const aTodayChars=300000;
401
+ const aTodayChar=1000000;
402
+ if( ATLT == '' || ATLT["api_key"] == '' || apiKey=='' ){
403
+ $("#loco-toolbar").find("#loco-actions")
404
+ .append(inActiveBtn);
405
+ return;
406
+ }else if( allowed=="no" && userType=='free'){
407
+ $("#loco-toolbar").find("#loco-actions")
408
+ .append(disabledBtn);
409
+ return;
410
+ }else if(today!==undefined && parseInt(today)>aTodayChars && userType=='free'){
411
+ $("#loco-toolbar").find("#loco-actions")
412
+ .append(disabledBtn);
413
+ return;
414
+ }else if(total!==undefined && parseInt(total)>aTodayChar
415
+ && userType=='free'){
416
+ $("#loco-toolbar").find("#loco-actions")
417
+ .append(disabledBtn);
418
+ return;
419
+ }else if( window.locoEditorStats.totalTranslated != "100%" && window.locoEditorStats.totalWords > 0 ){
420
+ if(userType=='pro' && validLicenseKey(ATLT["info"]["licenseKey"])){
421
+ $("#loco-toolbar").find("#loco-actions")
422
+ .append('<fieldset><button id="cool-auto-translate-btn" class="button has-icon icon-translate">Auto Translate</button></fieldset>');
423
+ }else{
424
+ if(today==undefined){
425
+ var todayChars=aTodayChars;
426
+ }else{
427
+ var todayChars=aTodayChars-parseInt(today);
428
+ }
429
+ var totalChars=aTodayChar-parseInt(total);
430
+ var freeBtn='<fieldset><button data-today-limit="'+todayChars+'" data-total-limit="'+totalChars+'" id="cool-auto-translate-btn" class="button has-icon icon-translate">Auto Translate</button></fieldset>';
431
+ $("#loco-toolbar").find("#loco-actions").append(freeBtn);
432
+ }
433
+ } else if( window.locoEditorStats.totalWords == 0){
434
+ return;
435
+ } else {
436
+ $("#loco-toolbar").find("#loco-actions")
437
+ .append('<fieldset><button id="cool-auto-translate-btn" class="button has-icon icon-translate" disabled>Translated</button></fieldset>');
438
+ }
439
+ }
440
+
441
+
442
+ // mark unsaved after ajax translation process
443
+ function markUnsavedString(){
444
+ const unSavedString = JSON.parse(localStorage.getItem('unSavedString'));
445
+ console.log(unSavedString);
446
+ for(var x=0;x<=unSavedString.length;x++){
447
+ var source = unSavedString[x];
448
+ jQuery("#po-list-tbody div[for='po-list-col-source'] div").filter(function(index){
449
+ return jQuery(this).text() == source
450
+ }).addClass('po-unsaved');
451
+ }
452
+ }
453
+
454
+ // detect String contain URL
455
+ function ValidURL(str) {
456
+ var pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
457
+ if(!pattern.test(str)) {
458
+ return false;
459
+ } else {
460
+ return true;
461
+ }
462
+ }
463
+ // detect Valid HTML in string
464
+ function isHTML(str){
465
+ var rgex=/<(?=.*? .*?\/ ?>|br|hr|input|!--|wbr)[a-z]+.*?>|<([a-z]+).*?<\/\1>/i;
466
+ if(str!==undefined){
467
+ return rgex.test(str);
468
+ }else {
469
+ return false;
470
+ }
471
+ }
472
+ // check special chars in string
473
+ function isSpecialChars(str){
474
+ var rgex=/[@#^&*{}|<>]/g;
475
+ if(str!==undefined){
476
+ return rgex.test(str);
477
+ }else {
478
+ return false;
479
+ }
480
+ }
481
+ // allowed special chars in HTML string
482
+ function isAllowedChars(str){
483
+ var rgex=/[!@#$%^&*(),?":|<>]/g;
484
+ if(str!==undefined){
485
+ return rgex.test(str);
486
+ }else {
487
+ return false;
488
+ }
489
+ }
490
+ // check string contain curly brackets
491
+ function isContainChars(str){
492
+ var rgex=/[{}[]/g;
493
+ if(str!==undefined){
494
+ return rgex.test(str);
495
+ }else {
496
+ return false;
497
+ }
498
+ }
499
+
500
+ function atltFormatNumber(num) {
501
+ return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
502
+ }
503
+
504
+ // create popup model for translation settings
505
+ function createSettingsPopup(){
506
+ let preloaderImg=extradata['preloader_path'];
507
+ const userInfo=ATLT["info"].type;
508
+ const yAC=ATLT["info"].yAvailableChars;
509
+ let yACH='';
510
+ let fieldStatus="";
511
+ let contCls="";
512
+ let proLbl="";
513
+ let gContCls='';
514
+ let gAvailableCharsHtml='';
515
+ if(userInfo=="free"){
516
+ let gAC=0;
517
+ fieldStatus="disabled";
518
+ contCls="html-disabled";
519
+ gContCls='g-disabled';
520
+ proLbl='<span class="atlt-pro-feature"><a href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/" target="_blank" style="color:red;font-weight:bold;" title="Only For Pro Users">PRO Only</a></span>';
521
+ }else{
522
+ let gAC=ATLT["info"].gAvailableChars;
523
+ if(gAC!==undefined && gAC>10000){
524
+ gAvailableCharsHtml='<span class="available-chars"> ('+ atltFormatNumber(gAC)+' Available This Month)</span>';
525
+ }
526
+ if(gAC<10000){
527
+ gAvailableCharsHtml='<span class="used-chars">You have consumed All Free Characters</span>';
528
+ }
529
+ }
530
+ if(yAC!==undefined){
531
+ yACH='<span class="available-chars"> ('+atltFormatNumber(yAC)+' Available Today)</span>';
532
+ }
533
+ let settingsHTML=`<div class="atlt-settings">
534
+ <form id="atlt-settings-form" method="post" action="#">
535
+ <strong class="atlt-heading">Select Translation API</strong>
536
+ <div class="inputGroup">
537
+ <input class="inputEle" type="radio" id="yendex_api"
538
+ checked="true" name="api_type" value="yendex">
539
+ <label for="yendex_api">Yendex ${yACH}</label>
540
+ </div>
541
+ <div class="inputGroup ${gContCls}">
542
+ <input class="inputEle" type="radio" id="google_api"
543
+ name="api_type" value="google" ${fieldStatus}>
544
+ <label for="google_api">Google</label> ${proLbl} ${gAvailableCharsHtml}
545
+ </div>
546
+ <strong class="atlt-heading">Select Content Type</strong>
547
+ <div class="inputGroup">
548
+ <input class="inputEle" type="radio" id="typeplain" checked="true" name="translationtype" value="plain">
549
+ <label for="typeplain">Translate Plain Text Strings</label>
550
+ </div><div class="inputGroup ${contCls}">
551
+ <input class="inputEle" type="radio" id="typehtml" name="translationtype" value="html" ${fieldStatus}>
552
+ <label for="typehtml">Translate HTML Strings (Beta) ${proLbl}<br/><small style="display:inline-block;margin-left:24px;margin-top:8px;">(<a href="https://locotranslate.com/html-translation-languages-list/" target="_blank">List of languages with HTML support</a>)</small></label>
553
+ </div>
554
+ <br/>
555
+ <fieldset><input type="submit" class="button has-icon icon-translate" value="Start Translation" id="cool-auto-translate-start">
556
+ <img style="display:none;margin-left:10px;margin-top:-3px;" id="atlt_preloader" src="${preloaderImg}">
557
+ </fieldset>
558
+ </form>
559
+ </div>`;
560
+ // custom popup message box
561
+ let popup_html = `<div id="atlt-dialog-container">
562
+ <div style="display:none;" id="atlt-dialog" title="Automatic Translation Progress">
563
+ ${settingsHTML}
564
+ <p><span class="translated-label">Translated</span>
565
+ <span class="translated-text">0%</span></p>
566
+ <div class="atlt-progress-bar-track">
567
+ <div class="atlt-progress-bar-value">
568
+ </div></div>
569
+ <div class="atlt-final-message"></div>
570
+ <button style="display:none;" class="atlt-ok button button-primary">OK</button>
571
+ </div></div>`;
572
+ $("body").append( popup_html );
573
+ }
574
+
575
+ function atlt_ajax_translation_request(data,type){
576
+ let filteredArr=[];
577
+ filteredArr=data.textToTranslateArr.map((item)=>{
578
+ if( typeof item.source!= 'undefined'){
579
+ return item.source;
580
+ } });
581
+ const jsonData=JSON.stringify(filteredArr);
582
+
583
+ return jQuery.ajax({
584
+ url: ajaxurl,
585
+ type:'POST',
586
+ data: {'action':'atlt_translation',
587
+ 'sourceLan':data.sourceLang,
588
+ 'targetLan':data.targetLang,
589
+ 'totalCharacters': TotalCharacters,
590
+ 'requestChars':requestChars,
591
+ 'nonce':data.nonce,
592
+ 'strType':data.strType,
593
+ 'apiType':data.apiType,
594
+ 'data':jsonData
595
+ },
596
+ done:function(res){
597
+ console.log(res)
598
+ }
599
+
600
+ });
601
+ }
assets/js/loco-js-editor.js ADDED
@@ -0,0 +1,1398 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Script for PO file editor pages
3
+ */
4
+ !function( window, $ ){
5
+ var TotalCharacters=0;
6
+ var HtmlStrings = 0;
7
+ var requestChars=0;
8
+ // ES6 Modules or TypeScript
9
+ let event = document.createEvent('event');
10
+ event.initEvent('atlt_run_translation');
11
+ createSettingsPopup();
12
+
13
+ $('#atlt-dialog .atlt-ok.button').on('click',function(){
14
+ // hide dialog container by finding main parent DOM
15
+ localStorage.removeItem('unSavedString');
16
+ $("#atlt-dialog").parent('.ui-dialog').hide();
17
+ });
18
+
19
+ var loco = window.locoScope,
20
+ conf = window.locoConf,
21
+ syncParams = null,
22
+ saveParams = null,
23
+ // UI translation
24
+ translator = loco.l10n,
25
+ sprintf = loco.string.sprintf,
26
+ // PO file data
27
+ locale = conf.locale,
28
+ messages = loco.po.init( locale ).wrap( conf.powrap ),
29
+ template = ! locale,
30
+ // form containing action buttons
31
+ elForm = document.getElementById('loco-actions'),
32
+ filePath = conf.popath,
33
+ syncPath = conf.potpath,
34
+
35
+ // file system connect when file is locked
36
+ elFilesys = document.getElementById('loco-fs'),
37
+ fsConnect = elFilesys && loco.fs.init( elFilesys ),
38
+
39
+ // prevent all write operations if readonly mode
40
+ readonly = conf.readonly,
41
+ editable = ! readonly,
42
+ // Editor components
43
+ editor,
44
+ saveButton,
45
+ innerDiv = document.getElementById('loco-editor-inner');
46
+
47
+ /**
48
+ *
49
+ */
50
+ function doSyncAction( callback ){
51
+ function onSuccess( result ){
52
+ var info = [],
53
+ doc = messages,
54
+ exp = result.po,
55
+ src = result.pot,
56
+ pot = loco.po.init().load( exp ),
57
+ done = doc.merge( pot ),
58
+ nadd = done.add.length,
59
+ ndel = done.del.length,
60
+ t = translator;
61
+ // reload even if unchanged, cos indexes could be off
62
+ editor.load( doc );
63
+ // Show summary
64
+ if( nadd || ndel ){
65
+ if( src ){
66
+ // Translators: Where %s is the name of the POT template file. Message appears after sync
67
+ info.push( sprintf( t._('Merged from %s'), src ) );
68
+ }
69
+ else {
70
+ // Translators: Message appears after sync operation
71
+ info.push( t._('Merged from source code') );
72
+ }
73
+ // Translators: Summary of new strings after running in-editor Sync
74
+ nadd && info.push( sprintf( t._n('1 new string added','%s new strings added', nadd ), nadd ) );
75
+ // Translators: Summary of existing strings that no longer exist after running in-editor Sync
76
+ ndel && info.push( sprintf( t._n('1 obsolete string removed','%s obsolete strings removed', ndel ), ndel ) );
77
+ // editor thinks it's saved, but we want the UI to appear otherwise
78
+ $(innerDiv).trigger('poUnsaved',[]);
79
+ updateStatus();
80
+ // debug info in lieu of proper merge confirmation:
81
+ window.console && debugMerge( console, done );
82
+ }
83
+ else if( src ){
84
+ // Translators: Message appears after sync operation when nothing has changed. %s refers to a POT file.
85
+ info.push( sprintf( t._('Already up to date with %s'), src ) );
86
+ }
87
+ else {
88
+ // Translators: Message appears after sync operation when nothing has changed
89
+ info.push( t._('Already up to date with source code') );
90
+ }
91
+ loco.notices.success( info.join('. ') );
92
+ $(innerDiv).trigger('poMerge',[result]);
93
+ // done sync
94
+ callback && callback();
95
+ }
96
+ loco.ajax.post( 'sync', syncParams, onSuccess, callback );
97
+ }
98
+
99
+ function debugMerge( console, result ){
100
+ var i = -1, t = result.add.length;
101
+ while( ++i < t ){
102
+ console.log(' + '+result.add[i].source() );
103
+ }
104
+ i = -1, t = result.del.length;
105
+ while( ++i < t ){
106
+ console.log(' - '+result.del[i].source() );
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Post full editor contents to "posave" endpoint
112
+ */
113
+ function doSaveAction( callback ){
114
+ function onSuccess( result ){
115
+ callback && callback();
116
+ editor.save( true );
117
+ // Update saved time update
118
+ $('#loco-po-modified').text( result.datetime||'[datetime error]' );
119
+ }
120
+ saveParams.locale = String( messages.locale() || '' );
121
+ if( fsConnect ){
122
+ fsConnect.applyCreds( saveParams );
123
+ }
124
+ // adding PO source last for easier debugging in network inspector
125
+ saveParams.data = String( messages );
126
+ loco.ajax.post( 'save', saveParams, onSuccess, callback );
127
+ }
128
+ function saveIfDirty(){
129
+ editor.dirty && doSaveAction();
130
+ }
131
+ function onUnloadWarning(){
132
+ // Translators: Warning appears when user tries to refresh or navigate away when editor work is unsaved
133
+ return translator._("Your changes will be lost if you continue without saving");
134
+ }
135
+
136
+ function registerSaveButton( button ){
137
+ saveButton = button;
138
+ // enables and disable according to save/unsave events
139
+ editor
140
+ .on('poUnsaved', function(){
141
+ enable();
142
+ $(button).addClass( 'button-primary loco-flagged' );
143
+ } )
144
+ .on('poSave', function(){
145
+ disable();
146
+ $(button).removeClass( 'button-primary loco-flagged' );
147
+ } )
148
+ ;
149
+ function disable(){
150
+ button.disabled = true;
151
+ }
152
+ function enable(){
153
+ button.disabled = false;
154
+ }
155
+ function think(){
156
+ disable();
157
+ $(button).addClass('loco-loading');
158
+ }
159
+ function unthink(){
160
+ enable();
161
+ $(button).removeClass('loco-loading');
162
+ }
163
+ saveParams = $.extend( { path: filePath }, conf.project||{} );
164
+
165
+ $(button).click( function(event){
166
+ event.preventDefault();
167
+ think();
168
+ doSaveAction( unthink );
169
+ setTimeout(function() {
170
+ location.reload();
171
+ },1500);
172
+ return false;
173
+ } );
174
+ return true;
175
+ };
176
+
177
+ function registerSyncButton( button ){
178
+ var project = conf.project;
179
+ if( project ){
180
+ function disable(){
181
+ button.disabled = true;
182
+ }
183
+ function enable(){
184
+ button.disabled = false;
185
+ }
186
+ function think(){
187
+ disable();
188
+ $(button).addClass('loco-loading');
189
+ }
190
+ function unthink(){
191
+ enable();
192
+ $(button).removeClass('loco-loading');
193
+ }
194
+ // Only permit sync when document is saved
195
+ editor
196
+ .on('poUnsaved', function(){
197
+ disable();
198
+ } )
199
+ .on('poSave', function(){
200
+ enable();
201
+ } )
202
+ ;
203
+ // params for sync end point
204
+ syncParams = {
205
+ bundle: project.bundle,
206
+ domain: project.domain,
207
+ type: template ? 'pot' : 'po',
208
+ sync: syncPath||''
209
+ };
210
+ // enable syncing on button click
211
+ $(button)
212
+ .click( function(event){
213
+ event.preventDefault();
214
+ think();
215
+ doSyncAction( unthink );
216
+ return false;
217
+ } )
218
+ //.attr('title', syncPath ? sprintf( translator._('Update from %s'), syncPath ) : translator._('Update from source code') )
219
+ ;
220
+ enable();
221
+ }
222
+ return true;
223
+ }
224
+
225
+ function registerFuzzyButton( button ){
226
+ var toggled = false,
227
+ enabled = false
228
+ ;
229
+ function redraw( message, state ){
230
+ // fuzziness only makes sense when top-level string is translated
231
+ var allowed = message && message.translated(0) || false;
232
+ if( enabled !== allowed ){
233
+ button.disabled = ! allowed;
234
+ enabled = allowed;
235
+ }
236
+ // toggle on/off according to new fuzziness
237
+ if( state !== toggled ){
238
+ $(button)[ state ? 'addClass' : 'removeClass' ]('inverted');
239
+ toggled = state;
240
+ }
241
+ }
242
+ // state changes depending on whether an asset is selected and is fuzzy
243
+ editor
244
+ .on('poSelected', function( event, message ){
245
+ redraw( message, message && message.fuzzy() || false );
246
+ } )
247
+ .on( 'poEmpty', function( event, blank, message, pluralIndex ){
248
+ if( 0 === pluralIndex && blank === enabled ){
249
+ redraw( message, toggled );
250
+ }
251
+ } )
252
+ .on( 'poFuzzy', function( event, message, newState ){
253
+ redraw( message, newState );
254
+ } )
255
+ ;
256
+ // click toggles current state
257
+ $(button).click( function( event ){
258
+ event.preventDefault();
259
+ editor.fuzzy( ! editor.fuzzy() );
260
+ return false;
261
+ } );
262
+ return true;
263
+ };
264
+
265
+ function registerRevertButton( button ){
266
+ // No need for revert when document is saved
267
+ editor
268
+ .on('poUnsaved', function(){
269
+ button.disabled = false;
270
+ } )
271
+ .on('poSave', function(){
272
+ button.disabled = true;
273
+ } )
274
+ ;
275
+ // handling unsaved state prompt with onbeforeunload, see below
276
+ $(button).click( function( event ){
277
+ event.preventDefault();
278
+ location.reload();
279
+ return false;
280
+ } );
281
+ return true;
282
+ };
283
+
284
+ function registerInvisiblesButton( button ){
285
+ var $button = $(button);
286
+ button.disabled = false;
287
+ editor.on('poInvs', function( event, state ){
288
+ $button[ state ? 'addClass' : 'removeClass' ]('inverted');
289
+ });
290
+ $button.click( function( event ){
291
+ event.preventDefault();
292
+ editor.setInvs( ! editor.getInvs() );
293
+ return false;
294
+ } );
295
+ locoScope.tooltip.init($button);
296
+ return true;
297
+ }
298
+
299
+ function registerCodeviewButton( button ){
300
+ var $button = $(button);
301
+ button.disabled = false;
302
+ $button.click( function(event){
303
+ event.preventDefault();
304
+ var state = ! editor.getMono();
305
+ editor.setMono( state );
306
+ $button[ state ? 'addClass' : 'removeClass' ]('inverted');
307
+ return false;
308
+ } );
309
+ locoScope.tooltip.init($button);
310
+ return true;
311
+ };
312
+
313
+ function registerAddButton( button ){
314
+ button.disabled = false;
315
+ $(button).click( function( event ){
316
+ event.preventDefault();
317
+ // Need a placeholder guaranteed to be unique for new items
318
+ var i = 1, baseid, msgid, regex = /(\d+)$/;
319
+ msgid = baseid = 'New message';
320
+ while( messages.get( msgid ) ){
321
+ i = regex.exec(msgid) ? Math.max(i,RegExp.$1) : i;
322
+ msgid = baseid+' '+( ++i );
323
+ }
324
+ editor.add( msgid );
325
+ return false;
326
+ } );
327
+ return true;
328
+ };
329
+
330
+ function registerDelButton( button ){
331
+ button.disabled = false;
332
+ $(button).click( function(event){
333
+ event.preventDefault();
334
+ editor.del();
335
+ return false;
336
+ } );
337
+ return true;
338
+ };
339
+
340
+ function registerDownloadButton( button, id ){
341
+ button.disabled = false;
342
+ $(button).click( function( event ){
343
+ var form = button.form,
344
+ path = filePath;
345
+ // swap out path
346
+ if( 'binary' === id ){
347
+ path = path.replace(/\.po$/,'.mo');
348
+ }
349
+ form.path.value = path;
350
+ form.source.value = messages.toString();
351
+ // allow form to submit
352
+ return true;
353
+ } );
354
+ return true;
355
+ }
356
+
357
+
358
+ // event handler that stops dead
359
+ function noop( event ){
360
+ event.preventDefault();
361
+ return false;
362
+ }
363
+
364
+ /*/ dummy function for enabling buttons that do nothing (or do something inherently)
365
+ function registerNoopButton( button ){
366
+ return true;
367
+ }*/
368
+
369
+ /**
370
+ * Update status message above editor.
371
+ * This is dynamic version of PHP Loco_gettext_Metadata::getProgressSummary
372
+ * TODO implement progress bar, not just text.
373
+ */
374
+ function updateStatus(){
375
+ var t = translator,
376
+ stats = editor.stats(),
377
+ total = stats.t,
378
+ fuzzy = stats.f,
379
+ empty = stats.u,
380
+ // Translators: Shows total string count at top of editor
381
+ stext = sprintf( t._n('1 string','%s strings',total ), total.format(0) ),
382
+ extra = [];
383
+ if( locale ){
384
+ // Translators: Shows percentage translated at top of editor
385
+ stext = sprintf( t._('%s%% translated'), stats.p.replace('%','') ) +', '+ stext;
386
+ // Translators: Shows number of fuzzy strings at top of editor
387
+ fuzzy && extra.push( sprintf( t._('%s fuzzy'), fuzzy.format(0) ) );
388
+ // Translators: Shows number of untranslated strings at top of editor
389
+ empty && extra.push( sprintf( t._('%s untranslated'), empty.format(0) ) );
390
+ if( extra.length ){
391
+ stext += ' ('+extra.join(', ')+')';
392
+ }
393
+ }
394
+ $('#loco-po-status').text( stext );
395
+ if( typeof window.locoEditorStats == 'undefined'){
396
+ window.locoEditorStats = {totalWords:stats.t, totalTranslated:stats.p} ;
397
+ }else{
398
+ window.locoEditorStats.totalWords = stats.t;
399
+ window.locoEditorStats.totalTranslated = stats.p;
400
+ }
401
+
402
+ }
403
+
404
+ /**
405
+ * Enable text filtering
406
+ */
407
+ function initSearchFilter( elSearch ){
408
+ editor.searchable( loco.fulltext.init() );
409
+ // prep search text field
410
+ elSearch.disabled = false;
411
+ elSearch.value = '';
412
+ function showValidFilter( numFound ){
413
+ $(elSearch.parentNode)[ numFound || null == numFound ? 'removeClass' : 'addClass' ]('invalid');
414
+ }
415
+ var listener = loco.watchtext( elSearch, function( value ){
416
+ var numFound = editor.filter( value, true );
417
+ showValidFilter( numFound );
418
+ } );
419
+ editor
420
+ .on( 'poFilter', function( event, value, numFound ){
421
+ listener.val( value||'' );
422
+ showValidFilter( numFound );
423
+ } )
424
+ .on( 'poMerge', function( event, result ){
425
+ var value = listener.val();
426
+ value && editor.filter( value );
427
+ } )
428
+ ;
429
+ }
430
+
431
+ // resize function fits editor to screen, accounting for headroom and touching bottom of screen.
432
+ var resize = function(){
433
+ function top( el, ancestor ){
434
+ var y = el.offsetTop||0;
435
+ while( ( el = el.offsetParent ) && el !== ancestor ){
436
+ y += el.offsetTop||0;
437
+ }
438
+ return y;
439
+ }
440
+ var fixHeight,
441
+ minHeight = parseInt($(innerDiv).css('min-height')||0)
442
+ ;
443
+ return function(){
444
+ var padBottom = 20,
445
+ topBanner = top( innerDiv, document.body ),
446
+ winHeight = window.innerHeight,
447
+ setHeight = Math.max( minHeight, winHeight - topBanner - padBottom )
448
+ ;
449
+ if( fixHeight !== setHeight ){
450
+ innerDiv.style.height = String(setHeight)+'px';
451
+ fixHeight = setHeight;
452
+ }
453
+ };
454
+ }();
455
+
456
+ // ensure outer resize is handled before editor's internal resize
457
+ resize();
458
+ $(window).resize( resize );
459
+
460
+ // initialize editor
461
+ innerDiv.innerHTML = '';
462
+ editor = loco.po.ed
463
+ .init( innerDiv )
464
+ .localise( translator )
465
+ ;
466
+ loco.po.kbd
467
+ .init( editor )
468
+ .add( 'save', saveIfDirty )
469
+ .enable('copy','clear','enter','next','prev','fuzzy','save','invis')
470
+ ;
471
+
472
+ // initialize toolbar button actions
473
+ var buttons = {
474
+ // help: registerNoopButton,
475
+ save: editable && registerSaveButton,
476
+ sync: editable && registerSyncButton,
477
+ revert: registerRevertButton,
478
+ // editor mode togglers
479
+ invs: registerInvisiblesButton,
480
+ code: registerCodeviewButton,
481
+ // downloads / post-throughs
482
+ source: registerDownloadButton,
483
+ binary: template ? null : registerDownloadButton
484
+ };
485
+ // POT only
486
+ if( template ){
487
+ buttons.add = editable && registerAddButton;
488
+ buttons.del = editable && registerDelButton;
489
+ }
490
+ // PO only
491
+ else {
492
+ buttons.fuzzy = registerFuzzyButton;
493
+ };
494
+ $('#loco-toolbar').find('button').each( function(i,el){
495
+ var id = el.getAttribute('data-loco'), register = buttons[id];
496
+ register && register(el,id) || $(el).hide();
497
+ } );
498
+
499
+ // disable submit on dummy form
500
+ $(elForm).submit( noop );
501
+
502
+ // enable text filtering
503
+ initSearchFilter( document.getElementById('loco-search') );
504
+
505
+ // editor event behaviours
506
+ editor
507
+ .on('poUnsaved', function(){
508
+ window.onbeforeunload = onUnloadWarning;
509
+ } )
510
+ .on('poSave', function(){
511
+ updateStatus();
512
+ window.onbeforeunload = null;
513
+ } )
514
+ .on( 'poUpdate', updateStatus );
515
+
516
+
517
+ // load raw message data
518
+ messages.load( conf.podata );
519
+
520
+ // ready to render editor
521
+ editor.load( messages );
522
+
523
+ // locale should be cast to full object once set in editor
524
+ if( locale = editor.targetLocale ){
525
+ locale.isRTL() && $(innerDiv).addClass('trg-rtl');
526
+ }
527
+ // enable template mode when no target locale
528
+ else {
529
+ editor.unlock();
530
+ }
531
+
532
+
533
+ /*
534
+ |--------------------------------------------------------------------------
535
+ | Auto Translator Custom Code
536
+ |--------------------------------------------------------------------------
537
+ */
538
+ //encode URL query string
539
+ function createEncodedString(allStringText){
540
+ const queryString=allStringText.map((item)=>{
541
+ return "&text="+ encodeURIComponent(item.source);
542
+ }).join(",");
543
+
544
+ return queryString;
545
+ }
546
+
547
+ function validLicenseKey(licenseKey){
548
+ if(licenseKey!=undefined && licenseKey.length>1){
549
+ let validKey= validate_pattern(licenseKey);
550
+ if(validKey.length>1){
551
+ return licenseKey;
552
+ }
553
+ }else{
554
+ return false;
555
+ }
556
+
557
+ }
558
+ function validate_pattern(str){
559
+ let m;
560
+ const regex = /^([A-Z0-9]{8})-([A-Z0-9]{8})-([A-Z0-9]{8})-([A-Z0-9]{8})$/gm;
561
+ let saveMatch=[];
562
+ while ((m = regex.exec(str)) !== null) {
563
+ // This is necessary to avoid infinite loops with zero-width matches
564
+ if (m.index === regex.lastIndex) {
565
+ regex.lastIndex++;
566
+ }
567
+ // The result can be accessed through the `m`-variable.
568
+ m.forEach((match, groupIndex) => {
569
+ saveMatch.push(match);
570
+ // console.log(`Found match, group ${groupIndex}: ${match}`);
571
+ });
572
+ }
573
+ return saveMatch;
574
+ }
575
+ function getTargetLang(){
576
+ return window.locoConf.locale.lang?window.locoConf.locale.lang:null;
577
+ }
578
+ $(document).ready(function(){
579
+ if( template ){
580
+ return ;
581
+ }
582
+ const locoRawData=conf.podata;
583
+ if(locoRawData!=undefined && locoRawData.length>0 ){
584
+ // called auto traslate button
585
+ addAutoTranslationBtn();
586
+ }
587
+
588
+ $(document).on("click", "#cool-auto-translate-btn", function() {
589
+ $('#atlt-dialog').dialog({width:400,height:450});
590
+ });
591
+ /* $("#atlt-settings-form").submit(function( event ) {
592
+ event.preventDefault();
593
+ let type = $("input[name='translationtype']:checked").val();
594
+ console.log(type);
595
+ }); */
596
+ // main translate handler
597
+
598
+ $("input[name=api_type]").on( "click",function(){
599
+ if($(this).val()=="google"){
600
+ $("#typehtmlWrapper").hide();
601
+ $("#typeplain").attr("checked","checked");
602
+ }else{
603
+ $("#typehtmlWrapper").show();
604
+ }
605
+ });
606
+
607
+ // integrate reset string traslation button
608
+ $("#atlt_reset_all").on("click",function(){
609
+ swal("What type of strings do you want to reset?",
610
+ {
611
+ dangerMode: true,
612
+ icon: "warning",
613
+ confirmButtonColor: '#8CD4F5',
614
+
615
+ buttons: {
616
+ plain: {
617
+ text: "Plain Text Strings",
618
+ value: "plain",
619
+ class:"danger"
620
+ },
621
+ html: {
622
+ text: "HTML Strings",
623
+ value: "html",
624
+ },
625
+ all: {
626
+ text: "All Strings",
627
+ value: "all",
628
+ },
629
+ cancel: {
630
+ text: "Cancel",
631
+ value: null,
632
+ visible: true,
633
+ className: "",
634
+ closeModal: false,
635
+ },
636
+ },
637
+ })
638
+ .then((value) => {
639
+ switch (value) {
640
+ case "all":
641
+ resetTranslations(value);
642
+ swal("Done!", "You have successfully reset all strings translations. Just close this popup & SAVE!","success");;
643
+ break;
644
+ case "plain":
645
+ resetTranslations(value);
646
+ swal("Done!", "You have successfully reset all plain text strings translations. Just close this popup & SAVE!", "success");
647
+ break;
648
+ case "html":
649
+ resetTranslations(value);
650
+ swal("Done!", "You have successfully reset all strings with HTML translations. Just close this popup & SAVE!", "success");
651
+ break;
652
+ default:
653
+ swal("Cancelled, Just close this popup!");
654
+ }
655
+ });
656
+
657
+ });
658
+
659
+ // reset string array
660
+ function resetTransArr(tranArr,type){
661
+ var resetStrs=[];
662
+ return resetStrs=tranArr.map(function(item){
663
+ if(item.source!==undefined && item.target!==undefined ){
664
+ if(type=="html"){
665
+ if((isHTML(item.source)|| isAllowedChars(item.source))){
666
+ item.target="";
667
+ }
668
+ }
669
+ if(type=="plain"){
670
+ if(isHTML(item.source) || isAllowedChars(item.source)){
671
+ }else{
672
+ item.target="";
673
+ }
674
+ }
675
+ if(type=="all"){
676
+ item.target="";
677
+ }
678
+ return item;
679
+ }
680
+ });
681
+ }
682
+
683
+ // integrate reset translation button
684
+ function resetTranslations(type){
685
+ var resetArr=[];
686
+ const saveBtn=$('[data-loco="save"]');
687
+ if(conf.podata!==undefined){
688
+ if(type=="plain"){
689
+ resetArr=resetTransArr(conf.podata,"plain");
690
+ }else if(type=="html"){
691
+ resetArr=resetTransArr(conf.podata,"html");
692
+ }else{
693
+ resetArr=resetTransArr(conf.podata,"all");
694
+ }
695
+ messages = loco.po.init( locale ).wrap( conf.powrap );
696
+ messages.load(resetArr);
697
+ // editor event behaviours
698
+ editor
699
+ .on('poUnsaved', function(){
700
+ window.onbeforeunload = onUnloadWarning;
701
+ } )
702
+ .on('poSave', function(){
703
+ updateStatus();
704
+ window.onbeforeunload = null;
705
+ } )
706
+ .on( 'poUpdate', updateStatus );
707
+
708
+ // ready to render editor
709
+ editor.load(messages);
710
+ saveBtn.addClass( 'button-primary loco-flagged' ).removeAttr("disabled");
711
+ updateStatus();
712
+ }
713
+ }
714
+ // handle form settings
715
+ $("#atlt-settings-form").submit(function( event ) {
716
+ event.preventDefault();
717
+ const user_type=ATLT["info"].type;
718
+ let strType = $("input[name='translationtype']:checked").val();
719
+ let apiType = $("input[name='api_type']:checked").val();
720
+ let mainBtn=$("#cool-auto-translate-btn");
721
+ var thisBtn=$("#cool-auto-translate-start");
722
+ let sourceApiKey ='';
723
+ var todayLimit= mainBtn.data('today-limit');
724
+ var totalLimit= mainBtn.data('total-limit');
725
+ let targetLang='';
726
+ if(user_type=="free" && strType=="html"){
727
+ alert("HTML Translation Only Available in the PRO version");
728
+ return false;
729
+ }
730
+ if(user_type=="free" && apiType=="google"){
731
+ alert("Google Translation Only Available in the PRO version");
732
+ return false;
733
+ }
734
+ if((user_type==undefined || user_type=="pro") && ATLT["info"]["licenseKey"]==undefined){
735
+ alert("Please enter Your License Key");
736
+ return false;
737
+ }
738
+
739
+ if(conf['locale']["lang"]=!undefined){
740
+ targetLang=conf['locale']["lang"];
741
+ }else{
742
+ targetLang=getTargetLang();
743
+ }
744
+ if(apiType=="google" && strType=="html"){
745
+ alert("Google Translate Only Support Plain Text Translation");
746
+ return false;
747
+ }
748
+ if(apiType=="google"){
749
+ sourceApiKey = ATLT["api_key"]["gApiKey"];
750
+ }else{
751
+ sourceApiKey = ATLT["api_key"]["yApiKey"];
752
+ }
753
+ // filter transable strings
754
+ if(locoRawData!=undefined && locoRawData.length>0 && sourceApiKey!='' ){
755
+ let plainStrArr=[];
756
+ let htmlStrArr=[];
757
+ let orgStrArr=[];
758
+ orgStrArr=locoRawData;
759
+ var countChars=0;
760
+ if(strType=="plain"){
761
+ plainStrArr= filterRawObject(locoRawData,"plain");
762
+ if (plainStrArr !== null) {
763
+ plainStrArr.map(function(index){
764
+ countChars +=index.source.length;
765
+ });
766
+ }
767
+ }else{
768
+ htmlStrArr= filterRawObject(locoRawData,"html");
769
+ if (htmlStrArr !== null) {
770
+ plainStrArr.map(function(index){
771
+ countChars +=index.length;
772
+ });
773
+ }
774
+ }
775
+
776
+ if (htmlStrArr !== null || plainStrArr !== null ) {
777
+ if(countChars>parseInt(todayLimit)){
778
+ alert('Your translation string are larger then available free limit.In order to extend limit Buy Pro license key');
779
+ }else{
780
+
781
+ if(strType=="plain"){
782
+ if(plainStrArr.length==0){
783
+ $("#atlt-dialog").parent('.ui-dialog').hide();
784
+ mainBtn.attr('disabled','disabled');
785
+ alert("You have no untransalted plain strings");
786
+ window.location.reload();
787
+ return;
788
+ }
789
+ dataObj = {
790
+ textToTranslateArr:plainStrArr,
791
+ strType:"plain",
792
+ };
793
+ }else{
794
+ if(htmlStrArr.length==0){
795
+ $("#atlt-dialog").parent('.ui-dialog').hide();
796
+ mainBtn.attr('disabled','disabled');
797
+ alert("You have no untransalted HTML strings");
798
+ window.location.reload();
799
+ return;
800
+ }
801
+ dataObj = {
802
+ textToTranslateArr:htmlStrArr,
803
+ strType:"html",
804
+ };
805
+ }
806
+ // create data object for later use
807
+ dataObj.orgStrArr=orgStrArr;
808
+ dataObj.thisBtn=thisBtn;
809
+ dataObj.apiType=apiType;
810
+ dataObj.targetLang=targetLang;
811
+ // save data object globaly for later use
812
+ window.locoEditorStats.dataObj = dataObj;
813
+ jQuery(document).trigger('atlt_run_translation');
814
+ thisBtn.val('Translating...');
815
+ mainBtn.text("Translating..");
816
+ $("#atlt_preloader").show();
817
+ // load raw message data
818
+
819
+ } //
820
+
821
+ } // else close
822
+ }
823
+
824
+ });
825
+
826
+ });
827
+ // create translation events
828
+ jQuery(document).on('atlt_run_translation',function(){
829
+ let textToTranslate = window.locoEditorStats.dataObj.textToTranslateArr
830
+ let totalTranslated = window.locoEditorStats.totalTranslated
831
+ const apiKey = ATLT["api_key"]["yApiKey"];
832
+ const nonce=ATLT["nonce"];
833
+ const saveBtn=$('[data-loco="save"]');
834
+ const orignalstringArr=window.locoEditorStats.dataObj.orgStrArr;
835
+ const targetLang= window.locoEditorStats.dataObj.targetLang;
836
+ let indexRequest = 50;
837
+ if( ATLT.api_key['atlt_index-per-request'] != "" && typeof ATLT.api_key['atlt_index-per-request'] != "undefined" ){
838
+ indexRequest = ATLT.api_key['atlt_index-per-request'];
839
+ }
840
+
841
+ //save pending array in window object for later use
842
+ if( typeof textToTranslate == "object" && textToTranslate.length >= 1 ){
843
+ // update object for later us
844
+ let translationO = {
845
+ textToTranslateArr:textToTranslate.slice(indexRequest), //save pending index for later us
846
+ thisBtn:window.locoEditorStats.dataObj.thisBtn,
847
+ strType:window.locoEditorStats.dataObj.strType,
848
+ orgStrArr:window.locoEditorStats.dataObj.orgStrArr,
849
+ apiType:window.locoEditorStats.dataObj.apiType,
850
+ targetLang:targetLang,
851
+ };
852
+ window.locoEditorStats.dataObj = translationO;
853
+
854
+ // send partial data request
855
+ let data = {
856
+ sourceLang:'en',
857
+ targetLang:targetLang,
858
+ textToTranslateArr:textToTranslate.slice(0,indexRequest),
859
+ orginalArr:orignalstringArr,
860
+ apiKey:apiKey,
861
+ thisBtn:window.locoEditorStats.dataObj.thisBtn,
862
+ strType:window.locoEditorStats.dataObj.strType,
863
+ apiType:window.locoEditorStats.dataObj.apiType,
864
+ saveBtn:saveBtn,
865
+ nonce:nonce
866
+ };
867
+ // slice data
868
+ textToTranslate.slice(0,indexRequest).map(function(value,index){
869
+ TotalCharacters += (value.source).length;
870
+ requestChars+=(value.source).length;
871
+ })
872
+ atlt_translate(data);
873
+ }
874
+ })
875
+
876
+ // Translate
877
+ function atlt_translate(data) {
878
+
879
+ atlt_ajax_translation_request(data, "POST").success(function(
880
+ resp,status,xhr) {
881
+ if(xhr.status==200){
882
+
883
+ const json_resp = JSON.parse(resp);
884
+ if( json_resp === false && JSON.parse(resp)!=undefined){
885
+ data.thisBtn.hide('slow');
886
+ $("#atlt_preloader").hide();
887
+ $("#cool-auto-translate-btn").text('Translation').attr('disabled','disabled');
888
+ $('#atlt-dialog .atlt-ok.button').show();
889
+
890
+ alert('Unable to make request to the server at the moment. Try again later.');
891
+ }else if(json_resp['code']==500){
892
+ alert('Unable to make request to the server at the moment. Try again later.');
893
+ window.location.reload();
894
+ return;
895
+ }
896
+ else if( typeof json_resp['code'] === undefined ||
897
+ json_resp['code'] != 200 ){
898
+ let error = '';
899
+ switch(json_resp['code']){
900
+ case 401:
901
+ error = 'Yandex API Key is invalid!';
902
+ break;
903
+ case 402:
904
+ error = 'Provided Yandex API Key has been blocked!';
905
+ break;
906
+ case 404:
907
+ error = 'Exceeded the daily limit for Yandex API on the amount of translated text.';
908
+ break;
909
+ case 422:
910
+ error = 'The text cannot be translated by Yandex API.';
911
+ break;
912
+ case 501:
913
+ error = 'Yandex API does not support the specified translation direction.';
914
+ break;
915
+ default:
916
+ error = json_resp['message'];
917
+ }
918
+ if( error != '' && (data.textToTranslateArr).length != 0 ){
919
+ $('#atlt-dialog .atlt-final-message').html("<strong>"+error+"</strong>");
920
+ $('#atlt-dialog .atlt-ok.button').show();
921
+ $("#atlt_preloader").hide();
922
+ $("#cool-auto-translate-btn").text('Error').attr('disabled','disabled');
923
+ //data.thisBtn.attr('disabled','disabled');
924
+ }
925
+ return;
926
+ }
927
+
928
+ let totalTranslated = window.locoEditorStats.totalTranslated;
929
+
930
+ var response = json_resp['translatedString'];
931
+ let unSavedStr=[];
932
+ if(response!==undefined){
933
+ for(i=0;i< response.length;i++){
934
+ var text = response[i];
935
+ if( data.textToTranslateArr[i] === undefined ){
936
+ break;
937
+ }
938
+ data.textToTranslateArr[i].target = text ;
939
+ }
940
+ }
941
+
942
+ let translatedStrArr=data['textToTranslateArr'];
943
+ // var mergeTranslatedText = atlt_arrayUnique(translatedStrArr.concat(data['orginalArr']) );
944
+
945
+ let Emptytargets = [];
946
+ for(var x=0; x<translatedStrArr.length;++x){
947
+ if(translatedStrArr[x].target !='' ){
948
+ Emptytargets[x]=translatedStrArr[x].source;
949
+ }
950
+ }
951
+
952
+ let items;
953
+ if (localStorage.getItem('unSavedString')) {
954
+ items = JSON.parse(localStorage.getItem('unSavedString'))
955
+ } else {
956
+ items = []
957
+ }
958
+ var unSavedStrArr = items.concat(Emptytargets);
959
+ localStorage.setItem('unSavedString', JSON.stringify(unSavedStrArr));
960
+
961
+
962
+ messages = loco.po.init( locale ).wrap( conf.powrap );
963
+ // ready to render editor
964
+ messages.load(data['orginalArr']);
965
+
966
+ // editor event behaviours
967
+ editor
968
+ .on('poUnsaved', function(){
969
+ window.onbeforeunload = onUnloadWarning;
970
+ } )
971
+ .on('poSave', function(){
972
+ updateStatus();
973
+ window.onbeforeunload = null;
974
+ } )
975
+ .on( 'poUpdate', updateStatus );
976
+
977
+ // ready to render editor
978
+ editor.load(messages);
979
+ data.saveBtn.addClass( 'button-primary loco-flagged' ).removeAttr("disabled");
980
+ updateStatus();
981
+ // run through DOM and mark *(STAR) for newly translated
982
+ markUnsavedString();
983
+
984
+ requestChars=0;
985
+ // update progress bar
986
+ $('#atlt-dialog .translated-label').text('Translated');
987
+ $('#atlt-dialog .translated-text').text(window.locoEditorStats.totalTranslated);
988
+
989
+ $('#atlt-dialog .atlt-progress-bar-value').width(window.locoEditorStats.totalTranslated);
990
+ if(json_resp!=undefined){
991
+ if(json_resp['stats']['time_saved']!=undefined){
992
+ var saved_time_msg = '<br/><br/><span style="border: 3px solid #14b75d;display: inline-block;padding: 3px;">Wahooo! You have saved your <strong>'+json_resp['stats']['time_saved']+'</strong> via auto translating '+parseInt(json_resp['stats']['totalChars'])+ ' characters using <strong><a href="https://wordpress.org/support/plugin/automatic-translator-addon-for-loco-translate/reviews/#new-post" target="_new">Loco Automatic Translate Addon</a></strong>.</span><br/><br/>';
993
+ }
994
+ }
995
+ switch( window.locoEditorStats.totalTranslated ){
996
+ case "0%":
997
+ $('#atlt-dialog .translated-label').text('Translating...');
998
+ $('#atlt-dialog .translated-text').text('');
999
+ break;
1000
+ case "100%":
1001
+ data.thisBtn.hide();
1002
+ $("#atlt_preloader").hide();
1003
+ data.thisBtn.attr('disabled','disabled');
1004
+ $("#cool-auto-translate-btn").text('Translated - SAVE NOW').attr('disabled','disabled');
1005
+ // change cursor to 'default' state
1006
+ $('#atlt-dialog .atlt-final-message').html("<strong style='font-size:18px;display:inline-block;margin:5px auto;'>Translation Complete!</strong><br/>(Close this popup & Click <strong>Save</strong>)"+saved_time_msg);
1007
+ $('#atlt-dialog .atlt-ok.button').show();
1008
+ return;
1009
+ break;
1010
+ }
1011
+
1012
+ // run through DOM and mark *(STAR) for newly translated
1013
+ for(var x=0;x<=Emptytargets.length;x++){
1014
+ var source = Emptytargets[x];
1015
+ jQuery("#po-list-tbody div[for='po-list-col-source'] div").filter(function(index){
1016
+ return jQuery(this).text() == source
1017
+ }).addClass('po-unsaved');
1018
+ }
1019
+
1020
+ if( (window.locoEditorStats.dataObj.textToTranslateArr).length == 0){
1021
+ data.thisBtn.val('Translated').attr("disabled","true");
1022
+ $("#atlt_preloader").hide();
1023
+ // data.thisBtn.attr('disabled','disabled').hide('slow');
1024
+ $("#cool-auto-translate-btn").text('Translated - SAVE NOW').attr('disabled','disabled');
1025
+ // change cursor to 'default' state
1026
+ $('#atlt-dialog .atlt-final-message').html("<strong style='font-size:18px;display:inline-block;margin:5px auto;'>Translation Complete!</strong><br/>(Close this popup & Click <strong>Save</strong>)."+saved_time_msg);
1027
+ $('#atlt-dialog .atlt-ok.button').show();
1028
+ return;
1029
+ }
1030
+
1031
+ jQuery(document).trigger('atlt_run_translation');
1032
+
1033
+ }else{
1034
+ data.thisBtn.hide('slow');
1035
+ $("#atlt_preloader").hide();
1036
+ $("#cool-auto-translate-btn").text('Translation').attr('disabled','disabled');
1037
+ $('#atlt-dialog .atlt-ok.button').show();
1038
+ alert('Unable to make request to the server at the moment. Try again later.');
1039
+ }
1040
+ }).fail(function(jqXHR){
1041
+ if(jqXHR.status==500 || jqXHR.status==0){
1042
+ // internal server error or internet connection broke
1043
+ data.thisBtn.hide('slow');
1044
+ $("#atlt_preloader").hide();
1045
+ $("#cool-auto-translate-btn").text('Translation').attr('disabled','disabled');
1046
+ $('#atlt-dialog .atlt-ok.button').show();
1047
+ alert('Unable to make request to the server at the moment. Try again later.');
1048
+ }
1049
+ });
1050
+ }
1051
+ // filter all saved strings
1052
+ function filterSavedStrings(rawArray){
1053
+ return filterdArr=rawArray.filter((item,index)=>{
1054
+ if(item.target!="" &&(item.source!==undefined && item.source!="")){
1055
+ return true;
1056
+ }
1057
+ });
1058
+ }
1059
+
1060
+ // filter string based upon type
1061
+ function filterRawObject(rawArray,filterType){
1062
+ filterdArr=[];
1063
+ return filterdArr=rawArray.filter((item,index)=>{
1064
+ if( (item.target===undefined || item.target=="" && item.source!="" && item.source!==undefined)){
1065
+ if( ValidURL(item.source)){
1066
+ return false;
1067
+ }
1068
+ if(filterType=="html"){
1069
+ if(isContainChars(item.source)){
1070
+ return false;
1071
+ } else if(isHTML(item.source)){
1072
+ return true;
1073
+ }else if(isAllowedChars(item.source)){
1074
+ return true;
1075
+ }else{
1076
+ return false;
1077
+ }
1078
+ }else{
1079
+ if(isHTML(item.source)){
1080
+ return false;
1081
+ }else if(isSpecialChars(item.source)){
1082
+ return false;
1083
+ }else if( item.source.includes('#') ) {
1084
+ return false;
1085
+ }else{
1086
+ return true;
1087
+ }
1088
+ }
1089
+ }
1090
+ });
1091
+ }
1092
+
1093
+ // find unique index in array
1094
+ function atlt_arrayUnique(array) {
1095
+ var a = array.concat();
1096
+ for(var i=0; i<a.length; ++i) {
1097
+ for(var j=i+1; j<a.length; ++j) {
1098
+ if(a[i] === a[j])
1099
+ a.splice(j--, 1);
1100
+ }
1101
+ }
1102
+ return a;
1103
+ }
1104
+
1105
+
1106
+ // auto traslator button in editor
1107
+ function addAutoTranslationBtn(){
1108
+ if($("#loco-toolbar").find("#cool-auto-translate-btn").length>0){
1109
+ $("#loco-toolbar").find("#cool-auto-translate-btn").remove();
1110
+ }
1111
+ const locoActions= $("#loco-toolbar").find("#loco-actions");
1112
+ const otherBtn='<button class="button has-icon icon-warn" id="atlt_reset_all">Reset Translations</button></fieldset>';
1113
+ const allTranslated='<fieldset><button id="cool-auto-translate-btn" class="button has-icon icon-translate" disabled>Translated</button></fieldset>';
1114
+ let savedStrings=filterSavedStrings(conf.podata);
1115
+
1116
+ let plainStrings= filterRawObject(conf.podata,"plain");
1117
+ let htmlStrings = filterRawObject(conf.podata,"html");
1118
+ const userType=ATLT["info"].type;
1119
+ if((Array.isArray(plainStrings) && plainStrings.length) ||
1120
+ (Array.isArray(htmlStrings)&& htmlStrings.length)
1121
+ ){
1122
+ const inActiveBtn='<fieldset><button title="Add API key to enable this feature." id="cool-auto-translate-btn" disabled class="button has-icon icon-translate">Auto Translate</button> <a style="font-size:9px;display:block;margin-left:8px;" target="_blank" href="https://tech.yandex.com/translate/">Get Free API Key</a></fieldset>';
1123
+ const disabledBtn='<fieldset><button title="Buy PRO." id="cool-auto-translate-btn" disabled class="button has-icon icon-translate">Auto Translate</button><div style="max-width:320px; display:inline-block;margin-top: 4px;"><span style="font-size:12px;display:inline-block;margin-left:8px;">You have exceeded free translation limit. In order to extend the limit - <a target="_blank" style="font-size:14px;display:inline-block;margin-left:8px;" target="_blank" href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/#pricing">Buy Premium License</a></span></div></fieldset>';
1124
+ const apiKey=ATLT["api_key"]["yApiKey"];
1125
+ const proActiveBtn='<fieldset><button id="cool-auto-translate-btn" class="button has-icon icon-translate">Auto Translate</button></fieldset>';
1126
+ const allowed=ATLT["info"].allowed;
1127
+ const today=ATLT["info"].today;
1128
+ const total=ATLT["info"].total;
1129
+ const aTodayChars=300000;
1130
+ const aTodayChar=1000000;
1131
+
1132
+ // not added API key
1133
+ if( ATLT == '' || ATLT["api_key"] == '' || apiKey=='' ){
1134
+ if( userType=='free'){
1135
+ locoActions.append(inActiveBtn);
1136
+ return;
1137
+ }else{
1138
+ locoActions.append(proActiveBtn);
1139
+ }
1140
+ }else if( allowed=="no" && userType=='free'){
1141
+ // free not allowed
1142
+ locoActions.append(disabledBtn);
1143
+ return;
1144
+ }else if(today!==undefined && parseInt(today)>aTodayChars
1145
+ && userType=='free'){
1146
+ // today free limit exceeded
1147
+ locoActions.append(disabledBtn);
1148
+ return;
1149
+ }else if(total!==undefined && parseInt(total)>aTodayChar
1150
+ && userType=='free'){
1151
+ // monthly limit exceeded
1152
+ locoActions.append(disabledBtn);
1153
+ return;
1154
+ }else if( window.locoEditorStats.totalTranslated != "100%"
1155
+ && window.locoEditorStats.totalWords > 0 ){
1156
+ //Pro user and added key then show button
1157
+ if(userType=='pro' && ATLT["info"]["licenseKey"]!=undefined && validLicenseKey(ATLT["info"]["licenseKey"])){
1158
+ locoActions.append(proActiveBtn);
1159
+ }else{
1160
+ //if user is free and allowed the show button
1161
+ if(today==undefined){
1162
+ var todayChars=aTodayChars;
1163
+ }else{
1164
+ var todayChars=aTodayChars-parseInt(today);
1165
+ }
1166
+ var totalChars=aTodayChar-parseInt(total);
1167
+ // append button for free
1168
+ var freeBtn='<fieldset><button data-today-limit="'+todayChars+'" data-total-limit="'+totalChars+'" id="cool-auto-translate-btn" class="button has-icon icon-translate">Auto Translate</button></fieldset>';
1169
+ locoActions.append(freeBtn);
1170
+ }
1171
+ } else if( window.locoEditorStats.totalWords == 0){
1172
+ return;
1173
+ }
1174
+ } else{
1175
+ locoActions.append(allTranslated);
1176
+ }
1177
+
1178
+ if((Array.isArray(savedStrings) && savedStrings.length)){
1179
+ if(userType=='pro' && ATLT["info"]["licenseKey"]!=undefined && validLicenseKey(ATLT["info"]["licenseKey"])){
1180
+ locoActions.append(otherBtn);
1181
+ }
1182
+ }
1183
+
1184
+ }
1185
+
1186
+
1187
+ // mark unsaved after ajax translation process
1188
+ function markUnsavedString(){
1189
+ const unSavedString = JSON.parse(localStorage.getItem('unSavedString'));
1190
+
1191
+ for(var x=0;x<=unSavedString.length;x++){
1192
+ var source = unSavedString[x];
1193
+ jQuery("#po-list-tbody div[for='po-list-col-source'] div").filter(function(index){
1194
+ return jQuery(this).text() == source
1195
+ }).addClass('po-unsaved');
1196
+ }
1197
+ }
1198
+
1199
+ // detect String contain URL
1200
+ function ValidURL(str) {
1201
+ var pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
1202
+ if(!pattern.test(str)) {
1203
+ return false;
1204
+ } else {
1205
+ return true;
1206
+ }
1207
+ }
1208
+ // detect Valid HTML in string
1209
+ function isHTML(str){
1210
+ var rgex=/<(?=.*? .*?\/ ?>|br|hr|input|!--|wbr)[a-z]+.*?>|<([a-z]+).*?<\/\1>/i;
1211
+ if(str!==undefined){
1212
+ return rgex.test(str);
1213
+ }else {
1214
+ return false;
1215
+ }
1216
+ }
1217
+ // check special chars in string
1218
+ function isSpecialChars(str){
1219
+ var rgex=/[@#^$%&*{}|<>]/g;
1220
+ if(str!==undefined){
1221
+ return rgex.test(str);
1222
+ }else {
1223
+ return false;
1224
+ }
1225
+ }
1226
+ // allowed special chars in HTML string
1227
+ function isAllowedChars(str){
1228
+ var rgex=/[!@#$%^&*(),?":|<>]/g;
1229
+ if(str!==undefined){
1230
+ return rgex.test(str);
1231
+ }else {
1232
+ return false;
1233
+ }
1234
+ }
1235
+ // check string contain curly brackets
1236
+ function isContainChars(str){
1237
+ var rgex=/[{}[]/g;
1238
+ if(str!==undefined){
1239
+ return rgex.test(str);
1240
+ }else {
1241
+ return false;
1242
+ }
1243
+ }
1244
+ // format numbers
1245
+ function atltFormatNumber(num) {
1246
+ return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
1247
+ }
1248
+
1249
+ // create popup model for translation settings
1250
+ function createSettingsPopup(){
1251
+ let preloaderImg=extradata['preloader_path'];
1252
+ const userInfo=ATLT["info"].type;
1253
+ const yAC=ATLT["info"].yAvailableChars;
1254
+ const licenseKey=ATLT["info"]["licenseKey"];
1255
+
1256
+ let yfieldStatus="";
1257
+ let gfieldStatus="";
1258
+ let hfieldStatus="";
1259
+ let htmlSupported="";
1260
+ let contCls="";
1261
+ let proLbl="";
1262
+ let gContCls='';
1263
+ let gHtml='';
1264
+ let submitBtn='';
1265
+ let yHtml='';
1266
+ let yChecked='checked="true"';
1267
+ if(userInfo=="free"){
1268
+ let gAC=0;
1269
+ gfieldStatus="disabled";
1270
+ hfieldStatus="disabled";
1271
+ contCls="html-disabled";
1272
+ gContCls='g-disabled';
1273
+ proLbl='<span class="atlt-pro-feature"><a href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/#pricing" target="_blank" style="color:red;font-weight:bold;" title="Only For Pro Users">PRO Only</a></span>';
1274
+ gHtml=proLbl+' (70% better than Yendex Translate)';
1275
+ }else{
1276
+
1277
+ if( ATLT["info"]["licenseKey"]!=undefined && validLicenseKey(ATLT["info"]["licenseKey"])
1278
+ && ATLT["api_key"]["gApiKey"]!=""){
1279
+ let gAC=ATLT["info"].gAvailableChars;
1280
+ if(gAC!==undefined && gAC>10000){
1281
+ gHtml='<span class="available-chars"> ('+ atltFormatNumber(gAC)+' Available This Month)</span>';
1282
+ }
1283
+ if(gAC<10000){
1284
+ gHtml='<span class="used-chars">You have consumed All Free Characters</span>';
1285
+ }
1286
+ }else{
1287
+ gfieldStatus="disabled";
1288
+ gContCls='g-disabled';
1289
+
1290
+ gHtml='<span class="error">Please Enter Google Translate API key in the Settings Panel</span>';
1291
+ }
1292
+
1293
+ if(ATLT["api_key"]["yApiKey"]!="")
1294
+ {
1295
+ if(yAC!==undefined){
1296
+ yHtml='<span class="available-chars"> ('+atltFormatNumber(yAC)+' Available Today)</span>';
1297
+ }
1298
+ }else{
1299
+ yfieldStatus="disabled";
1300
+ yContCls='g-disabled';
1301
+ yChecked='';
1302
+ yHtml='<span class="error">Please Enter Yandex API key in the Settings Panel</span>';
1303
+ }
1304
+ }
1305
+ if( ATLT["api_key"]["yApiKey"]!="" || ATLT["api_key"]["gApiKey"]!="" )
1306
+ {
1307
+ submitBtn='<input type="submit" class="button has-icon icon-translate" value="Start Translation" id="cool-auto-translate-start">';
1308
+ }else{
1309
+ submitBtn='<button class="atlt-ok button button-primary">OK</button>';
1310
+
1311
+ }
1312
+ let settingsHTML=`<div class="atlt-settings">
1313
+ <form id="atlt-settings-form" method="post" action="#">
1314
+ <strong class="atlt-heading">Select Translation API</strong>
1315
+ <div class="inputGroup">
1316
+ <input class="inputEle" type="radio" id="yandex_api"
1317
+ ${yChecked} ${yfieldStatus} name="api_type" value="yandex">
1318
+ <label for="yandex_api">Yandex ${yHtml}</label>
1319
+ </div>
1320
+ <div class="inputGroup ${gContCls}">
1321
+ <input class="inputEle" type="radio" id="google_api"
1322
+ name="api_type" value="google" ${gfieldStatus}>
1323
+ <label for="google_api">Google</label> ${gHtml}
1324
+ </div>
1325
+ <br/>
1326
+ <strong class="atlt-heading">Select Content Type</strong>
1327
+ <div class="inputGroup">
1328
+ <input class="inputEle" type="radio" id="typeplain" checked="true" name="translationtype" value="plain">
1329
+ <label for="typeplain">Translate Plain Text Strings</label>
1330
+ </div>
1331
+ <div id="typehtmlWrapper" class="inputGroup ${contCls}">
1332
+ <input class="inputEle" type="radio" id="typehtml" name="translationtype" value="html" ${hfieldStatus}>
1333
+ <label for="typehtml">Translate HTML Strings (Beta) ${proLbl}
1334
+ </label>
1335
+ </br>
1336
+ <small style="display:inline-block;margin-left:24px;margin-top:8px;">(<a href="https://locotranslate.com/html-translation-languages-list/" target="_blank">List of languages with HTML support</a>)</small>
1337
+ </div>
1338
+
1339
+ <br/>
1340
+ <fieldset>
1341
+ ${submitBtn}
1342
+ <img style="display:none;margin-left:10px;margin-top:-3px;" id="atlt_preloader" src="${preloaderImg}">
1343
+ </fieldset>
1344
+ </form>
1345
+ </div>`;
1346
+ // custom popup message box
1347
+ let popup_html = `<div id="atlt-dialog-container">
1348
+ <div style="display:none;" id="atlt-dialog" title="Automatic Translation Progress">
1349
+ ${settingsHTML}
1350
+ <p><span class="translated-label">Translated</span>
1351
+ <span class="translated-text">0%</span></p>
1352
+ <div class="atlt-progress-bar-track">
1353
+ <div class="atlt-progress-bar-value">
1354
+ </div></div>
1355
+ <div class="atlt-final-message"></div>
1356
+ <button style="display:none;" class="atlt-ok button button-primary">OK</button>
1357
+ </div></div>`;
1358
+ $("body").append( popup_html );
1359
+ }
1360
+
1361
+ // send ajax request
1362
+ function atlt_ajax_translation_request(data,type){
1363
+ let filteredArr=[];
1364
+ filteredArr=data.textToTranslateArr.map((item)=>{
1365
+ if( typeof item.source!= 'undefined'){
1366
+ return item.source;
1367
+ } });
1368
+ const jsonData=JSON.stringify(filteredArr);
1369
+
1370
+ return jQuery.ajax({
1371
+ url: ajaxurl,
1372
+ type:'POST',
1373
+ data: {'action':'atlt_translation',
1374
+ 'sourceLan':data.sourceLang,
1375
+ 'targetLan':data.targetLang,
1376
+ 'totalCharacters': TotalCharacters,
1377
+ 'requestChars':requestChars,
1378
+ 'nonce':data.nonce,
1379
+ 'strType':data.strType,
1380
+ 'apiType':data.apiType,
1381
+ 'data':jsonData
1382
+ },
1383
+ done:function(res){
1384
+ // console.log(res)
1385
+ }
1386
+
1387
+
1388
+ });
1389
+ }
1390
+
1391
+ // ok, editor ready
1392
+ updateStatus();
1393
+
1394
+ // clean up
1395
+ //delete window.locoConf;
1396
+ //conf = buttons = null;
1397
+
1398
+ }( window, jQuery );
assets/js/loco-js-editor.min.js CHANGED
@@ -1 +1,1398 @@
1
- !function(t,e){var a=0,o=0;document.createEvent("event").initEvent("atlt_translated"),function(){let t=extradata.preloader_path;const a=ATLT.info.type;let o="",n="",l="";"free"==a&&(o="disabled",n="html-disabled",l='<span class="atlt-pro-feature"><a href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/" target="_blank" style="color:red;font-weight:bold;" title="Only For Pro Users">PRO Only</a></span>');let r=`<div id="atlt-dialog-container">\n <div style="display:none;" id="atlt-dialog" title="Automatic Translation Progress">\n ${`<div class="atlt-settings">\n <form id="atlt-settings-form" method="post" action="#">\n <strong class="atlt-heading">Select Content Type</strong>\n <div class="inputGroup">\n <input class="inputEle" type="radio" id="typeplain" checked="true" name="translationtype" value="plain">\n <label for="typeplain">Translate Plain Text Strings</label>\n </div><div class="inputGroup ${n}">\n <input class="inputEle" type="radio" id="typehtml" name="translationtype" value="html" ${o}>\n <label for="typehtml">Translate HTML Strings (Beta) ${l}<br/><small style="display:inline-block;margin-left:24px;margin-top:8px;">(<a href="https://locotranslate.com/html-translation-languages-list/" target="_blank">List of languages with HTML support</a>)</small></label>\n </div>\n <br/>\n <fieldset><input type="submit" class="button has-icon icon-translate" value="Start Translation" id="cool-auto-translate-start">\n <img style="display:none;margin-left:10px;margin-top:-3px;" id="atlt_preloader" src="${t}">\n </fieldset>\n </form>\n </div>`}\n <p><span class="translated-label">Translated</span>\n <span class="translated-text">0%</span></p>\n <div class="atlt-progress-bar-track">\n <div class="atlt-progress-bar-value">\n </div></div>\n <div class="atlt-final-message"></div>\n <button style="display:none;" class="atlt-ok button button-primary">OK</button>\n </div></div>`;e("body").append(r)}(),e("#atlt-dialog .atlt-ok.button").on("click",function(){localStorage.removeItem("unSavedString"),e("#atlt-dialog").parent(".ui-dialog").hide()});var n,l=t.locoScope,r=t.locoConf,s=null,d=null,c=l.l10n,u=l.string.sprintf,p=r.locale,f=l.po.init(p).wrap(r.powrap),g=!p,b=document.getElementById("loco-actions"),v=r.popath,h=r.potpath,m=document.getElementById("loco-fs"),y=m&&l.fs.init(m),T=!r.readonly,x=document.getElementById("loco-editor-inner");function S(t){d.locale=String(f.locale()||""),y&&y.applyCreds(d),d.data=String(f),l.ajax.post("save",d,function(a){t&&t(),n.save(!0),e("#loco-po-modified").text(a.datetime||"[datetime error]")},t)}function k(){return c._("Your changes will be lost if you continue without saving")}function A(t,a){return t.disabled=!1,e(t).click(function(e){var o=t.form,n=v;return"binary"===a&&(n=n.replace(/\.po$/,".mo")),o.path.value=n,o.source.value=f.toString(),!0}),!0}function _(){var a=c,o=n.stats(),l=o.t,r=o.f,i=o.u,s=u(a._n("1 string","%s strings",l),l.format(0)),d=[];p&&(s=u(a._("%s%% translated"),o.p.replace("%",""))+", "+s,r&&d.push(u(a._("%s fuzzy"),r.format(0))),i&&d.push(u(a._("%s untranslated"),i.format(0))),d.length&&(s+=" ("+d.join(", ")+")")),e("#loco-po-status").text(s),void 0===t.locoEditorStats?t.locoEditorStats={totalWords:o.t,totalTranslated:o.p}:(t.locoEditorStats.totalWords=o.t,t.locoEditorStats.totalTranslated=o.p)}var w=function(){var a,o=parseInt(e(x).css("min-height")||0);return function(){var e=function(t,e){for(var a=t.offsetTop||0;(t=t.offsetParent)&&t!==e;)a+=t.offsetTop||0;return a}(x,document.body),n=t.innerHeight,l=Math.max(o,n-e-20);a!==l&&(x.style.height=String(l)+"px",a=l)}}();w(),e(t).resize(w),x.innerHTML="",n=l.po.ed.init(x).localise(c),l.po.kbd.init(n).add("save",function(){n.dirty&&S()}).enable("copy","clear","enter","next","prev","fuzzy","save","invis");var E={save:T&&function(t){function a(){t.disabled=!0}function o(){t.disabled=!1}function l(){o(),e(t).removeClass("loco-loading")}return t,n.on("poUnsaved",function(){o(),e(t).addClass("button-primary loco-flagged")}).on("poSave",function(){a(),e(t).removeClass("button-primary loco-flagged")}),d=e.extend({path:v},r.project||{}),e(t).click(function(o){return o.preventDefault(),a(),e(t).addClass("loco-loading"),S(l),!1}),!0},sync:T&&function(a){var o=r.project;if(o){function i(){a.disabled=!0}function d(){a.disabled=!1}function p(){d(),e(a).removeClass("loco-loading")}n.on("poUnsaved",function(){i()}).on("poSave",function(){d()}),s={bundle:o.bundle,domain:o.domain,type:g?"pot":"po",sync:h||""},e(a).click(function(o){var r;return o.preventDefault(),i(),e(a).addClass("loco-loading"),r=p,l.ajax.post("sync",s,function(a){var o=[],i=f,s=a.po,d=a.pot,p=l.po.init().load(s),g=i.merge(p),b=g.add.length,v=g.del.length,h=c;n.load(i),b||v?(d?o.push(u(h._("Merged from %s"),d)):o.push(h._("Merged from source code")),b&&o.push(u(h._n("1 new string added","%s new strings added",b),b)),v&&o.push(u(h._n("1 obsolete string removed","%s obsolete strings removed",v),v)),e(x).trigger("poUnsaved",[]),_(),t.console&&function(t,e){for(var a=-1,o=e.add.length;++a<o;)t.log(" + "+e.add[a].source());for(a=-1,o=e.del.length;++a<o;)t.log(" - "+e.del[a].source())}(console,g)):d?o.push(u(h._("Already up to date with %s"),d)):o.push(h._("Already up to date with source code")),l.notices.success(o.join(". ")),e(x).trigger("poMerge",[a]),r&&r()},r),!1}),d()}return!0},revert:function(t){return n.on("poUnsaved",function(){t.disabled=!1}).on("poSave",function(){t.disabled=!0}),e(t).click(function(t){return t.preventDefault(),location.reload(),!1}),!0},invs:function(t){var a=e(t);return t.disabled=!1,n.on("poInvs",function(t,e){a[e?"addClass":"removeClass"]("inverted")}),a.click(function(t){return t.preventDefault(),n.setInvs(!n.getInvs()),!1}),locoScope.tooltip.init(a),!0},code:function(t){var a=e(t);return t.disabled=!1,a.click(function(t){t.preventDefault();var e=!n.getMono();return n.setMono(e),a[e?"addClass":"removeClass"]("inverted"),!1}),locoScope.tooltip.init(a),!0},source:A,binary:g?null:A};function j(t){return!!/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/.test(t)}function C(t){return void 0!==t&&/<(?=.*? .*?\/ ?>|br|hr|input|!--|wbr)[a-z]+.*?>|<([a-z]+).*?<\/\1>/i.test(t)}g?(E.add=T&&function(t){return t.disabled=!1,e(t).click(function(t){t.preventDefault();var e,a=1,o=/(\d+)$/;for(e="New message";f.get(e);)a=o.exec(e)?Math.max(a,RegExp.$1):a,e="New message "+ ++a;return n.add(e),!1}),!0},E.del=T&&function(t){return t.disabled=!1,e(t).click(function(t){return t.preventDefault(),n.del(),!1}),!0}):E.fuzzy=function(t){var a=!1,o=!1;function l(n,l){var r=n&&n.translated(0)||!1;o!==r&&(t.disabled=!r,o=r),l!==a&&(e(t)[l?"addClass":"removeClass"]("inverted"),a=l)}return n.on("poSelected",function(t,e){l(e,e&&e.fuzzy()||!1)}).on("poEmpty",function(t,e,n,r){0===r&&e===o&&l(n,a)}).on("poFuzzy",function(t,e,a){l(e,a)}),e(t).click(function(t){return t.preventDefault(),n.fuzzy(!n.fuzzy()),!1}),!0},e("#loco-toolbar").find("button").each(function(t,a){var o=a.getAttribute("data-loco"),n=E[o];n&&n(a,o)||e(a).hide()}),e(b).submit(function(t){return t.preventDefault(),!1}),function(t){function a(a){e(t.parentNode)[a||null==a?"removeClass":"addClass"]("invalid")}n.searchable(l.fulltext.init()),t.disabled=!1,t.value="";var o=l.watchtext(t,function(t){a(n.filter(t,!0))});n.on("poFilter",function(t,e,n){o.val(e||""),a(n)}).on("poMerge",function(t,e){var a=o.val();a&&n.filter(a)})}(document.getElementById("loco-search")),n.on("poUnsaved",function(){t.onbeforeunload=k}).on("poSave",function(){_(),t.onbeforeunload=null}).on("poUpdate",_),f.load(r.podata),n.load(f),(p=n.targetLocale)?p.isRTL()&&e(x).addClass("trg-rtl"):n.unlock(),e(document).ready(function(){const a=r.podata;null!=a&&a.length>0&&function(){e("#loco-toolbar").find("#cool-auto-translate-btn").length>0&&e("#loco-toolbar").find("#cool-auto-translate-btn").remove();const a='<fieldset><button title="Buy PRO." id="cool-auto-translate-btn" disabled class="button has-icon icon-translate">Auto Translate</button><div style="max-width:320px; display:inline-block;margin-top: 4px;"><span style="font-size:12px;display:inline-block;margin-left:8px;">You have exceeded free translation limit. In order to extend the limit - <a target="_blank" style="font-size:14px;display:inline-block;margin-left:8px;" target="_blank" href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/">Buy Premium License</a></span></div></fieldset>',o=ATLT.api_key["atlt_api-key"],n=ATLT.info.type,l=ATLT.info.allowed,r=ATLT.info.today,i=ATLT.info.total;if(""==ATLT||""==ATLT.api_key||""==o)return void e("#loco-toolbar").find("#loco-actions").append('<fieldset><button title="Add API key to enable this feature." id="cool-auto-translate-btn" disabled class="button has-icon icon-translate">Auto Translate</button> <a style="font-size:9px;display:block;margin-left:8px;" target="_blank" href="https://tech.yandex.com/translate/">Get Free API Key</a></fieldset>');if("no"==l&&"free"==n)return void e("#loco-toolbar").find("#loco-actions").append(a);if(void 0!==r&&parseInt(r)>3e5&&"free"==n)return void e("#loco-toolbar").find("#loco-actions").append(a);if(void 0!==i&&parseInt(i)>1e6&&"free"==n)return void e("#loco-toolbar").find("#loco-actions").append(a);if("100%"!=t.locoEditorStats.totalTranslated&&t.locoEditorStats.totalWords>0)if("pro"==n&&ATLT.info.licenseKey)e("#loco-toolbar").find("#loco-actions").append('<fieldset><button id="cool-auto-translate-btn" class="button has-icon icon-translate">Auto Translate</button> <a style="font-size:9px;display:block;margin-left:8px;" target="_blank" href="http://translate.yandex.com/">Powered by Yandex.Translate</a></fieldset>');else{if(null==r)var s=3e5;else var s=3e5-parseInt(r);var d=1e6-parseInt(i),c='<fieldset><button data-today-limit="'+s+'" data-total-limit="'+d+'" id="cool-auto-translate-btn" class="button has-icon icon-translate">Auto Translate</button> <a style="font-size:9px;display:block;margin-left:8px;" target="_blank" href="http://translate.yandex.com/">Powered by Yandex.Translate</a></fieldset>';e("#loco-toolbar").find("#loco-actions").append(c)}else{if(0==t.locoEditorStats.totalWords)return;e("#loco-toolbar").find("#loco-actions").append('<fieldset><button id="cool-auto-translate-btn" class="button has-icon icon-translate" disabled>Translated</button></fieldset>')}}(),e(document).on("click","#cool-auto-translate-btn",function(){e("#atlt-dialog").dialog({width:320,height:300})}),e("#atlt-settings-form").submit(function(o){o.preventDefault();let n=e("input[name='translationtype']:checked").val(),l=e("#cool-auto-translate-btn");var r=e("#cool-auto-translate-start"),i=l.data("today-limit");l.data("total-limit");const s=ATLT.api_key["atlt_api-key"];if(null!=a&&a.length>0&&""!=s){let o=[],s=[],c=[];c=a,s=a.filter((t,e)=>{if(void 0===t.target||""==t.target&&""!=t.source&&void 0!==t.source)return!j(t.source)&&(!function(t){return void 0!==t&&/[{}[]/g.test(t)}(t.source)&&(!!C(t.source)||!!function(t){return void 0!==t&&/[!@#$%^&*(),?":|<>]/g.test(t)}(t.source)))}),o=a.filter((t,e)=>{if((void 0===t.target||""==t.target)&&""!=t.source)return!C(t.source)&&!j(t.source)&&(!function(t){return void 0!==t&&/[@#^&*{}|<>]/g.test(t)}(t.source)&&1!=t.source.includes("#"))});var d=0;if("plain"==n?null!==o&&o.map(function(t){d+=t.source.length}):null!==s&&o.map(function(t){d+=t.length}),null!==s||null!==o)if(d>parseInt(i))alert("Your translation string are larger then available free limit.In order to extend limit Buy Pro license key");else{if("plain"==n){if(0==o.length)return e("#atlt-dialog").parent(".ui-dialog").hide(),l.attr("disabled","disabled"),alert("You have no untransalted strings"),void t.location.reload();dataObj={textToTranslateArr:o,thisBtn:e(this),strType:"plain"}}else{if(0==s.length)return e("#atlt-dialog").parent(".ui-dialog").hide(),l.attr("disabled","disabled"),alert("You have no untransalted HTML strings"),void t.location.reload();dataObj={textToTranslateArr:s,thisBtn:e(this),strType:"html"}}dataObj.orgStrArr=c,r.val("Translating..."),l.text("Translating.."),e("#atlt_preloader").show(),t.locoEditorStats.dataObj=dataObj,jQuery(document).trigger("atlt_translated")}}})}),jQuery(document).on("atlt_translated",function(){let s=t.locoEditorStats.dataObj.textToTranslateArr;t.locoEditorStats.totalTranslated;const d=ATLT.api_key["atlt_api-key"],c=ATLT.nonce,u=e('[data-loco="save"]'),g=t.locoEditorStats.dataObj.orgStrArr,b=r.locale.lang;let v=50;if(""!=ATLT.api_key["atlt_index-per-request"]&&void 0!==ATLT.api_key["atlt_index-per-request"]&&(v=ATLT.api_key["atlt_index-per-request"]),"object"==typeof s&&s.length>=1){let h={textToTranslateArr:s.slice(v),thisBtn:t.locoEditorStats.dataObj.thisBtn,strType:t.locoEditorStats.dataObj.strType,orgStrArr:t.locoEditorStats.dataObj.orgStrArr};t.locoEditorStats.dataObj=h;let m={sourceLang:"en",targetLang:b,textToTranslateArr:s.slice(0,v),orginalArr:g,apiKey:d,thisBtn:t.locoEditorStats.dataObj.thisBtn,strType:t.locoEditorStats.dataObj.strType,saveBtn:u,nonce:c};s.slice(0,v).map(function(t,e){a+=t.source.length,o+=t.source.length}),function(s){(function(t,e){let n=[];n=t.textToTranslateArr.map(t=>{if(void 0!==t.source)return t.source});const l=JSON.stringify(n);return jQuery.ajax({url:ajaxurl,type:"POST",data:{action:"atlt_translation",sourceLan:t.sourceLang,targetLan:t.targetLang,totalCharacters:a,requestChars:o,nonce:t.nonce,strType:t.strType,data:l},done:function(t){console.log(t)}})})(s).success(function(a){const d=JSON.parse(a);if(0==d)s.thisBtn.hide("slow"),e("#cool-auto-translate-btn").attr("disabled","disabled"),e("#cool-auto-translate-btn").text("Translation").attr("disabled","disabled"),alert("Unable to make request to the server at the moment. Try again later.");else if(void 0===typeof d.code||200!=d.code){let t="";switch(d.code){case 401:t="Yendex API Key is invalid!";break;case 402:t="Provided Yendex API Key has been blocked!";break;case 404:t="Exceeded the daily limit for Yendex API on the amount of translated text.";break;case 422:t="The text cannot be translated by Yendex API.";break;case 501:t="Yendex API does not support the specified translation direction.";break;default:t=d.message}return void(""!=t&&0!=s.textToTranslateArr.length&&(e("#atlt-dialog .atlt-final-message").html("<strong>"+t+"</strong>"),e("#atlt-dialog .atlt-ok.button").show(),s.thisBtn.val("Translation"),e("#cool-auto-translate-btn").text("Translation").attr("disabled","disabled"),s.thisBtn.attr("disabled","disabled")))}t.locoEditorStats.totalTranslated;var c=d.text;if(void 0!==c)for(i=0;i<c.length;i++){var u=c[i];if(void 0===s.textToTranslateArr[i])break;s.textToTranslateArr[i].target=u}let g=s.textToTranslateArr;var b=function(t){for(var e=t.concat(),a=0;a<e.length;++a)for(var o=a+1;o<e.length;++o)e[a]===e[o]&&e.splice(o--,1);return e}(g.concat(s.orginalArr));let v,h=[];for(var m=0;m<g.length;++m)""!=g[m].target&&(h[m]=g[m].source);var y=(v=localStorage.getItem("unSavedString")?JSON.parse(localStorage.getItem("unSavedString")):[]).concat(h);if(localStorage.setItem("unSavedString",JSON.stringify(y)),(f=l.po.init(p).wrap(r.powrap)).load(b),n.on("poUnsaved",function(){t.onbeforeunload=k}).on("poSave",function(){_(),t.onbeforeunload=null}).on("poUpdate",_),n.load(f),s.saveBtn.addClass("button-primary loco-flagged").removeAttr("disabled"),_(),function(){const t=JSON.parse(localStorage.getItem("unSavedString"));console.log(t);for(var e=0;e<=t.length;e++){var a=t[e];jQuery("#po-list-tbody div[for='po-list-col-source'] div").filter(function(t){return jQuery(this).text()==a}).addClass("po-unsaved")}}(),o=0,e("#atlt-dialog .translated-label").text("Translated"),e("#atlt-dialog .translated-text").text(t.locoEditorStats.totalTranslated),e("#atlt-dialog .atlt-progress-bar-value").width(t.locoEditorStats.totalTranslated),void 0!==d&&void 0!==d.stats.time_saved)var T='<br/><br/><span style="border: 3px solid #14b75d;display: inline-block;padding: 3px;">Wahooo! You have saved your <strong>'+d.stats.time_saved+"</strong> via auto translating "+parseInt(d.stats.totalChars)+' characters using <strong><a href="https://wordpress.org/support/plugin/automatic-translator-addon-for-loco-translate/reviews/#new-post" target="_new">Loco Automatic Translate Addon</a></strong>.</span><br/><br/>';switch(t.locoEditorStats.totalTranslated){case"0%":e("#atlt-dialog .translated-label").text("Translating..."),e("#atlt-dialog .translated-text").text("");break;case"100%":return s.thisBtn.text("Translated"),s.thisBtn.attr("disabled","disabled").hide("slow"),e("#cool-auto-translate-btn").text("Translated - SAVE NOW").attr("disabled","disabled"),e("#atlt-dialog .atlt-final-message").html("<strong style='font-size:18px;display:inline-block;margin:5px auto;'>Translation Complete!</strong><br/>(Close this popup & Click <strong>Save</strong>)"+T),void e("#atlt-dialog .atlt-ok.button").show()}e("#cool-auto-translate-btn").text("Translated");for(var m=0;m<=h.length;m++){var x=h[m];jQuery("#po-list-tbody div[for='po-list-col-source'] div").filter(function(t){return jQuery(this).text()==x}).addClass("po-unsaved")}if(0==t.locoEditorStats.dataObj.textToTranslateArr.length)return s.thisBtn.text("Translated"),e("#atlt_preloader").hide(),s.thisBtn.attr("disabled","disabled").hide("slow"),e("#cool-auto-translate-btn").text("Translated - SAVE NOW").attr("disabled","disabled"),e("#atlt-dialog .atlt-final-message").html("<strong style='font-size:18px;display:inline-block;margin:5px auto;'>Translation Complete!</strong><br/>(Close this popup & Click <strong>Save</strong>)."+T),void e("#atlt-dialog .atlt-ok.button").show();jQuery(document).trigger("atlt_translated")})}(m)}}),_()}(window,jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Script for PO file editor pages
3
+ */
4
+ !function( window, $ ){
5
+ var TotalCharacters=0;
6
+ var HtmlStrings = 0;
7
+ var requestChars=0;
8
+ // ES6 Modules or TypeScript
9
+ let event = document.createEvent('event');
10
+ event.initEvent('atlt_run_translation');
11
+ createSettingsPopup();
12
+
13
+ $('#atlt-dialog .atlt-ok.button').on('click',function(){
14
+ // hide dialog container by finding main parent DOM
15
+ localStorage.removeItem('unSavedString');
16
+ $("#atlt-dialog").parent('.ui-dialog').hide();
17
+ });
18
+
19
+ var loco = window.locoScope,
20
+ conf = window.locoConf,
21
+ syncParams = null,
22
+ saveParams = null,
23
+ // UI translation
24
+ translator = loco.l10n,
25
+ sprintf = loco.string.sprintf,
26
+ // PO file data
27
+ locale = conf.locale,
28
+ messages = loco.po.init( locale ).wrap( conf.powrap ),
29
+ template = ! locale,
30
+ // form containing action buttons
31
+ elForm = document.getElementById('loco-actions'),
32
+ filePath = conf.popath,
33
+ syncPath = conf.potpath,
34
+
35
+ // file system connect when file is locked
36
+ elFilesys = document.getElementById('loco-fs'),
37
+ fsConnect = elFilesys && loco.fs.init( elFilesys ),
38
+
39
+ // prevent all write operations if readonly mode
40
+ readonly = conf.readonly,
41
+ editable = ! readonly,
42
+ // Editor components
43
+ editor,
44
+ saveButton,
45
+ innerDiv = document.getElementById('loco-editor-inner');
46
+
47
+ /**
48
+ *
49
+ */
50
+ function doSyncAction( callback ){
51
+ function onSuccess( result ){
52
+ var info = [],
53
+ doc = messages,
54
+ exp = result.po,
55
+ src = result.pot,
56
+ pot = loco.po.init().load( exp ),
57
+ done = doc.merge( pot ),
58
+ nadd = done.add.length,
59
+ ndel = done.del.length,
60
+ t = translator;
61
+ // reload even if unchanged, cos indexes could be off
62
+ editor.load( doc );
63
+ // Show summary
64
+ if( nadd || ndel ){
65
+ if( src ){
66
+ // Translators: Where %s is the name of the POT template file. Message appears after sync
67
+ info.push( sprintf( t._('Merged from %s'), src ) );
68
+ }
69
+ else {
70
+ // Translators: Message appears after sync operation
71
+ info.push( t._('Merged from source code') );
72
+ }
73
+ // Translators: Summary of new strings after running in-editor Sync
74
+ nadd && info.push( sprintf( t._n('1 new string added','%s new strings added', nadd ), nadd ) );
75
+ // Translators: Summary of existing strings that no longer exist after running in-editor Sync
76
+ ndel && info.push( sprintf( t._n('1 obsolete string removed','%s obsolete strings removed', ndel ), ndel ) );
77
+ // editor thinks it's saved, but we want the UI to appear otherwise
78
+ $(innerDiv).trigger('poUnsaved',[]);
79
+ updateStatus();
80
+ // debug info in lieu of proper merge confirmation:
81
+ window.console && debugMerge( console, done );
82
+ }
83
+ else if( src ){
84
+ // Translators: Message appears after sync operation when nothing has changed. %s refers to a POT file.
85
+ info.push( sprintf( t._('Already up to date with %s'), src ) );
86
+ }
87
+ else {
88
+ // Translators: Message appears after sync operation when nothing has changed
89
+ info.push( t._('Already up to date with source code') );
90
+ }
91
+ loco.notices.success( info.join('. ') );
92
+ $(innerDiv).trigger('poMerge',[result]);
93
+ // done sync
94
+ callback && callback();
95
+ }
96
+ loco.ajax.post( 'sync', syncParams, onSuccess, callback );
97
+ }
98
+
99
+ function debugMerge( console, result ){
100
+ var i = -1, t = result.add.length;
101
+ while( ++i < t ){
102
+ console.log(' + '+result.add[i].source() );
103
+ }
104
+ i = -1, t = result.del.length;
105
+ while( ++i < t ){
106
+ console.log(' - '+result.del[i].source() );
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Post full editor contents to "posave" endpoint
112
+ */
113
+ function doSaveAction( callback ){
114
+ function onSuccess( result ){
115
+ callback && callback();
116
+ editor.save( true );
117
+ // Update saved time update
118
+ $('#loco-po-modified').text( result.datetime||'[datetime error]' );
119
+ }
120
+ saveParams.locale = String( messages.locale() || '' );
121
+ if( fsConnect ){
122
+ fsConnect.applyCreds( saveParams );
123
+ }
124
+ // adding PO source last for easier debugging in network inspector
125
+ saveParams.data = String( messages );
126
+ loco.ajax.post( 'save', saveParams, onSuccess, callback );
127
+ }
128
+ function saveIfDirty(){
129
+ editor.dirty && doSaveAction();
130
+ }
131
+ function onUnloadWarning(){
132
+ // Translators: Warning appears when user tries to refresh or navigate away when editor work is unsaved
133
+ return translator._("Your changes will be lost if you continue without saving");
134
+ }
135
+
136
+ function registerSaveButton( button ){
137
+ saveButton = button;
138
+ // enables and disable according to save/unsave events
139
+ editor
140
+ .on('poUnsaved', function(){
141
+ enable();
142
+ $(button).addClass( 'button-primary loco-flagged' );
143
+ } )
144
+ .on('poSave', function(){
145
+ disable();
146
+ $(button).removeClass( 'button-primary loco-flagged' );
147
+ } )
148
+ ;
149
+ function disable(){
150
+ button.disabled = true;
151
+ }
152
+ function enable(){
153
+ button.disabled = false;
154
+ }
155
+ function think(){
156
+ disable();
157
+ $(button).addClass('loco-loading');
158
+ }
159
+ function unthink(){
160
+ enable();
161
+ $(button).removeClass('loco-loading');
162
+ }
163
+ saveParams = $.extend( { path: filePath }, conf.project||{} );
164
+
165
+ $(button).click( function(event){
166
+ event.preventDefault();
167
+ think();
168
+ doSaveAction( unthink );
169
+ setTimeout(function() {
170
+ location.reload();
171
+ },1500);
172
+ return false;
173
+ } );
174
+ return true;
175
+ };
176
+
177
+ function registerSyncButton( button ){
178
+ var project = conf.project;
179
+ if( project ){
180
+ function disable(){
181
+ button.disabled = true;
182
+ }
183
+ function enable(){
184
+ button.disabled = false;
185
+ }
186
+ function think(){
187
+ disable();
188
+ $(button).addClass('loco-loading');
189
+ }
190
+ function unthink(){
191
+ enable();
192
+ $(button).removeClass('loco-loading');
193
+ }
194
+ // Only permit sync when document is saved
195
+ editor
196
+ .on('poUnsaved', function(){
197
+ disable();
198
+ } )
199
+ .on('poSave', function(){
200
+ enable();
201
+ } )
202
+ ;
203
+ // params for sync end point
204
+ syncParams = {
205
+ bundle: project.bundle,
206
+ domain: project.domain,
207
+ type: template ? 'pot' : 'po',
208
+ sync: syncPath||''
209
+ };
210
+ // enable syncing on button click
211
+ $(button)
212
+ .click( function(event){
213
+ event.preventDefault();
214
+ think();
215
+ doSyncAction( unthink );
216
+ return false;
217
+ } )
218
+ //.attr('title', syncPath ? sprintf( translator._('Update from %s'), syncPath ) : translator._('Update from source code') )
219
+ ;
220
+ enable();
221
+ }
222
+ return true;
223
+ }
224
+
225
+ function registerFuzzyButton( button ){
226
+ var toggled = false,
227
+ enabled = false
228
+ ;
229
+ function redraw( message, state ){
230
+ // fuzziness only makes sense when top-level string is translated
231
+ var allowed = message && message.translated(0) || false;
232
+ if( enabled !== allowed ){
233
+ button.disabled = ! allowed;
234
+ enabled = allowed;
235
+ }
236
+ // toggle on/off according to new fuzziness
237
+ if( state !== toggled ){
238
+ $(button)[ state ? 'addClass' : 'removeClass' ]('inverted');
239
+ toggled = state;
240
+ }
241
+ }
242
+ // state changes depending on whether an asset is selected and is fuzzy
243
+ editor
244
+ .on('poSelected', function( event, message ){
245
+ redraw( message, message && message.fuzzy() || false );
246
+ } )
247
+ .on( 'poEmpty', function( event, blank, message, pluralIndex ){
248
+ if( 0 === pluralIndex && blank === enabled ){
249
+ redraw( message, toggled );
250
+ }
251
+ } )
252
+ .on( 'poFuzzy', function( event, message, newState ){
253
+ redraw( message, newState );
254
+ } )
255
+ ;
256
+ // click toggles current state
257
+ $(button).click( function( event ){
258
+ event.preventDefault();
259
+ editor.fuzzy( ! editor.fuzzy() );
260
+ return false;
261
+ } );
262
+ return true;
263
+ };
264
+
265
+ function registerRevertButton( button ){
266
+ // No need for revert when document is saved
267
+ editor
268
+ .on('poUnsaved', function(){
269
+ button.disabled = false;
270
+ } )
271
+ .on('poSave', function(){
272
+ button.disabled = true;
273
+ } )
274
+ ;
275
+ // handling unsaved state prompt with onbeforeunload, see below
276
+ $(button).click( function( event ){
277
+ event.preventDefault();
278
+ location.reload();
279
+ return false;
280
+ } );
281
+ return true;
282
+ };
283
+
284
+ function registerInvisiblesButton( button ){
285
+ var $button = $(button);
286
+ button.disabled = false;
287
+ editor.on('poInvs', function( event, state ){
288
+ $button[ state ? 'addClass' : 'removeClass' ]('inverted');
289
+ });
290
+ $button.click( function( event ){
291
+ event.preventDefault();
292
+ editor.setInvs( ! editor.getInvs() );
293
+ return false;
294
+ } );
295
+ locoScope.tooltip.init($button);
296
+ return true;
297
+ }
298
+
299
+ function registerCodeviewButton( button ){
300
+ var $button = $(button);
301
+ button.disabled = false;
302
+ $button.click( function(event){
303
+ event.preventDefault();
304
+ var state = ! editor.getMono();
305
+ editor.setMono( state );
306
+ $button[ state ? 'addClass' : 'removeClass' ]('inverted');
307
+ return false;
308
+ } );
309
+ locoScope.tooltip.init($button);
310
+ return true;
311
+ };
312
+
313
+ function registerAddButton( button ){
314
+ button.disabled = false;
315
+ $(button).click( function( event ){
316
+ event.preventDefault();
317
+ // Need a placeholder guaranteed to be unique for new items
318
+ var i = 1, baseid, msgid, regex = /(\d+)$/;
319
+ msgid = baseid = 'New message';
320
+ while( messages.get( msgid ) ){
321
+ i = regex.exec(msgid) ? Math.max(i,RegExp.$1) : i;
322
+ msgid = baseid+' '+( ++i );
323
+ }
324
+ editor.add( msgid );
325
+ return false;
326
+ } );
327
+ return true;
328
+ };
329
+
330
+ function registerDelButton( button ){
331
+ button.disabled = false;
332
+ $(button).click( function(event){
333
+ event.preventDefault();
334
+ editor.del();
335
+ return false;
336
+ } );
337
+ return true;
338
+ };
339
+
340
+ function registerDownloadButton( button, id ){
341
+ button.disabled = false;
342
+ $(button).click( function( event ){
343
+ var form = button.form,
344
+ path = filePath;
345
+ // swap out path
346
+ if( 'binary' === id ){
347
+ path = path.replace(/\.po$/,'.mo');
348
+ }
349
+ form.path.value = path;
350
+ form.source.value = messages.toString();
351
+ // allow form to submit
352
+ return true;
353
+ } );
354
+ return true;
355
+ }
356
+
357
+
358
+ // event handler that stops dead
359
+ function noop( event ){
360
+ event.preventDefault();
361
+ return false;
362
+ }
363
+
364
+ /*/ dummy function for enabling buttons that do nothing (or do something inherently)
365
+ function registerNoopButton( button ){
366
+ return true;
367
+ }*/
368
+
369
+ /**
370
+ * Update status message above editor.
371
+ * This is dynamic version of PHP Loco_gettext_Metadata::getProgressSummary
372
+ * TODO implement progress bar, not just text.
373
+ */
374
+ function updateStatus(){
375
+ var t = translator,
376
+ stats = editor.stats(),
377
+ total = stats.t,
378
+ fuzzy = stats.f,
379
+ empty = stats.u,
380
+ // Translators: Shows total string count at top of editor
381
+ stext = sprintf( t._n('1 string','%s strings',total ), total.format(0) ),
382
+ extra = [];
383
+ if( locale ){
384
+ // Translators: Shows percentage translated at top of editor
385
+ stext = sprintf( t._('%s%% translated'), stats.p.replace('%','') ) +', '+ stext;
386
+ // Translators: Shows number of fuzzy strings at top of editor
387
+ fuzzy && extra.push( sprintf( t._('%s fuzzy'), fuzzy.format(0) ) );
388
+ // Translators: Shows number of untranslated strings at top of editor
389
+ empty && extra.push( sprintf( t._('%s untranslated'), empty.format(0) ) );
390
+ if( extra.length ){
391
+ stext += ' ('+extra.join(', ')+')';
392
+ }
393
+ }
394
+ $('#loco-po-status').text( stext );
395
+ if( typeof window.locoEditorStats == 'undefined'){
396
+ window.locoEditorStats = {totalWords:stats.t, totalTranslated:stats.p} ;
397
+ }else{
398
+ window.locoEditorStats.totalWords = stats.t;
399
+ window.locoEditorStats.totalTranslated = stats.p;
400
+ }
401
+
402
+ }
403
+
404
+ /**
405
+ * Enable text filtering
406
+ */
407
+ function initSearchFilter( elSearch ){
408
+ editor.searchable( loco.fulltext.init() );
409
+ // prep search text field
410
+ elSearch.disabled = false;
411
+ elSearch.value = '';
412
+ function showValidFilter( numFound ){
413
+ $(elSearch.parentNode)[ numFound || null == numFound ? 'removeClass' : 'addClass' ]('invalid');
414
+ }
415
+ var listener = loco.watchtext( elSearch, function( value ){
416
+ var numFound = editor.filter( value, true );
417
+ showValidFilter( numFound );
418
+ } );
419
+ editor
420
+ .on( 'poFilter', function( event, value, numFound ){
421
+ listener.val( value||'' );
422
+ showValidFilter( numFound );
423
+ } )
424
+ .on( 'poMerge', function( event, result ){
425
+ var value = listener.val();
426
+ value && editor.filter( value );
427
+ } )
428
+ ;
429
+ }
430
+
431
+ // resize function fits editor to screen, accounting for headroom and touching bottom of screen.
432
+ var resize = function(){
433
+ function top( el, ancestor ){
434
+ var y = el.offsetTop||0;
435
+ while( ( el = el.offsetParent ) && el !== ancestor ){
436
+ y += el.offsetTop||0;
437
+ }
438
+ return y;
439
+ }
440
+ var fixHeight,
441
+ minHeight = parseInt($(innerDiv).css('min-height')||0)
442
+ ;
443
+ return function(){
444
+ var padBottom = 20,
445
+ topBanner = top( innerDiv, document.body ),
446
+ winHeight = window.innerHeight,
447
+ setHeight = Math.max( minHeight, winHeight - topBanner - padBottom )
448
+ ;
449
+ if( fixHeight !== setHeight ){
450
+ innerDiv.style.height = String(setHeight)+'px';
451
+ fixHeight = setHeight;
452
+ }
453
+ };
454
+ }();
455
+
456
+ // ensure outer resize is handled before editor's internal resize
457
+ resize();
458
+ $(window).resize( resize );
459
+
460
+ // initialize editor
461
+ innerDiv.innerHTML = '';
462
+ editor = loco.po.ed
463
+ .init( innerDiv )
464
+ .localise( translator )
465
+ ;
466
+ loco.po.kbd
467
+ .init( editor )
468
+ .add( 'save', saveIfDirty )
469
+ .enable('copy','clear','enter','next','prev','fuzzy','save','invis')
470
+ ;
471
+
472
+ // initialize toolbar button actions
473
+ var buttons = {
474
+ // help: registerNoopButton,
475
+ save: editable && registerSaveButton,
476
+ sync: editable && registerSyncButton,
477
+ revert: registerRevertButton,
478
+ // editor mode togglers
479
+ invs: registerInvisiblesButton,
480
+ code: registerCodeviewButton,
481
+ // downloads / post-throughs
482
+ source: registerDownloadButton,
483
+ binary: template ? null : registerDownloadButton
484
+ };
485
+ // POT only
486
+ if( template ){
487
+ buttons.add = editable && registerAddButton;
488
+ buttons.del = editable && registerDelButton;
489
+ }
490
+ // PO only
491
+ else {
492
+ buttons.fuzzy = registerFuzzyButton;
493
+ };
494
+ $('#loco-toolbar').find('button').each( function(i,el){
495
+ var id = el.getAttribute('data-loco'), register = buttons[id];
496
+ register && register(el,id) || $(el).hide();
497
+ } );
498
+
499
+ // disable submit on dummy form
500
+ $(elForm).submit( noop );
501
+
502
+ // enable text filtering
503
+ initSearchFilter( document.getElementById('loco-search') );
504
+
505
+ // editor event behaviours
506
+ editor
507
+ .on('poUnsaved', function(){
508
+ window.onbeforeunload = onUnloadWarning;
509
+ } )
510
+ .on('poSave', function(){
511
+ updateStatus();
512
+ window.onbeforeunload = null;
513
+ } )
514
+ .on( 'poUpdate', updateStatus );
515
+
516
+
517
+ // load raw message data
518
+ messages.load( conf.podata );
519
+
520
+ // ready to render editor
521
+ editor.load( messages );
522
+
523
+ // locale should be cast to full object once set in editor
524
+ if( locale = editor.targetLocale ){
525
+ locale.isRTL() && $(innerDiv).addClass('trg-rtl');
526
+ }
527
+ // enable template mode when no target locale
528
+ else {
529
+ editor.unlock();
530
+ }
531
+
532
+
533
+ /*
534
+ |--------------------------------------------------------------------------
535
+ | Auto Translator Custom Code
536
+ |--------------------------------------------------------------------------
537
+ */
538
+ //encode URL query string
539
+ function createEncodedString(allStringText){
540
+ const queryString=allStringText.map((item)=>{
541
+ return "&text="+ encodeURIComponent(item.source);
542
+ }).join(",");
543
+
544
+ return queryString;
545
+ }
546
+
547
+ function validLicenseKey(licenseKey){
548
+ if(licenseKey!=undefined && licenseKey.length>1){
549
+ let validKey= validate_pattern(licenseKey);
550
+ if(validKey.length>1){
551
+ return licenseKey;
552
+ }
553
+ }else{
554
+ return false;
555
+ }
556
+
557
+ }
558
+ function validate_pattern(str){
559
+ let m;
560
+ const regex = /^([A-Z0-9]{8})-([A-Z0-9]{8})-([A-Z0-9]{8})-([A-Z0-9]{8})$/gm;
561
+ let saveMatch=[];
562
+ while ((m = regex.exec(str)) !== null) {
563
+ // This is necessary to avoid infinite loops with zero-width matches
564
+ if (m.index === regex.lastIndex) {
565
+ regex.lastIndex++;
566
+ }
567
+ // The result can be accessed through the `m`-variable.
568
+ m.forEach((match, groupIndex) => {
569
+ saveMatch.push(match);
570
+ // console.log(`Found match, group ${groupIndex}: ${match}`);
571
+ });
572
+ }
573
+ return saveMatch;
574
+ }
575
+ function getTargetLang(){
576
+ return window.locoConf.locale.lang?window.locoConf.locale.lang:null;
577
+ }
578
+ $(document).ready(function(){
579
+ if( template ){
580
+ return ;
581
+ }
582
+ const locoRawData=conf.podata;
583
+ if(locoRawData!=undefined && locoRawData.length>0 ){
584
+ // called auto traslate button
585
+ addAutoTranslationBtn();
586
+ }
587
+
588
+ $(document).on("click", "#cool-auto-translate-btn", function() {
589
+ $('#atlt-dialog').dialog({width:400,height:450});
590
+ });
591
+ /* $("#atlt-settings-form").submit(function( event ) {
592
+ event.preventDefault();
593
+ let type = $("input[name='translationtype']:checked").val();
594
+ console.log(type);
595
+ }); */
596
+ // main translate handler
597
+
598
+ $("input[name=api_type]").on( "click",function(){
599
+ if($(this).val()=="google"){
600
+ $("#typehtmlWrapper").hide();
601
+ $("#typeplain").attr("checked","checked");
602
+ }else{
603
+ $("#typehtmlWrapper").show();
604
+ }
605
+ });
606
+
607
+ // integrate reset string traslation button
608
+ $("#atlt_reset_all").on("click",function(){
609
+ swal("What type of strings do you want to reset?",
610
+ {
611
+ dangerMode: true,
612
+ icon: "warning",
613
+ confirmButtonColor: '#8CD4F5',
614
+
615
+ buttons: {
616
+ plain: {
617
+ text: "Plain Text Strings",
618
+ value: "plain",
619
+ class:"danger"
620
+ },
621
+ html: {
622
+ text: "HTML Strings",
623
+ value: "html",
624
+ },
625
+ all: {
626
+ text: "All Strings",
627
+ value: "all",
628
+ },
629
+ cancel: {
630
+ text: "Cancel",
631
+ value: null,
632
+ visible: true,
633
+ className: "",
634
+ closeModal: false,
635
+ },
636
+ },
637
+ })
638
+ .then((value) => {
639
+ switch (value) {
640
+ case "all":
641
+ resetTranslations(value);
642
+ swal("Done!", "You have successfully reset all strings translations. Just close this popup & SAVE!","success");;
643
+ break;
644
+ case "plain":
645
+ resetTranslations(value);
646
+ swal("Done!", "You have successfully reset all plain text strings translations. Just close this popup & SAVE!", "success");
647
+ break;
648
+ case "html":
649
+ resetTranslations(value);
650
+ swal("Done!", "You have successfully reset all strings with HTML translations. Just close this popup & SAVE!", "success");
651
+ break;
652
+ default:
653
+ swal("Cancelled, Just close this popup!");
654
+ }
655
+ });
656
+
657
+ });
658
+
659
+ // reset string array
660
+ function resetTransArr(tranArr,type){
661
+ var resetStrs=[];
662
+ return resetStrs=tranArr.map(function(item){
663
+ if(item.source!==undefined && item.target!==undefined ){
664
+ if(type=="html"){
665
+ if((isHTML(item.source)|| isAllowedChars(item.source))){
666
+ item.target="";
667
+ }
668
+ }
669
+ if(type=="plain"){
670
+ if(isHTML(item.source) || isAllowedChars(item.source)){
671
+ }else{
672
+ item.target="";
673
+ }
674
+ }
675
+ if(type=="all"){
676
+ item.target="";
677
+ }
678
+ return item;
679
+ }
680
+ });
681
+ }
682
+
683
+ // integrate reset translation button
684
+ function resetTranslations(type){
685
+ var resetArr=[];
686
+ const saveBtn=$('[data-loco="save"]');
687
+ if(conf.podata!==undefined){
688
+ if(type=="plain"){
689
+ resetArr=resetTransArr(conf.podata,"plain");
690
+ }else if(type=="html"){
691
+ resetArr=resetTransArr(conf.podata,"html");
692
+ }else{
693
+ resetArr=resetTransArr(conf.podata,"all");
694
+ }
695
+ messages = loco.po.init( locale ).wrap( conf.powrap );
696
+ messages.load(resetArr);
697
+ // editor event behaviours
698
+ editor
699
+ .on('poUnsaved', function(){
700
+ window.onbeforeunload = onUnloadWarning;
701
+ } )
702
+ .on('poSave', function(){
703
+ updateStatus();
704
+ window.onbeforeunload = null;
705
+ } )
706
+ .on( 'poUpdate', updateStatus );
707
+
708
+ // ready to render editor
709
+ editor.load(messages);
710
+ saveBtn.addClass( 'button-primary loco-flagged' ).removeAttr("disabled");
711
+ updateStatus();
712
+ }
713
+ }
714
+ // handle form settings
715
+ $("#atlt-settings-form").submit(function( event ) {
716
+ event.preventDefault();
717
+ const user_type=ATLT["info"].type;
718
+ let strType = $("input[name='translationtype']:checked").val();
719
+ let apiType = $("input[name='api_type']:checked").val();
720
+ let mainBtn=$("#cool-auto-translate-btn");
721
+ var thisBtn=$("#cool-auto-translate-start");
722
+ let sourceApiKey ='';
723
+ var todayLimit= mainBtn.data('today-limit');
724
+ var totalLimit= mainBtn.data('total-limit');
725
+ let targetLang='';
726
+ if(user_type=="free" && strType=="html"){
727
+ alert("HTML Translation Only Available in the PRO version");
728
+ return false;
729
+ }
730
+ if(user_type=="free" && apiType=="google"){
731
+ alert("Google Translation Only Available in the PRO version");
732
+ return false;
733
+ }
734
+ if((user_type==undefined || user_type=="pro") && ATLT["info"]["licenseKey"]==undefined){
735
+ alert("Please enter Your License Key");
736
+ return false;
737
+ }
738
+
739
+ if(conf['locale']["lang"]=!undefined){
740
+ targetLang=conf['locale']["lang"];
741
+ }else{
742
+ targetLang=getTargetLang();
743
+ }
744
+ if(apiType=="google" && strType=="html"){
745
+ alert("Google Translate Only Support Plain Text Translation");
746
+ return false;
747
+ }
748
+ if(apiType=="google"){
749
+ sourceApiKey = ATLT["api_key"]["gApiKey"];
750
+ }else{
751
+ sourceApiKey = ATLT["api_key"]["yApiKey"];
752
+ }
753
+ // filter transable strings
754
+ if(locoRawData!=undefined && locoRawData.length>0 && sourceApiKey!='' ){
755
+ let plainStrArr=[];
756
+ let htmlStrArr=[];
757
+ let orgStrArr=[];
758
+ orgStrArr=locoRawData;
759
+ var countChars=0;
760
+ if(strType=="plain"){
761
+ plainStrArr= filterRawObject(locoRawData,"plain");
762
+ if (plainStrArr !== null) {
763
+ plainStrArr.map(function(index){
764
+ countChars +=index.source.length;
765
+ });
766
+ }
767
+ }else{
768
+ htmlStrArr= filterRawObject(locoRawData,"html");
769
+ if (htmlStrArr !== null) {
770
+ plainStrArr.map(function(index){
771
+ countChars +=index.length;
772
+ });
773
+ }
774
+ }
775
+
776
+ if (htmlStrArr !== null || plainStrArr !== null ) {
777
+ if(countChars>parseInt(todayLimit)){
778
+ alert('Your translation string are larger then available free limit.In order to extend limit Buy Pro license key');
779
+ }else{
780
+
781
+ if(strType=="plain"){
782
+ if(plainStrArr.length==0){
783
+ $("#atlt-dialog").parent('.ui-dialog').hide();
784
+ mainBtn.attr('disabled','disabled');
785
+ alert("You have no untransalted plain strings");
786
+ window.location.reload();
787
+ return;
788
+ }
789
+ dataObj = {
790
+ textToTranslateArr:plainStrArr,
791
+ strType:"plain",
792
+ };
793
+ }else{
794
+ if(htmlStrArr.length==0){
795
+ $("#atlt-dialog").parent('.ui-dialog').hide();
796
+ mainBtn.attr('disabled','disabled');
797
+ alert("You have no untransalted HTML strings");
798
+ window.location.reload();
799
+ return;
800
+ }
801
+ dataObj = {
802
+ textToTranslateArr:htmlStrArr,
803
+ strType:"html",
804
+ };
805
+ }
806
+ // create data object for later use
807
+ dataObj.orgStrArr=orgStrArr;
808
+ dataObj.thisBtn=thisBtn;
809
+ dataObj.apiType=apiType;
810
+ dataObj.targetLang=targetLang;
811
+ // save data object globaly for later use
812
+ window.locoEditorStats.dataObj = dataObj;
813
+ jQuery(document).trigger('atlt_run_translation');
814
+ thisBtn.val('Translating...');
815
+ mainBtn.text("Translating..");
816
+ $("#atlt_preloader").show();
817
+ // load raw message data
818
+
819
+ } //
820
+
821
+ } // else close
822
+ }
823
+
824
+ });
825
+
826
+ });
827
+ // create translation events
828
+ jQuery(document).on('atlt_run_translation',function(){
829
+ let textToTranslate = window.locoEditorStats.dataObj.textToTranslateArr
830
+ let totalTranslated = window.locoEditorStats.totalTranslated
831
+ const apiKey = ATLT["api_key"]["yApiKey"];
832
+ const nonce=ATLT["nonce"];
833
+ const saveBtn=$('[data-loco="save"]');
834
+ const orignalstringArr=window.locoEditorStats.dataObj.orgStrArr;
835
+ const targetLang= window.locoEditorStats.dataObj.targetLang;
836
+ let indexRequest = 50;
837
+ if( ATLT.api_key['atlt_index-per-request'] != "" && typeof ATLT.api_key['atlt_index-per-request'] != "undefined" ){
838
+ indexRequest = ATLT.api_key['atlt_index-per-request'];
839
+ }
840
+
841
+ //save pending array in window object for later use
842
+ if( typeof textToTranslate == "object" && textToTranslate.length >= 1 ){
843
+ // update object for later us
844
+ let translationO = {
845
+ textToTranslateArr:textToTranslate.slice(indexRequest), //save pending index for later us
846
+ thisBtn:window.locoEditorStats.dataObj.thisBtn,
847
+ strType:window.locoEditorStats.dataObj.strType,
848
+ orgStrArr:window.locoEditorStats.dataObj.orgStrArr,
849
+ apiType:window.locoEditorStats.dataObj.apiType,
850
+ targetLang:targetLang,
851
+ };
852
+ window.locoEditorStats.dataObj = translationO;
853
+
854
+ // send partial data request
855
+ let data = {
856
+ sourceLang:'en',
857
+ targetLang:targetLang,
858
+ textToTranslateArr:textToTranslate.slice(0,indexRequest),
859
+ orginalArr:orignalstringArr,
860
+ apiKey:apiKey,
861
+ thisBtn:window.locoEditorStats.dataObj.thisBtn,
862
+ strType:window.locoEditorStats.dataObj.strType,
863
+ apiType:window.locoEditorStats.dataObj.apiType,
864
+ saveBtn:saveBtn,
865
+ nonce:nonce
866
+ };
867
+ // slice data
868
+ textToTranslate.slice(0,indexRequest).map(function(value,index){
869
+ TotalCharacters += (value.source).length;
870
+ requestChars+=(value.source).length;
871
+ })
872
+ atlt_translate(data);
873
+ }
874
+ })
875
+
876
+ // Translate
877
+ function atlt_translate(data) {
878
+
879
+ atlt_ajax_translation_request(data, "POST").success(function(
880
+ resp,status,xhr) {
881
+ if(xhr.status==200){
882
+
883
+ const json_resp = JSON.parse(resp);
884
+ if( json_resp === false && JSON.parse(resp)!=undefined){
885
+ data.thisBtn.hide('slow');
886
+ $("#atlt_preloader").hide();
887
+ $("#cool-auto-translate-btn").text('Translation').attr('disabled','disabled');
888
+ $('#atlt-dialog .atlt-ok.button').show();
889
+
890
+ alert('Unable to make request to the server at the moment. Try again later.');
891
+ }else if(json_resp['code']==500){
892
+ alert('Unable to make request to the server at the moment. Try again later.');
893
+ window.location.reload();
894
+ return;
895
+ }
896
+ else if( typeof json_resp['code'] === undefined ||
897
+ json_resp['code'] != 200 ){
898
+ let error = '';
899
+ switch(json_resp['code']){
900
+ case 401:
901
+ error = 'Yandex API Key is invalid!';
902
+ break;
903
+ case 402:
904
+ error = 'Provided Yandex API Key has been blocked!';
905
+ break;
906
+ case 404:
907
+ error = 'Exceeded the daily limit for Yandex API on the amount of translated text.';
908
+ break;
909
+ case 422:
910
+ error = 'The text cannot be translated by Yandex API.';
911
+ break;
912
+ case 501:
913
+ error = 'Yandex API does not support the specified translation direction.';
914
+ break;
915
+ default:
916
+ error = json_resp['message'];
917
+ }
918
+ if( error != '' && (data.textToTranslateArr).length != 0 ){
919
+ $('#atlt-dialog .atlt-final-message').html("<strong>"+error+"</strong>");
920
+ $('#atlt-dialog .atlt-ok.button').show();
921
+ $("#atlt_preloader").hide();
922
+ $("#cool-auto-translate-btn").text('Error').attr('disabled','disabled');
923
+ //data.thisBtn.attr('disabled','disabled');
924
+ }
925
+ return;
926
+ }
927
+
928
+ let totalTranslated = window.locoEditorStats.totalTranslated;
929
+
930
+ var response = json_resp['translatedString'];
931
+ let unSavedStr=[];
932
+ if(response!==undefined){
933
+ for(i=0;i< response.length;i++){
934
+ var text = response[i];
935
+ if( data.textToTranslateArr[i] === undefined ){
936
+ break;
937
+ }
938
+ data.textToTranslateArr[i].target = text ;
939
+ }
940
+ }
941
+
942
+ let translatedStrArr=data['textToTranslateArr'];
943
+ // var mergeTranslatedText = atlt_arrayUnique(translatedStrArr.concat(data['orginalArr']) );
944
+
945
+ let Emptytargets = [];
946
+ for(var x=0; x<translatedStrArr.length;++x){
947
+ if(translatedStrArr[x].target !='' ){
948
+ Emptytargets[x]=translatedStrArr[x].source;
949
+ }
950
+ }
951
+
952
+ let items;
953
+ if (localStorage.getItem('unSavedString')) {
954
+ items = JSON.parse(localStorage.getItem('unSavedString'))
955
+ } else {
956
+ items = []
957
+ }
958
+ var unSavedStrArr = items.concat(Emptytargets);
959
+ localStorage.setItem('unSavedString', JSON.stringify(unSavedStrArr));
960
+
961
+
962
+ messages = loco.po.init( locale ).wrap( conf.powrap );
963
+ // ready to render editor
964
+ messages.load(data['orginalArr']);
965
+
966
+ // editor event behaviours
967
+ editor
968
+ .on('poUnsaved', function(){
969
+ window.onbeforeunload = onUnloadWarning;
970
+ } )
971
+ .on('poSave', function(){
972
+ updateStatus();
973
+ window.onbeforeunload = null;
974
+ } )
975
+ .on( 'poUpdate', updateStatus );
976
+
977
+ // ready to render editor
978
+ editor.load(messages);
979
+ data.saveBtn.addClass( 'button-primary loco-flagged' ).removeAttr("disabled");
980
+ updateStatus();
981
+ // run through DOM and mark *(STAR) for newly translated
982
+ markUnsavedString();
983
+
984
+ requestChars=0;
985
+ // update progress bar
986
+ $('#atlt-dialog .translated-label').text('Translated');
987
+ $('#atlt-dialog .translated-text').text(window.locoEditorStats.totalTranslated);
988
+
989
+ $('#atlt-dialog .atlt-progress-bar-value').width(window.locoEditorStats.totalTranslated);
990
+ if(json_resp!=undefined){
991
+ if(json_resp['stats']['time_saved']!=undefined){
992
+ var saved_time_msg = '<br/><br/><span style="border: 3px solid #14b75d;display: inline-block;padding: 3px;">Wahooo! You have saved your <strong>'+json_resp['stats']['time_saved']+'</strong> via auto translating '+parseInt(json_resp['stats']['totalChars'])+ ' characters using <strong><a href="https://wordpress.org/support/plugin/automatic-translator-addon-for-loco-translate/reviews/#new-post" target="_new">Loco Automatic Translate Addon</a></strong>.</span><br/><br/>';
993
+ }
994
+ }
995
+ switch( window.locoEditorStats.totalTranslated ){
996
+ case "0%":
997
+ $('#atlt-dialog .translated-label').text('Translating...');
998
+ $('#atlt-dialog .translated-text').text('');
999
+ break;
1000
+ case "100%":
1001
+ data.thisBtn.hide();
1002
+ $("#atlt_preloader").hide();
1003
+ data.thisBtn.attr('disabled','disabled');
1004
+ $("#cool-auto-translate-btn").text('Translated - SAVE NOW').attr('disabled','disabled');
1005
+ // change cursor to 'default' state
1006
+ $('#atlt-dialog .atlt-final-message').html("<strong style='font-size:18px;display:inline-block;margin:5px auto;'>Translation Complete!</strong><br/>(Close this popup & Click <strong>Save</strong>)"+saved_time_msg);
1007
+ $('#atlt-dialog .atlt-ok.button').show();
1008
+ return;
1009
+ break;
1010
+ }
1011
+
1012
+ // run through DOM and mark *(STAR) for newly translated
1013
+ for(var x=0;x<=Emptytargets.length;x++){
1014
+ var source = Emptytargets[x];
1015
+ jQuery("#po-list-tbody div[for='po-list-col-source'] div").filter(function(index){
1016
+ return jQuery(this).text() == source
1017
+ }).addClass('po-unsaved');
1018
+ }
1019
+
1020
+ if( (window.locoEditorStats.dataObj.textToTranslateArr).length == 0){
1021
+ data.thisBtn.val('Translated').attr("disabled","true");
1022
+ $("#atlt_preloader").hide();
1023
+ // data.thisBtn.attr('disabled','disabled').hide('slow');
1024
+ $("#cool-auto-translate-btn").text('Translated - SAVE NOW').attr('disabled','disabled');
1025
+ // change cursor to 'default' state
1026
+ $('#atlt-dialog .atlt-final-message').html("<strong style='font-size:18px;display:inline-block;margin:5px auto;'>Translation Complete!</strong><br/>(Close this popup & Click <strong>Save</strong>)."+saved_time_msg);
1027
+ $('#atlt-dialog .atlt-ok.button').show();
1028
+ return;
1029
+ }
1030
+
1031
+ jQuery(document).trigger('atlt_run_translation');
1032
+
1033
+ }else{
1034
+ data.thisBtn.hide('slow');
1035
+ $("#atlt_preloader").hide();
1036
+ $("#cool-auto-translate-btn").text('Translation').attr('disabled','disabled');
1037
+ $('#atlt-dialog .atlt-ok.button').show();
1038
+ alert('Unable to make request to the server at the moment. Try again later.');
1039
+ }
1040
+ }).fail(function(jqXHR){
1041
+ if(jqXHR.status==500 || jqXHR.status==0){
1042
+ // internal server error or internet connection broke
1043
+ data.thisBtn.hide('slow');
1044
+ $("#atlt_preloader").hide();
1045
+ $("#cool-auto-translate-btn").text('Translation').attr('disabled','disabled');
1046
+ $('#atlt-dialog .atlt-ok.button').show();
1047
+ alert('Unable to make request to the server at the moment. Try again later.');
1048
+ }
1049
+ });
1050
+ }
1051
+ // filter all saved strings
1052
+ function filterSavedStrings(rawArray){
1053
+ return filterdArr=rawArray.filter((item,index)=>{
1054
+ if(item.target!="" &&(item.source!==undefined && item.source!="")){
1055
+ return true;
1056
+ }
1057
+ });
1058
+ }
1059
+
1060
+ // filter string based upon type
1061
+ function filterRawObject(rawArray,filterType){
1062
+ filterdArr=[];
1063
+ return filterdArr=rawArray.filter((item,index)=>{
1064
+ if( (item.target===undefined || item.target=="" && item.source!="" && item.source!==undefined)){
1065
+ if( ValidURL(item.source)){
1066
+ return false;
1067
+ }
1068
+ if(filterType=="html"){
1069
+ if(isContainChars(item.source)){
1070
+ return false;
1071
+ } else if(isHTML(item.source)){
1072
+ return true;
1073
+ }else if(isAllowedChars(item.source)){
1074
+ return true;
1075
+ }else{
1076
+ return false;
1077
+ }
1078
+ }else{
1079
+ if(isHTML(item.source)){
1080
+ return false;
1081
+ }else if(isSpecialChars(item.source)){
1082
+ return false;
1083
+ }else if( item.source.includes('#') ) {
1084
+ return false;
1085
+ }else{
1086
+ return true;
1087
+ }
1088
+ }
1089
+ }
1090
+ });
1091
+ }
1092
+
1093
+ // find unique index in array
1094
+ function atlt_arrayUnique(array) {
1095
+ var a = array.concat();
1096
+ for(var i=0; i<a.length; ++i) {
1097
+ for(var j=i+1; j<a.length; ++j) {
1098
+ if(a[i] === a[j])
1099
+ a.splice(j--, 1);
1100
+ }
1101
+ }
1102
+ return a;
1103
+ }
1104
+
1105
+
1106
+ // auto traslator button in editor
1107
+ function addAutoTranslationBtn(){
1108
+ if($("#loco-toolbar").find("#cool-auto-translate-btn").length>0){
1109
+ $("#loco-toolbar").find("#cool-auto-translate-btn").remove();
1110
+ }
1111
+ const locoActions= $("#loco-toolbar").find("#loco-actions");
1112
+ const otherBtn='<button class="button has-icon icon-warn" id="atlt_reset_all">Reset Translations</button></fieldset>';
1113
+ const allTranslated='<fieldset><button id="cool-auto-translate-btn" class="button has-icon icon-translate" disabled>Translated</button></fieldset>';
1114
+ let savedStrings=filterSavedStrings(conf.podata);
1115
+
1116
+ let plainStrings= filterRawObject(conf.podata,"plain");
1117
+ let htmlStrings = filterRawObject(conf.podata,"html");
1118
+ const userType=ATLT["info"].type;
1119
+ if((Array.isArray(plainStrings) && plainStrings.length) ||
1120
+ (Array.isArray(htmlStrings)&& htmlStrings.length)
1121
+ ){
1122
+ const inActiveBtn='<fieldset><button title="Add API key to enable this feature." id="cool-auto-translate-btn" disabled class="button has-icon icon-translate">Auto Translate</button> <a style="font-size:9px;display:block;margin-left:8px;" target="_blank" href="https://tech.yandex.com/translate/">Get Free API Key</a></fieldset>';
1123
+ const disabledBtn='<fieldset><button title="Buy PRO." id="cool-auto-translate-btn" disabled class="button has-icon icon-translate">Auto Translate</button><div style="max-width:320px; display:inline-block;margin-top: 4px;"><span style="font-size:12px;display:inline-block;margin-left:8px;">You have exceeded free translation limit. In order to extend the limit - <a target="_blank" style="font-size:14px;display:inline-block;margin-left:8px;" target="_blank" href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/#pricing">Buy Premium License</a></span></div></fieldset>';
1124
+ const apiKey=ATLT["api_key"]["yApiKey"];
1125
+ const proActiveBtn='<fieldset><button id="cool-auto-translate-btn" class="button has-icon icon-translate">Auto Translate</button></fieldset>';
1126
+ const allowed=ATLT["info"].allowed;
1127
+ const today=ATLT["info"].today;
1128
+ const total=ATLT["info"].total;
1129
+ const aTodayChars=300000;
1130
+ const aTodayChar=1000000;
1131
+
1132
+ // not added API key
1133
+ if( ATLT == '' || ATLT["api_key"] == '' || apiKey=='' ){
1134
+ if( userType=='free'){
1135
+ locoActions.append(inActiveBtn);
1136
+ return;
1137
+ }else{
1138
+ locoActions.append(proActiveBtn);
1139
+ }
1140
+ }else if( allowed=="no" && userType=='free'){
1141
+ // free not allowed
1142
+ locoActions.append(disabledBtn);
1143
+ return;
1144
+ }else if(today!==undefined && parseInt(today)>aTodayChars
1145
+ && userType=='free'){
1146
+ // today free limit exceeded
1147
+ locoActions.append(disabledBtn);
1148
+ return;
1149
+ }else if(total!==undefined && parseInt(total)>aTodayChar
1150
+ && userType=='free'){
1151
+ // monthly limit exceeded
1152
+ locoActions.append(disabledBtn);
1153
+ return;
1154
+ }else if( window.locoEditorStats.totalTranslated != "100%"
1155
+ && window.locoEditorStats.totalWords > 0 ){
1156
+ //Pro user and added key then show button
1157
+ if(userType=='pro' && ATLT["info"]["licenseKey"]!=undefined && validLicenseKey(ATLT["info"]["licenseKey"])){
1158
+ locoActions.append(proActiveBtn);
1159
+ }else{
1160
+ //if user is free and allowed the show button
1161
+ if(today==undefined){
1162
+ var todayChars=aTodayChars;
1163
+ }else{
1164
+ var todayChars=aTodayChars-parseInt(today);
1165
+ }
1166
+ var totalChars=aTodayChar-parseInt(total);
1167
+ // append button for free
1168
+ var freeBtn='<fieldset><button data-today-limit="'+todayChars+'" data-total-limit="'+totalChars+'" id="cool-auto-translate-btn" class="button has-icon icon-translate">Auto Translate</button></fieldset>';
1169
+ locoActions.append(freeBtn);
1170
+ }
1171
+ } else if( window.locoEditorStats.totalWords == 0){
1172
+ return;
1173
+ }
1174
+ } else{
1175
+ locoActions.append(allTranslated);
1176
+ }
1177
+
1178
+ if((Array.isArray(savedStrings) && savedStrings.length)){
1179
+ if(userType=='pro' && ATLT["info"]["licenseKey"]!=undefined && validLicenseKey(ATLT["info"]["licenseKey"])){
1180
+ locoActions.append(otherBtn);
1181
+ }
1182
+ }
1183
+
1184
+ }
1185
+
1186
+
1187
+ // mark unsaved after ajax translation process
1188
+ function markUnsavedString(){
1189
+ const unSavedString = JSON.parse(localStorage.getItem('unSavedString'));
1190
+
1191
+ for(var x=0;x<=unSavedString.length;x++){
1192
+ var source = unSavedString[x];
1193
+ jQuery("#po-list-tbody div[for='po-list-col-source'] div").filter(function(index){
1194
+ return jQuery(this).text() == source
1195
+ }).addClass('po-unsaved');
1196
+ }
1197
+ }
1198
+
1199
+ // detect String contain URL
1200
+ function ValidURL(str) {
1201
+ var pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
1202
+ if(!pattern.test(str)) {
1203
+ return false;
1204
+ } else {
1205
+ return true;
1206
+ }
1207
+ }
1208
+ // detect Valid HTML in string
1209
+ function isHTML(str){
1210
+ var rgex=/<(?=.*? .*?\/ ?>|br|hr|input|!--|wbr)[a-z]+.*?>|<([a-z]+).*?<\/\1>/i;
1211
+ if(str!==undefined){
1212
+ return rgex.test(str);
1213
+ }else {
1214
+ return false;
1215
+ }
1216
+ }
1217
+ // check special chars in string
1218
+ function isSpecialChars(str){
1219
+ var rgex=/[@#^$%&*{}|<>]/g;
1220
+ if(str!==undefined){
1221
+ return rgex.test(str);
1222
+ }else {
1223
+ return false;
1224
+ }
1225
+ }
1226
+ // allowed special chars in HTML string
1227
+ function isAllowedChars(str){
1228
+ var rgex=/[!@#$%^&*(),?":|<>]/g;
1229
+ if(str!==undefined){
1230
+ return rgex.test(str);
1231
+ }else {
1232
+ return false;
1233
+ }
1234
+ }
1235
+ // check string contain curly brackets
1236
+ function isContainChars(str){
1237
+ var rgex=/[{}[]/g;
1238
+ if(str!==undefined){
1239
+ return rgex.test(str);
1240
+ }else {
1241
+ return false;
1242
+ }
1243
+ }
1244
+ // format numbers
1245
+ function atltFormatNumber(num) {
1246
+ return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
1247
+ }
1248
+
1249
+ // create popup model for translation settings
1250
+ function createSettingsPopup(){
1251
+ let preloaderImg=extradata['preloader_path'];
1252
+ const userInfo=ATLT["info"].type;
1253
+ const yAC=ATLT["info"].yAvailableChars;
1254
+ const licenseKey=ATLT["info"]["licenseKey"];
1255
+
1256
+ let yfieldStatus="";
1257
+ let gfieldStatus="";
1258
+ let hfieldStatus="";
1259
+ let htmlSupported="";
1260
+ let contCls="";
1261
+ let proLbl="";
1262
+ let gContCls='';
1263
+ let gHtml='';
1264
+ let submitBtn='';
1265
+ let yHtml='';
1266
+ let yChecked='checked="true"';
1267
+ if(userInfo=="free"){
1268
+ let gAC=0;
1269
+ gfieldStatus="disabled";
1270
+ hfieldStatus="disabled";
1271
+ contCls="html-disabled";
1272
+ gContCls='g-disabled';
1273
+ proLbl='<span class="atlt-pro-feature"><a href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/#pricing" target="_blank" style="color:red;font-weight:bold;" title="Only For Pro Users">PRO Only</a></span>';
1274
+ gHtml=proLbl+' (70% better than Yendex Translate)';
1275
+ }else{
1276
+
1277
+ if( ATLT["info"]["licenseKey"]!=undefined && validLicenseKey(ATLT["info"]["licenseKey"])
1278
+ && ATLT["api_key"]["gApiKey"]!=""){
1279
+ let gAC=ATLT["info"].gAvailableChars;
1280
+ if(gAC!==undefined && gAC>10000){
1281
+ gHtml='<span class="available-chars"> ('+ atltFormatNumber(gAC)+' Available This Month)</span>';
1282
+ }
1283
+ if(gAC<10000){
1284
+ gHtml='<span class="used-chars">You have consumed All Free Characters</span>';
1285
+ }
1286
+ }else{
1287
+ gfieldStatus="disabled";
1288
+ gContCls='g-disabled';
1289
+
1290
+ gHtml='<span class="error">Please Enter Google Translate API key in the Settings Panel</span>';
1291
+ }
1292
+
1293
+ if(ATLT["api_key"]["yApiKey"]!="")
1294
+ {
1295
+ if(yAC!==undefined){
1296
+ yHtml='<span class="available-chars"> ('+atltFormatNumber(yAC)+' Available Today)</span>';
1297
+ }
1298
+ }else{
1299
+ yfieldStatus="disabled";
1300
+ yContCls='g-disabled';
1301
+ yChecked='';
1302
+ yHtml='<span class="error">Please Enter Yandex API key in the Settings Panel</span>';
1303
+ }
1304
+ }
1305
+ if( ATLT["api_key"]["yApiKey"]!="" || ATLT["api_key"]["gApiKey"]!="" )
1306
+ {
1307
+ submitBtn='<input type="submit" class="button has-icon icon-translate" value="Start Translation" id="cool-auto-translate-start">';
1308
+ }else{
1309
+ submitBtn='<button class="atlt-ok button button-primary">OK</button>';
1310
+
1311
+ }
1312
+ let settingsHTML=`<div class="atlt-settings">
1313
+ <form id="atlt-settings-form" method="post" action="#">
1314
+ <strong class="atlt-heading">Select Translation API</strong>
1315
+ <div class="inputGroup">
1316
+ <input class="inputEle" type="radio" id="yandex_api"
1317
+ ${yChecked} ${yfieldStatus} name="api_type" value="yandex">
1318
+ <label for="yandex_api">Yandex ${yHtml}</label>
1319
+ </div>
1320
+ <div class="inputGroup ${gContCls}">
1321
+ <input class="inputEle" type="radio" id="google_api"
1322
+ name="api_type" value="google" ${gfieldStatus}>
1323
+ <label for="google_api">Google</label> ${gHtml}
1324
+ </div>
1325
+ <br/>
1326
+ <strong class="atlt-heading">Select Content Type</strong>
1327
+ <div class="inputGroup">
1328
+ <input class="inputEle" type="radio" id="typeplain" checked="true" name="translationtype" value="plain">
1329
+ <label for="typeplain">Translate Plain Text Strings</label>
1330
+ </div>
1331
+ <div id="typehtmlWrapper" class="inputGroup ${contCls}">
1332
+ <input class="inputEle" type="radio" id="typehtml" name="translationtype" value="html" ${hfieldStatus}>
1333
+ <label for="typehtml">Translate HTML Strings (Beta) ${proLbl}
1334
+ </label>
1335
+ </br>
1336
+ <small style="display:inline-block;margin-left:24px;margin-top:8px;">(<a href="https://locotranslate.com/html-translation-languages-list/" target="_blank">List of languages with HTML support</a>)</small>
1337
+ </div>
1338
+
1339
+ <br/>
1340
+ <fieldset>
1341
+ ${submitBtn}
1342
+ <img style="display:none;margin-left:10px;margin-top:-3px;" id="atlt_preloader" src="${preloaderImg}">
1343
+ </fieldset>
1344
+ </form>
1345
+ </div>`;
1346
+ // custom popup message box
1347
+ let popup_html = `<div id="atlt-dialog-container">
1348
+ <div style="display:none;" id="atlt-dialog" title="Automatic Translation Progress">
1349
+ ${settingsHTML}
1350
+ <p><span class="translated-label">Translated</span>
1351
+ <span class="translated-text">0%</span></p>
1352
+ <div class="atlt-progress-bar-track">
1353
+ <div class="atlt-progress-bar-value">
1354
+ </div></div>
1355
+ <div class="atlt-final-message"></div>
1356
+ <button style="display:none;" class="atlt-ok button button-primary">OK</button>
1357
+ </div></div>`;
1358
+ $("body").append( popup_html );
1359
+ }
1360
+
1361
+ // send ajax request
1362
+ function atlt_ajax_translation_request(data,type){
1363
+ let filteredArr=[];
1364
+ filteredArr=data.textToTranslateArr.map((item)=>{
1365
+ if( typeof item.source!= 'undefined'){
1366
+ return item.source;
1367
+ } });
1368
+ const jsonData=JSON.stringify(filteredArr);
1369
+
1370
+ return jQuery.ajax({
1371
+ url: ajaxurl,
1372
+ type:'POST',
1373
+ data: {'action':'atlt_translation',
1374
+ 'sourceLan':data.sourceLang,
1375
+ 'targetLan':data.targetLang,
1376
+ 'totalCharacters': TotalCharacters,
1377
+ 'requestChars':requestChars,
1378
+ 'nonce':data.nonce,
1379
+ 'strType':data.strType,
1380
+ 'apiType':data.apiType,
1381
+ 'data':jsonData
1382
+ },
1383
+ done:function(res){
1384
+ // console.log(res)
1385
+ }
1386
+
1387
+
1388
+ });
1389
+ }
1390
+
1391
+ // ok, editor ready
1392
+ updateStatus();
1393
+
1394
+ // clean up
1395
+ //delete window.locoConf;
1396
+ //conf = buttons = null;
1397
+
1398
+ }( window, jQuery );
assets/sweetalert/sweetalert.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.swal=e():t.swal=e()}(this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,o){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=8)}([function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o="swal-button";e.CLASS_NAMES={MODAL:"swal-modal",OVERLAY:"swal-overlay",SHOW_MODAL:"swal-overlay--show-modal",MODAL_TITLE:"swal-title",MODAL_TEXT:"swal-text",ICON:"swal-icon",ICON_CUSTOM:"swal-icon--custom",CONTENT:"swal-content",FOOTER:"swal-footer",BUTTON_CONTAINER:"swal-button-container",BUTTON:o,CONFIRM_BUTTON:o+"--confirm",CANCEL_BUTTON:o+"--cancel",DANGER_BUTTON:o+"--danger",BUTTON_LOADING:o+"--loading",BUTTON_LOADER:o+"__loader"},e.default=e.CLASS_NAMES},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getNode=function(t){var e="."+t;return document.querySelector(e)},e.stringToNode=function(t){var e=document.createElement("div");return e.innerHTML=t.trim(),e.firstChild},e.insertAfter=function(t,e){var n=e.nextSibling;e.parentNode.insertBefore(t,n)},e.removeNode=function(t){t.parentElement.removeChild(t)},e.throwErr=function(t){throw t=t.replace(/ +(?= )/g,""),"SweetAlert: "+(t=t.trim())},e.isPlainObject=function(t){if("[object Object]"!==Object.prototype.toString.call(t))return!1;var e=Object.getPrototypeOf(t);return null===e||e===Object.prototype},e.ordinalSuffixOf=function(t){var e=t%10,n=t%100;return 1===e&&11!==n?t+"st":2===e&&12!==n?t+"nd":3===e&&13!==n?t+"rd":t+"th"}},function(t,e,n){"use strict";function o(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),o(n(25));var r=n(26);e.overlayMarkup=r.default,o(n(27)),o(n(28)),o(n(29));var i=n(0),a=i.default.MODAL_TITLE,s=i.default.MODAL_TEXT,c=i.default.ICON,l=i.default.FOOTER;e.iconMarkup='\n <div class="'+c+'"></div>',e.titleMarkup='\n <div class="'+a+'"></div>\n',e.textMarkup='\n <div class="'+s+'"></div>',e.footerMarkup='\n <div class="'+l+'"></div>\n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1);e.CONFIRM_KEY="confirm",e.CANCEL_KEY="cancel";var r={visible:!0,text:null,value:null,className:"",closeModal:!0},i=Object.assign({},r,{visible:!1,text:"Cancel",value:null}),a=Object.assign({},r,{text:"OK",value:!0});e.defaultButtonList={cancel:i,confirm:a};var s=function(t){switch(t){case e.CONFIRM_KEY:return a;case e.CANCEL_KEY:return i;default:var n=t.charAt(0).toUpperCase()+t.slice(1);return Object.assign({},r,{text:n,value:t})}},c=function(t,e){var n=s(t);return!0===e?Object.assign({},n,{visible:!0}):"string"==typeof e?Object.assign({},n,{visible:!0,text:e}):o.isPlainObject(e)?Object.assign({visible:!0},n,e):Object.assign({},n,{visible:!1})},l=function(t){for(var e={},n=0,o=Object.keys(t);n<o.length;n++){var r=o[n],a=t[r],s=c(r,a);e[r]=s}return e.cancel||(e.cancel=i),e},u=function(t){var n={};switch(t.length){case 1:n[e.CANCEL_KEY]=Object.assign({},i,{visible:!1});break;case 2:n[e.CANCEL_KEY]=c(e.CANCEL_KEY,t[0]),n[e.CONFIRM_KEY]=c(e.CONFIRM_KEY,t[1]);break;default:o.throwErr("Invalid number of 'buttons' in array ("+t.length+").\n If you want more than 2 buttons, you need to use an object!")}return n};e.getButtonListOpts=function(t){var n=e.defaultButtonList;return"string"==typeof t?n[e.CONFIRM_KEY]=c(e.CONFIRM_KEY,t):Array.isArray(t)?n=u(t):o.isPlainObject(t)?n=l(t):!0===t?n=u([!0,!0]):!1===t?n=u([!1,!1]):void 0===t&&(n=e.defaultButtonList),n}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(2),i=n(0),a=i.default.MODAL,s=i.default.OVERLAY,c=n(30),l=n(31),u=n(32),f=n(33);e.injectElIntoModal=function(t){var e=o.getNode(a),n=o.stringToNode(t);return e.appendChild(n),n};var d=function(t){t.className=a,t.textContent=""},p=function(t,e){d(t);var n=e.className;n&&t.classList.add(n)};e.initModalContent=function(t){var e=o.getNode(a);p(e,t),c.default(t.icon),l.initTitle(t.title),l.initText(t.text),f.default(t.content),u.default(t.buttons,t.dangerMode)};var m=function(){var t=o.getNode(s),e=o.stringToNode(r.modalMarkup);t.appendChild(e)};e.default=m},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(3),r={isOpen:!1,promise:null,actions:{},timer:null},i=Object.assign({},r);e.resetState=function(){i=Object.assign({},r)},e.setActionValue=function(t){if("string"==typeof t)return a(o.CONFIRM_KEY,t);for(var e in t)a(e,t[e])};var a=function(t,e){i.actions[t]||(i.actions[t]={}),Object.assign(i.actions[t],{value:e})};e.setActionOptionsFor=function(t,e){var n=(void 0===e?{}:e).closeModal,o=void 0===n||n;Object.assign(i.actions[t],{closeModal:o})},e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(3),i=n(0),a=i.default.OVERLAY,s=i.default.SHOW_MODAL,c=i.default.BUTTON,l=i.default.BUTTON_LOADING,u=n(5);e.openModal=function(){o.getNode(a).classList.add(s),u.default.isOpen=!0};var f=function(){o.getNode(a).classList.remove(s),u.default.isOpen=!1};e.onAction=function(t){void 0===t&&(t=r.CANCEL_KEY);var e=u.default.actions[t],n=e.value;if(!1===e.closeModal){var i=c+"--"+t;o.getNode(i).classList.add(l)}else f();u.default.promise.resolve(n)},e.getState=function(){var t=Object.assign({},u.default);return delete t.promise,delete t.timer,t},e.stopLoading=function(){for(var t=document.querySelectorAll("."+c),e=0;e<t.length;e++){t[e].classList.remove(l)}}},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){(function(e){t.exports=e.sweetAlert=n(9)}).call(e,n(7))},function(t,e,n){(function(e){t.exports=e.swal=n(10)}).call(e,n(7))},function(t,e,n){"undefined"!=typeof window&&n(11),n(16);var o=n(23).default;t.exports=o},function(t,e,n){var o=n(12);"string"==typeof o&&(o=[[t.i,o,""]]);var r={insertAt:"top"};r.transform=void 0;n(14)(o,r);o.locals&&(t.exports=o.locals)},function(t,e,n){e=t.exports=n(13)(void 0),e.push([t.i,'.swal-icon--error{border-color:#f27474;-webkit-animation:animateErrorIcon .5s;animation:animateErrorIcon .5s}.swal-icon--error__x-mark{position:relative;display:block;-webkit-animation:animateXMark .5s;animation:animateXMark .5s}.swal-icon--error__line{position:absolute;height:5px;width:47px;background-color:#f27474;display:block;top:37px;border-radius:2px}.swal-icon--error__line--left{-webkit-transform:rotate(45deg);transform:rotate(45deg);left:17px}.swal-icon--error__line--right{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);right:16px}@-webkit-keyframes animateErrorIcon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}to{-webkit-transform:rotateX(0deg);transform:rotateX(0deg);opacity:1}}@keyframes animateErrorIcon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}to{-webkit-transform:rotateX(0deg);transform:rotateX(0deg);opacity:1}}@-webkit-keyframes animateXMark{0%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}to{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}@keyframes animateXMark{0%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}to{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}.swal-icon--warning{border-color:#f8bb86;-webkit-animation:pulseWarning .75s infinite alternate;animation:pulseWarning .75s infinite alternate}.swal-icon--warning__body{width:5px;height:47px;top:10px;border-radius:2px;margin-left:-2px}.swal-icon--warning__body,.swal-icon--warning__dot{position:absolute;left:50%;background-color:#f8bb86}.swal-icon--warning__dot{width:7px;height:7px;border-radius:50%;margin-left:-4px;bottom:-11px}@-webkit-keyframes pulseWarning{0%{border-color:#f8d486}to{border-color:#f8bb86}}@keyframes pulseWarning{0%{border-color:#f8d486}to{border-color:#f8bb86}}.swal-icon--success{border-color:#a5dc86}.swal-icon--success:after,.swal-icon--success:before{content:"";border-radius:50%;position:absolute;width:60px;height:120px;background:#fff;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swal-icon--success:before{border-radius:120px 0 0 120px;top:-7px;left:-33px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:60px 60px;transform-origin:60px 60px}.swal-icon--success:after{border-radius:0 120px 120px 0;top:-11px;left:30px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:0 60px;transform-origin:0 60px;-webkit-animation:rotatePlaceholder 4.25s ease-in;animation:rotatePlaceholder 4.25s ease-in}.swal-icon--success__ring{width:80px;height:80px;border:4px solid hsla(98,55%,69%,.2);border-radius:50%;box-sizing:content-box;position:absolute;left:-4px;top:-4px;z-index:2}.swal-icon--success__hide-corners{width:5px;height:90px;background-color:#fff;padding:1px;position:absolute;left:28px;top:8px;z-index:1;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal-icon--success__line{height:5px;background-color:#a5dc86;display:block;border-radius:2px;position:absolute;z-index:2}.swal-icon--success__line--tip{width:25px;left:14px;top:46px;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-animation:animateSuccessTip .75s;animation:animateSuccessTip .75s}.swal-icon--success__line--long{width:47px;right:8px;top:38px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-animation:animateSuccessLong .75s;animation:animateSuccessLong .75s}@-webkit-keyframes rotatePlaceholder{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}to{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}@keyframes rotatePlaceholder{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}to{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}@-webkit-keyframes animateSuccessTip{0%{width:0;left:1px;top:19px}54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}to{width:25px;left:14px;top:45px}}@keyframes animateSuccessTip{0%{width:0;left:1px;top:19px}54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}to{width:25px;left:14px;top:45px}}@-webkit-keyframes animateSuccessLong{0%{width:0;right:46px;top:54px}65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}to{width:47px;right:8px;top:38px}}@keyframes animateSuccessLong{0%{width:0;right:46px;top:54px}65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}to{width:47px;right:8px;top:38px}}.swal-icon--info{border-color:#c9dae1}.swal-icon--info:before{width:5px;height:29px;bottom:17px;border-radius:2px;margin-left:-2px}.swal-icon--info:after,.swal-icon--info:before{content:"";position:absolute;left:50%;background-color:#c9dae1}.swal-icon--info:after{width:7px;height:7px;border-radius:50%;margin-left:-3px;top:19px}.swal-icon{width:80px;height:80px;border-width:4px;border-style:solid;border-radius:50%;padding:0;position:relative;box-sizing:content-box;margin:20px auto}.swal-icon:first-child{margin-top:32px}.swal-icon--custom{width:auto;height:auto;max-width:100%;border:none;border-radius:0}.swal-icon img{max-width:100%;max-height:100%}.swal-title{color:rgba(0,0,0,.65);font-weight:600;text-transform:none;position:relative;display:block;padding:13px 16px;font-size:27px;line-height:normal;text-align:center;margin-bottom:0}.swal-title:first-child{margin-top:26px}.swal-title:not(:first-child){padding-bottom:0}.swal-title:not(:last-child){margin-bottom:13px}.swal-text{font-size:16px;position:relative;float:none;line-height:normal;vertical-align:top;text-align:left;display:inline-block;margin:0;padding:0 10px;font-weight:400;color:rgba(0,0,0,.64);max-width:calc(100% - 20px);overflow-wrap:break-word;box-sizing:border-box}.swal-text:first-child{margin-top:45px}.swal-text:last-child{margin-bottom:45px}.swal-footer{text-align:right;padding-top:13px;margin-top:13px;padding:13px 16px;border-radius:inherit;border-top-left-radius:0;border-top-right-radius:0}.swal-button-container{margin:5px;display:inline-block;position:relative}.swal-button{background-color:#7cd1f9;color:#fff;border:none;box-shadow:none;border-radius:5px;font-weight:600;font-size:14px;padding:10px 24px;margin:0;cursor:pointer}.swal-button:not([disabled]):hover{background-color:#78cbf2}.swal-button:active{background-color:#70bce0}.swal-button:focus{outline:none;box-shadow:0 0 0 1px #fff,0 0 0 3px rgba(43,114,165,.29)}.swal-button[disabled]{opacity:.5;cursor:default}.swal-button::-moz-focus-inner{border:0}.swal-button--cancel{color:#555;background-color:#efefef}.swal-button--cancel:not([disabled]):hover{background-color:#e8e8e8}.swal-button--cancel:active{background-color:#d7d7d7}.swal-button--cancel:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px rgba(116,136,150,.29)}.swal-button--danger{background-color:#e64942}.swal-button--danger:not([disabled]):hover{background-color:#df4740}.swal-button--danger:active{background-color:#cf423b}.swal-button--danger:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px rgba(165,43,43,.29)}.swal-content{padding:0 20px;margin-top:20px;font-size:medium}.swal-content:last-child{margin-bottom:20px}.swal-content__input,.swal-content__textarea{-webkit-appearance:none;background-color:#fff;border:none;font-size:14px;display:block;box-sizing:border-box;width:100%;border:1px solid rgba(0,0,0,.14);padding:10px 13px;border-radius:2px;transition:border-color .2s}.swal-content__input:focus,.swal-content__textarea:focus{outline:none;border-color:#6db8ff}.swal-content__textarea{resize:vertical}.swal-button--loading{color:transparent}.swal-button--loading~.swal-button__loader{opacity:1}.swal-button__loader{position:absolute;height:auto;width:43px;z-index:2;left:50%;top:50%;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);text-align:center;pointer-events:none;opacity:0}.swal-button__loader div{display:inline-block;float:none;vertical-align:baseline;width:9px;height:9px;padding:0;border:none;margin:2px;opacity:.4;border-radius:7px;background-color:hsla(0,0%,100%,.9);transition:background .2s;-webkit-animation:swal-loading-anim 1s infinite;animation:swal-loading-anim 1s infinite}.swal-button__loader div:nth-child(3n+2){-webkit-animation-delay:.15s;animation-delay:.15s}.swal-button__loader div:nth-child(3n+3){-webkit-animation-delay:.3s;animation-delay:.3s}@-webkit-keyframes swal-loading-anim{0%{opacity:.4}20%{opacity:.4}50%{opacity:1}to{opacity:.4}}@keyframes swal-loading-anim{0%{opacity:.4}20%{opacity:.4}50%{opacity:1}to{opacity:.4}}.swal-overlay{position:fixed;top:0;bottom:0;left:0;right:0;text-align:center;font-size:0;overflow-y:auto;background-color:rgba(0,0,0,.4);z-index:10000;pointer-events:none;opacity:0;transition:opacity .3s}.swal-overlay:before{content:" ";display:inline-block;vertical-align:middle;height:100%}.swal-overlay--show-modal{opacity:1;pointer-events:auto}.swal-overlay--show-modal .swal-modal{opacity:1;pointer-events:auto;box-sizing:border-box;-webkit-animation:showSweetAlert .3s;animation:showSweetAlert .3s;will-change:transform}.swal-modal{width:478px;opacity:0;pointer-events:none;background-color:#fff;text-align:center;border-radius:5px;position:static;margin:20px auto;display:inline-block;vertical-align:middle;-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 50%;transform-origin:50% 50%;z-index:10001;transition:opacity .2s,-webkit-transform .3s;transition:transform .3s,opacity .2s;transition:transform .3s,opacity .2s,-webkit-transform .3s}@media (max-width:500px){.swal-modal{width:calc(100% - 20px)}}@-webkit-keyframes showSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1)}1%{-webkit-transform:scale(.5);transform:scale(.5)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}to{-webkit-transform:scale(1);transform:scale(1)}}@keyframes showSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1)}1%{-webkit-transform:scale(.5);transform:scale(.5)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}to{-webkit-transform:scale(1);transform:scale(1)}}',""])},function(t,e){function n(t,e){var n=t[1]||"",r=t[3];if(!r)return n;if(e&&"function"==typeof btoa){var i=o(r);return[n].concat(r.sources.map(function(t){return"/*# sourceURL="+r.sourceRoot+t+" */"})).concat([i]).join("\n")}return[n].join("\n")}function o(t){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(t))))+" */"}t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var o=n(e,t);return e[2]?"@media "+e[2]+"{"+o+"}":o}).join("")},e.i=function(t,n){"string"==typeof t&&(t=[[null,t,""]]);for(var o={},r=0;r<this.length;r++){var i=this[r][0];"number"==typeof i&&(o[i]=!0)}for(r=0;r<t.length;r++){var a=t[r];"number"==typeof a[0]&&o[a[0]]||(n&&!a[2]?a[2]=n:n&&(a[2]="("+a[2]+") and ("+n+")"),e.push(a))}},e}},function(t,e,n){function o(t,e){for(var n=0;n<t.length;n++){var o=t[n],r=m[o.id];if(r){r.refs++;for(var i=0;i<r.parts.length;i++)r.parts[i](o.parts[i]);for(;i<o.parts.length;i++)r.parts.push(u(o.parts[i],e))}else{for(var a=[],i=0;i<o.parts.length;i++)a.push(u(o.parts[i],e));m[o.id]={id:o.id,refs:1,parts:a}}}}function r(t,e){for(var n=[],o={},r=0;r<t.length;r++){var i=t[r],a=e.base?i[0]+e.base:i[0],s=i[1],c=i[2],l=i[3],u={css:s,media:c,sourceMap:l};o[a]?o[a].parts.push(u):n.push(o[a]={id:a,parts:[u]})}return n}function i(t,e){var n=v(t.insertInto);if(!n)throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");var o=w[w.length-1];if("top"===t.insertAt)o?o.nextSibling?n.insertBefore(e,o.nextSibling):n.appendChild(e):n.insertBefore(e,n.firstChild),w.push(e);else{if("bottom"!==t.insertAt)throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");n.appendChild(e)}}function a(t){if(null===t.parentNode)return!1;t.parentNode.removeChild(t);var e=w.indexOf(t);e>=0&&w.splice(e,1)}function s(t){var e=document.createElement("style");return t.attrs.type="text/css",l(e,t.attrs),i(t,e),e}function c(t){var e=document.createElement("link");return t.attrs.type="text/css",t.attrs.rel="stylesheet",l(e,t.attrs),i(t,e),e}function l(t,e){Object.keys(e).forEach(function(n){t.setAttribute(n,e[n])})}function u(t,e){var n,o,r,i;if(e.transform&&t.css){if(!(i=e.transform(t.css)))return function(){};t.css=i}if(e.singleton){var l=h++;n=g||(g=s(e)),o=f.bind(null,n,l,!1),r=f.bind(null,n,l,!0)}else t.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=c(e),o=p.bind(null,n,e),r=function(){a(n),n.href&&URL.revokeObjectURL(n.href)}):(n=s(e),o=d.bind(null,n),r=function(){a(n)});return o(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;o(t=e)}else r()}}function f(t,e,n,o){var r=n?"":o.css;if(t.styleSheet)t.styleSheet.cssText=x(e,r);else{var i=document.createTextNode(r),a=t.childNodes;a[e]&&t.removeChild(a[e]),a.length?t.insertBefore(i,a[e]):t.appendChild(i)}}function d(t,e){var n=e.css,o=e.media;if(o&&t.setAttribute("media",o),t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}function p(t,e,n){var o=n.css,r=n.sourceMap,i=void 0===e.convertToAbsoluteUrls&&r;(e.convertToAbsoluteUrls||i)&&(o=y(o)),r&&(o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var a=new Blob([o],{type:"text/css"}),s=t.href;t.href=URL.createObjectURL(a),s&&URL.revokeObjectURL(s)}var m={},b=function(t){var e;return function(){return void 0===e&&(e=t.apply(this,arguments)),e}}(function(){return window&&document&&document.all&&!window.atob}),v=function(t){var e={};return function(n){return void 0===e[n]&&(e[n]=t.call(this,n)),e[n]}}(function(t){return document.querySelector(t)}),g=null,h=0,w=[],y=n(15);t.exports=function(t,e){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");e=e||{},e.attrs="object"==typeof e.attrs?e.attrs:{},e.singleton||(e.singleton=b()),e.insertInto||(e.insertInto="head"),e.insertAt||(e.insertAt="bottom");var n=r(t,e);return o(n,e),function(t){for(var i=[],a=0;a<n.length;a++){var s=n[a],c=m[s.id];c.refs--,i.push(c)}if(t){o(r(t,e),e)}for(var a=0;a<i.length;a++){var c=i[a];if(0===c.refs){for(var l=0;l<c.parts.length;l++)c.parts[l]();delete m[c.id]}}}};var x=function(){var t=[];return function(e,n){return t[e]=n,t.filter(Boolean).join("\n")}}()},function(t,e){t.exports=function(t){var e="undefined"!=typeof window&&window.location;if(!e)throw new Error("fixUrls requires window.location");if(!t||"string"!=typeof t)return t;var n=e.protocol+"//"+e.host,o=n+e.pathname.replace(/\/[^\/]*$/,"/");return t.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi,function(t,e){var r=e.trim().replace(/^"(.*)"$/,function(t,e){return e}).replace(/^'(.*)'$/,function(t,e){return e});if(/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/)/i.test(r))return t;var i;return i=0===r.indexOf("//")?r:0===r.indexOf("/")?n+r:o+r.replace(/^\.\//,""),"url("+JSON.stringify(i)+")"})}},function(t,e,n){var o=n(17);"undefined"==typeof window||window.Promise||(window.Promise=o),n(21),String.prototype.includes||(String.prototype.includes=function(t,e){"use strict";return"number"!=typeof e&&(e=0),!(e+t.length>this.length)&&-1!==this.indexOf(t,e)}),Array.prototype.includes||Object.defineProperty(Array.prototype,"includes",{value:function(t,e){if(null==this)throw new TypeError('"this" is null or not defined');var n=Object(this),o=n.length>>>0;if(0===o)return!1;for(var r=0|e,i=Math.max(r>=0?r:o-Math.abs(r),0);i<o;){if(function(t,e){return t===e||"number"==typeof t&&"number"==typeof e&&isNaN(t)&&isNaN(e)}(n[i],t))return!0;i++}return!1}}),"undefined"!=typeof window&&function(t){t.forEach(function(t){t.hasOwnProperty("remove")||Object.defineProperty(t,"remove",{configurable:!0,enumerable:!0,writable:!0,value:function(){this.parentNode.removeChild(this)}})})}([Element.prototype,CharacterData.prototype,DocumentType.prototype])},function(t,e,n){(function(e){!function(n){function o(){}function r(t,e){return function(){t.apply(e,arguments)}}function i(t){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],f(t,this)}function a(t,e){for(;3===t._state;)t=t._value;if(0===t._state)return void t._deferreds.push(e);t._handled=!0,i._immediateFn(function(){var n=1===t._state?e.onFulfilled:e.onRejected;if(null===n)return void(1===t._state?s:c)(e.promise,t._value);var o;try{o=n(t._value)}catch(t){return void c(e.promise,t)}s(e.promise,o)})}function s(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var n=e.then;if(e instanceof i)return t._state=3,t._value=e,void l(t);if("function"==typeof n)return void f(r(n,e),t)}t._state=1,t._value=e,l(t)}catch(e){c(t,e)}}function c(t,e){t._state=2,t._value=e,l(t)}function l(t){2===t._state&&0===t._deferreds.length&&i._immediateFn(function(){t._handled||i._unhandledRejectionFn(t._value)});for(var e=0,n=t._deferreds.length;e<n;e++)a(t,t._deferreds[e]);t._deferreds=null}function u(t,e,n){this.onFulfilled="function"==typeof t?t:null,this.onRejected="function"==typeof e?e:null,this.promise=n}function f(t,e){var n=!1;try{t(function(t){n||(n=!0,s(e,t))},function(t){n||(n=!0,c(e,t))})}catch(t){if(n)return;n=!0,c(e,t)}}var d=setTimeout;i.prototype.catch=function(t){return this.then(null,t)},i.prototype.then=function(t,e){var n=new this.constructor(o);return a(this,new u(t,e,n)),n},i.all=function(t){var e=Array.prototype.slice.call(t);return new i(function(t,n){function o(i,a){try{if(a&&("object"==typeof a||"function"==typeof a)){var s=a.then;if("function"==typeof s)return void s.call(a,function(t){o(i,t)},n)}e[i]=a,0==--r&&t(e)}catch(t){n(t)}}if(0===e.length)return t([]);for(var r=e.length,i=0;i<e.length;i++)o(i,e[i])})},i.resolve=function(t){return t&&"object"==typeof t&&t.constructor===i?t:new i(function(e){e(t)})},i.reject=function(t){return new i(function(e,n){n(t)})},i.race=function(t){return new i(function(e,n){for(var o=0,r=t.length;o<r;o++)t[o].then(e,n)})},i._immediateFn="function"==typeof e&&function(t){e(t)}||function(t){d(t,0)},i._unhandledRejectionFn=function(t){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",t)},i._setImmediateFn=function(t){i._immediateFn=t},i._setUnhandledRejectionFn=function(t){i._unhandledRejectionFn=t},void 0!==t&&t.exports?t.exports=i:n.Promise||(n.Promise=i)}(this)}).call(e,n(18).setImmediate)},function(t,e,n){function o(t,e){this._id=t,this._clearFn=e}var r=Function.prototype.apply;e.setTimeout=function(){return new o(r.call(setTimeout,window,arguments),clearTimeout)},e.setInterval=function(){return new o(r.call(setInterval,window,arguments),clearInterval)},e.clearTimeout=e.clearInterval=function(t){t&&t.close()},o.prototype.unref=o.prototype.ref=function(){},o.prototype.close=function(){this._clearFn.call(window,this._id)},e.enroll=function(t,e){clearTimeout(t._idleTimeoutId),t._idleTimeout=e},e.unenroll=function(t){clearTimeout(t._idleTimeoutId),t._idleTimeout=-1},e._unrefActive=e.active=function(t){clearTimeout(t._idleTimeoutId);var e=t._idleTimeout;e>=0&&(t._idleTimeoutId=setTimeout(function(){t._onTimeout&&t._onTimeout()},e))},n(19),e.setImmediate=setImmediate,e.clearImmediate=clearImmediate},function(t,e,n){(function(t,e){!function(t,n){"use strict";function o(t){"function"!=typeof t&&(t=new Function(""+t));for(var e=new Array(arguments.length-1),n=0;n<e.length;n++)e[n]=arguments[n+1];var o={callback:t,args:e};return l[c]=o,s(c),c++}function r(t){delete l[t]}function i(t){var e=t.callback,o=t.args;switch(o.length){case 0:e();break;case 1:e(o[0]);break;case 2:e(o[0],o[1]);break;case 3:e(o[0],o[1],o[2]);break;default:e.apply(n,o)}}function a(t){if(u)setTimeout(a,0,t);else{var e=l[t];if(e){u=!0;try{i(e)}finally{r(t),u=!1}}}}if(!t.setImmediate){var s,c=1,l={},u=!1,f=t.document,d=Object.getPrototypeOf&&Object.getPrototypeOf(t);d=d&&d.setTimeout?d:t,"[object process]"==={}.toString.call(t.process)?function(){s=function(t){e.nextTick(function(){a(t)})}}():function(){if(t.postMessage&&!t.importScripts){var e=!0,n=t.onmessage;return t.onmessage=function(){e=!1},t.postMessage("","*"),t.onmessage=n,e}}()?function(){var e="setImmediate$"+Math.random()+"$",n=function(n){n.source===t&&"string"==typeof n.data&&0===n.data.indexOf(e)&&a(+n.data.slice(e.length))};t.addEventListener?t.addEventListener("message",n,!1):t.attachEvent("onmessage",n),s=function(n){t.postMessage(e+n,"*")}}():t.MessageChannel?function(){var t=new MessageChannel;t.port1.onmessage=function(t){a(t.data)},s=function(e){t.port2.postMessage(e)}}():f&&"onreadystatechange"in f.createElement("script")?function(){var t=f.documentElement;s=function(e){var n=f.createElement("script");n.onreadystatechange=function(){a(e),n.onreadystatechange=null,t.removeChild(n),n=null},t.appendChild(n)}}():function(){s=function(t){setTimeout(a,0,t)}}(),d.setImmediate=o,d.clearImmediate=r}}("undefined"==typeof self?void 0===t?this:t:self)}).call(e,n(7),n(20))},function(t,e){function n(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function r(t){if(u===setTimeout)return setTimeout(t,0);if((u===n||!u)&&setTimeout)return u=setTimeout,setTimeout(t,0);try{return u(t,0)}catch(e){try{return u.call(null,t,0)}catch(e){return u.call(this,t,0)}}}function i(t){if(f===clearTimeout)return clearTimeout(t);if((f===o||!f)&&clearTimeout)return f=clearTimeout,clearTimeout(t);try{return f(t)}catch(e){try{return f.call(null,t)}catch(e){return f.call(this,t)}}}function a(){b&&p&&(b=!1,p.length?m=p.concat(m):v=-1,m.length&&s())}function s(){if(!b){var t=r(a);b=!0;for(var e=m.length;e;){for(p=m,m=[];++v<e;)p&&p[v].run();v=-1,e=m.length}p=null,b=!1,i(t)}}function c(t,e){this.fun=t,this.array=e}function l(){}var u,f,d=t.exports={};!function(){try{u="function"==typeof setTimeout?setTimeout:n}catch(t){u=n}try{f="function"==typeof clearTimeout?clearTimeout:o}catch(t){f=o}}();var p,m=[],b=!1,v=-1;d.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];m.push(new c(t,e)),1!==m.length||b||r(s)},c.prototype.run=function(){this.fun.apply(null,this.array)},d.title="browser",d.browser=!0,d.env={},d.argv=[],d.version="",d.versions={},d.on=l,d.addListener=l,d.once=l,d.off=l,d.removeListener=l,d.removeAllListeners=l,d.emit=l,d.prependListener=l,d.prependOnceListener=l,d.listeners=function(t){return[]},d.binding=function(t){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(t){throw new Error("process.chdir is not supported")},d.umask=function(){return 0}},function(t,e,n){"use strict";n(22).polyfill()},function(t,e,n){"use strict";function o(t,e){if(void 0===t||null===t)throw new TypeError("Cannot convert first argument to object");for(var n=Object(t),o=1;o<arguments.length;o++){var r=arguments[o];if(void 0!==r&&null!==r)for(var i=Object.keys(Object(r)),a=0,s=i.length;a<s;a++){var c=i[a],l=Object.getOwnPropertyDescriptor(r,c);void 0!==l&&l.enumerable&&(n[c]=r[c])}}return n}function r(){Object.assign||Object.defineProperty(Object,"assign",{enumerable:!1,configurable:!0,writable:!0,value:o})}t.exports={assign:o,polyfill:r}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(24),r=n(6),i=n(5),a=n(36),s=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];if("undefined"!=typeof window){var n=a.getOpts.apply(void 0,t);return new Promise(function(t,e){i.default.promise={resolve:t,reject:e},o.default(n),setTimeout(function(){r.openModal()})})}};s.close=r.onAction,s.getState=r.getState,s.setActionValue=i.setActionValue,s.stopLoading=r.stopLoading,s.setDefaults=a.setDefaults,e.default=s},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(0),i=r.default.MODAL,a=n(4),s=n(34),c=n(35),l=n(1);e.init=function(t){o.getNode(i)||(document.body||l.throwErr("You can only use SweetAlert AFTER the DOM has loaded!"),s.default(),a.default()),a.initModalContent(t),c.default(t)},e.default=e.init},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.MODAL;e.modalMarkup='\n <div class="'+r+'" role="dialog" aria-modal="true"></div>',e.default=e.modalMarkup},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.OVERLAY,i='<div \n class="'+r+'"\n tabIndex="-1">\n </div>';e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.ICON;e.errorIconMarkup=function(){var t=r+"--error",e=t+"__line";return'\n <div class="'+t+'__x-mark">\n <span class="'+e+" "+e+'--left"></span>\n <span class="'+e+" "+e+'--right"></span>\n </div>\n '},e.warningIconMarkup=function(){var t=r+"--warning";return'\n <span class="'+t+'__body">\n <span class="'+t+'__dot"></span>\n </span>\n '},e.successIconMarkup=function(){var t=r+"--success";return'\n <span class="'+t+"__line "+t+'__line--long"></span>\n <span class="'+t+"__line "+t+'__line--tip"></span>\n\n <div class="'+t+'__ring"></div>\n <div class="'+t+'__hide-corners"></div>\n '}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.CONTENT;e.contentMarkup='\n <div class="'+r+'">\n\n </div>\n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.BUTTON_CONTAINER,i=o.default.BUTTON,a=o.default.BUTTON_LOADER;e.buttonMarkup='\n <div class="'+r+'">\n\n <button\n class="'+i+'"\n ></button>\n\n <div class="'+a+'">\n <div></div>\n <div></div>\n <div></div>\n </div>\n\n </div>\n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(4),r=n(2),i=n(0),a=i.default.ICON,s=i.default.ICON_CUSTOM,c=["error","warning","success","info"],l={error:r.errorIconMarkup(),warning:r.warningIconMarkup(),success:r.successIconMarkup()},u=function(t,e){var n=a+"--"+t;e.classList.add(n);var o=l[t];o&&(e.innerHTML=o)},f=function(t,e){e.classList.add(s);var n=document.createElement("img");n.src=t,e.appendChild(n)},d=function(t){if(t){var e=o.injectElIntoModal(r.iconMarkup);c.includes(t)?u(t,e):f(t,e)}};e.default=d},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(2),r=n(4),i=function(t){navigator.userAgent.includes("AppleWebKit")&&(t.style.display="none",t.offsetHeight,t.style.display="")};e.initTitle=function(t){if(t){var e=r.injectElIntoModal(o.titleMarkup);e.textContent=t,i(e)}},e.initText=function(t){if(t){var e=document.createDocumentFragment();t.split("\n").forEach(function(t,n,o){e.appendChild(document.createTextNode(t)),n<o.length-1&&e.appendChild(document.createElement("br"))});var n=r.injectElIntoModal(o.textMarkup);n.appendChild(e),i(n)}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(4),i=n(0),a=i.default.BUTTON,s=i.default.DANGER_BUTTON,c=n(3),l=n(2),u=n(6),f=n(5),d=function(t,e,n){var r=e.text,i=e.value,d=e.className,p=e.closeModal,m=o.stringToNode(l.buttonMarkup),b=m.querySelector("."+a),v=a+"--"+t;if(b.classList.add(v),d){(Array.isArray(d)?d:d.split(" ")).filter(function(t){return t.length>0}).forEach(function(t){b.classList.add(t)})}n&&t===c.CONFIRM_KEY&&b.classList.add(s),b.textContent=r;var g={};return g[t]=i,f.setActionValue(g),f.setActionOptionsFor(t,{closeModal:p}),b.addEventListener("click",function(){return u.onAction(t)}),m},p=function(t,e){var n=r.injectElIntoModal(l.footerMarkup);for(var o in t){var i=t[o],a=d(o,i,e);i.visible&&n.appendChild(a)}0===n.children.length&&n.remove()};e.default=p},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(3),r=n(4),i=n(2),a=n(5),s=n(6),c=n(0),l=c.default.CONTENT,u=function(t){t.addEventListener("input",function(t){var e=t.target,n=e.value;a.setActionValue(n)}),t.addEventListener("keyup",function(t){if("Enter"===t.key)return s.onAction(o.CONFIRM_KEY)}),setTimeout(function(){t.focus(),a.setActionValue("")},0)},f=function(t,e,n){var o=document.createElement(e),r=l+"__"+e;o.classList.add(r);for(var i in n){var a=n[i];o[i]=a}"input"===e&&u(o),t.appendChild(o)},d=function(t){if(t){var e=r.injectElIntoModal(i.contentMarkup),n=t.element,o=t.attributes;"string"==typeof n?f(e,n,o):e.appendChild(n)}};e.default=d},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(2),i=function(){var t=o.stringToNode(r.overlayMarkup);document.body.appendChild(t)};e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(5),r=n(6),i=n(1),a=n(3),s=n(0),c=s.default.MODAL,l=s.default.BUTTON,u=s.default.OVERLAY,f=function(t){t.preventDefault(),v()},d=function(t){t.preventDefault(),g()},p=function(t){if(o.default.isOpen)switch(t.key){case"Escape":return r.onAction(a.CANCEL_KEY)}},m=function(t){if(o.default.isOpen)switch(t.key){case"Tab":return f(t)}},b=function(t){if(o.default.isOpen)return"Tab"===t.key&&t.shiftKey?d(t):void 0},v=function(){var t=i.getNode(l);t&&(t.tabIndex=0,t.focus())},g=function(){var t=i.getNode(c),e=t.querySelectorAll("."+l),n=e.length-1,o=e[n];o&&o.focus()},h=function(t){t[t.length-1].addEventListener("keydown",m)},w=function(t){t[0].addEventListener("keydown",b)},y=function(){var t=i.getNode(c),e=t.querySelectorAll("."+l);e.length&&(h(e),w(e))},x=function(t){if(i.getNode(u)===t.target)return r.onAction(a.CANCEL_KEY)},_=function(t){var e=i.getNode(u);e.removeEventListener("click",x),t&&e.addEventListener("click",x)},k=function(t){o.default.timer&&clearTimeout(o.default.timer),t&&(o.default.timer=window.setTimeout(function(){return r.onAction(a.CANCEL_KEY)},t))},O=function(t){t.closeOnEsc?document.addEventListener("keyup",p):document.removeEventListener("keyup",p),t.dangerMode?v():g(),y(),_(t.closeOnClickOutside),k(t.timer)};e.default=O},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(3),i=n(37),a=n(38),s={title:null,text:null,icon:null,buttons:r.defaultButtonList,content:null,className:null,closeOnClickOutside:!0,closeOnEsc:!0,dangerMode:!1,timer:null},c=Object.assign({},s);e.setDefaults=function(t){c=Object.assign({},s,t)};var l=function(t){var e=t&&t.button,n=t&&t.buttons;return void 0!==e&&void 0!==n&&o.throwErr("Cannot set both 'button' and 'buttons' options!"),void 0!==e?{confirm:e}:n},u=function(t){return o.ordinalSuffixOf(t+1)},f=function(t,e){o.throwErr(u(e)+" argument ('"+t+"') is invalid")},d=function(t,e){var n=t+1,r=e[n];o.isPlainObject(r)||void 0===r||o.throwErr("Expected "+u(n)+" argument ('"+r+"') to be a plain object")},p=function(t,e){var n=t+1,r=e[n];void 0!==r&&o.throwErr("Unexpected "+u(n)+" argument ("+r+")")},m=function(t,e,n,r){var i=typeof e,a="string"===i,s=e instanceof Element;if(a){if(0===n)return{text:e};if(1===n)return{text:e,title:r[0]};if(2===n)return d(n,r),{icon:e};f(e,n)}else{if(s&&0===n)return d(n,r),{content:e};if(o.isPlainObject(e))return p(n,r),e;f(e,n)}};e.getOpts=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n={};t.forEach(function(e,o){var r=m(0,e,o,t);Object.assign(n,r)});var o=l(n);n.buttons=r.getButtonListOpts(o),delete n.button,n.content=i.getContentOpts(n.content);var u=Object.assign({},s,c,n);return Object.keys(u).forEach(function(t){a.DEPRECATED_OPTS[t]&&a.logDeprecation(t)}),u}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r={element:"input",attributes:{placeholder:""}};e.getContentOpts=function(t){var e={};return o.isPlainObject(t)?Object.assign(e,t):t instanceof Element?{element:t}:"input"===t?r:null}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.logDeprecation=function(t){var n=e.DEPRECATED_OPTS[t],o=n.onlyRename,r=n.replacement,i=n.subOption,a=n.link,s=o?"renamed":"deprecated",c='SweetAlert warning: "'+t+'" option has been '+s+".";if(r){c+=" Please use"+(i?' "'+i+'" in ':" ")+'"'+r+'" instead.'}var l="https://sweetalert.js.org";c+=a?" More details: "+l+a:" More details: "+l+"/guides/#upgrading-from-1x",console.warn(c)},e.DEPRECATED_OPTS={type:{replacement:"icon",link:"/docs/#icon"},imageUrl:{replacement:"icon",link:"/docs/#icon"},customClass:{replacement:"className",onlyRename:!0,link:"/docs/#classname"},imageSize:{},showCancelButton:{replacement:"buttons",link:"/docs/#buttons"},showConfirmButton:{replacement:"button",link:"/docs/#button"},confirmButtonText:{replacement:"button",link:"/docs/#button"},confirmButtonColor:{},cancelButtonText:{replacement:"buttons",link:"/docs/#buttons"},closeOnConfirm:{replacement:"button",subOption:"closeModal",link:"/docs/#button"},closeOnCancel:{replacement:"buttons",subOption:"closeModal",link:"/docs/#buttons"},showLoaderOnConfirm:{replacement:"buttons"},animation:{},inputType:{replacement:"content",link:"/docs/#content"},inputValue:{replacement:"content",link:"/docs/#content"},inputPlaceholder:{replacement:"content",link:"/docs/#content"},html:{replacement:"content",link:"/docs/#content"},allowEscapeKey:{replacement:"closeOnEsc",onlyRename:!0,link:"/docs/#closeonesc"},allowClickOutside:{replacement:"closeOnClickOutside",onlyRename:!0,link:"/docs/#closeonclickoutside"}}}])});
automatic-translator-addon-for-loco-translate.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
  /*
3
  Plugin Name:Loco Automatic Translate Addon
4
- Description:Auto language translator add-on for Loco Translate plugin to translate plugins and themes translation files into any language via fully automatic machine translations via Yendex Translate API.
5
- Version:1.4.1
6
  License:GPL2
7
  Text Domain:atlt
8
  Domain Path:languages
@@ -13,7 +13,7 @@ namespace LocoAutoTranslateAddon;
13
  use LocoAutoTranslateAddon\Helpers\Helpers;
14
  /**
15
  * @package Loco Automatic Translate Addon
16
- * @version 1.4.1
17
  */
18
  if (!defined('ABSPATH')) {
19
  die('WordPress Environment Not Found!');
@@ -22,7 +22,7 @@ if (!defined('ABSPATH')) {
22
  define('ATLT_FILE', __FILE__);
23
  define('ATLT_URL', plugin_dir_url(ATLT_FILE));
24
  define('ATLT_PATH', plugin_dir_path(ATLT_FILE));
25
- define('ATLT_VERSION', '1.4.1');
26
 
27
  class LocoAutoTranslate
28
  {
@@ -37,7 +37,7 @@ class LocoAutoTranslate
37
  add_action('wp_ajax_atlt_translation', array($this, 'atlt_translate_string_callback'), 100);
38
  add_action('init',array($this,'checkStatus'));
39
  add_action('plugins_loaded', array($this,'include_files'));
40
- add_action('testRequest',array($this,'testHtmltranslation'));
41
  }
42
 
43
  /**
@@ -67,6 +67,7 @@ class LocoAutoTranslate
67
  //require_once ATLT_PATH . "includes/init-api.php";
68
  include_once ATLT_PATH . 'includes/Register/LocoAutomaticTranslateAddonPro.php';
69
  }
 
70
  }
71
  public function checkStatus(){
72
  Helpers::checkPeriod();
@@ -105,41 +106,37 @@ class LocoAutoTranslate
105
  }
106
 
107
  /*
108
- |------------------------------------------------------------------------
109
- | Enqueue required JS file
110
- |------------------------------------------------------------------------
111
- */
112
- function atlt_enqueue_scripts(){
113
-
114
- wp_deregister_script('loco-js-editor');
115
- wp_register_script( 'loco-js-editor', ATLT_URL.'assets/js/loco-js-editor.min.js', array('loco-js-min-admin'),false, true);
116
-
117
- if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'file-edit') {
118
- $data=array();
119
- wp_enqueue_script('loco-js-editor');
120
- $status=Helpers::atltVerification();
121
- $nonce = wp_create_nonce('atlt_nonce');
122
- if($status['type']=="free"){
123
- $data['api_key']=Helpers::getAPIkey();
124
- $data['info']=Helpers::atltVerification();
125
- $data['nonce']=$nonce;
126
- }else{
127
- $data['api_key']=Helpers::getAPIkey();
128
- $key=Helpers::getLicenseKey();
129
- if(Helpers::validKey( $key)){
130
- $data['info']['type']="pro";
131
- $data['info']['allowed']="yes";
132
- $data['info']['licenseKey']=$key;
133
- $data['nonce']=$nonce;
134
- }
135
  }
136
- $extraData['preloader_path']=ATLT_URL.'/assets/images/preloader.gif';
137
- wp_localize_script('loco-js-editor', 'ATLT', $data);
138
- wp_localize_script('loco-js-editor', 'extradata', $extraData);
139
-
140
- }
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
- }
143
 
144
  /*
145
  |----------------------------------------------------------------------
@@ -155,74 +152,238 @@ class LocoAutoTranslate
155
  // user status
156
  $status=Helpers::atltVerification();
157
  if($status['type']=="free" && $status['allowed']=="no"){
158
- die(json_encode(array('code' => 800, 'message' => 'You have consumed daily limit')));
159
  }
160
-
161
- // grab API keys
162
- $api_key_arr = Helpers::getAPIkey();
163
- $apiKey = $api_key_arr['atlt_api-key'];
164
  // get request vars
165
  if (empty($_REQUEST['data'])) {
166
  die(json_encode(array('code' => 900, 'message' => 'Empty request')));
167
  }
168
-
169
  if(isset($_REQUEST['data'])){
170
-
 
 
171
  $requestData = $_REQUEST['data'];
172
  $targetLang=$_REQUEST['targetLan'];
173
  $sourceLang=$_REQUEST['sourceLan'];
174
- if($targetLang=="nb"){
175
  $targetLang="no";
176
  }
177
- $lang = $sourceLang.'-'.$targetLang;
178
  $request_chars = $_REQUEST['requestChars'];
179
  $totalChars = $_REQUEST['totalCharacters'];
180
- $requestType=$_REQUEST['strType'];
181
-
182
-
183
- // create query string
184
- $queryString='';
185
- $stringArr= json_decode(stripslashes($requestData),true);
186
- if(is_array($stringArr)){
187
- foreach($stringArr as $str){
188
- $queryString.='&text='.urlencode($str);
189
- }
190
- }
191
- // build query
192
- $buildReqURL='';
193
- $buildReqURL.='https://translate.yandex.net/api/v1.5/tr.json/translate';
194
- $buildReqURL.='?key=' . $apiKey . '&lang=' . $lang.'&format='.$requestType;
195
- $buildReqURL.=$queryString;
196
- // get API response
197
- $response = wp_remote_get($buildReqURL, array('timeout'=>'180'));
198
-
199
- if (is_wp_error($response)) {
200
- return $response; // Bail early
201
- }
202
- $body = wp_remote_retrieve_body($response);
203
- $data = json_decode( $body, true); // convert string into assoc array
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
- if($data['code']==200){
206
- // grab translation count data
207
- $today_translated = Helpers::todayTranslated( $request_chars);
208
- $monthly_translated = Helpers::monthlyTranslated( $request_chars);
209
- /** Calculate the total time save on translation */
210
- $session_time_saved = Helpers::atlt_time_saved_on_translation( $totalChars);
211
- $total_time_saved = Helpers::atlt_time_saved_on_translation($totalChars);
212
- // create response array
213
- $data['stats']=array(
214
- 'todays_translation'=>$today_translated,
215
- 'total_translation'=>$monthly_translated,
216
- 'time_saved'=> $session_time_saved,
217
- 'total_time_saved'=>$total_time_saved,
218
- 'totalChars'=>$totalChars
219
- );
220
  }
221
- die(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
222
  }
223
 
224
- }
225
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
 
227
  /*
228
  |------------------------------------------------------
@@ -238,6 +399,7 @@ class LocoAutoTranslate
238
  }
239
 
240
 
 
241
  /*
242
  |-------------------------------------------------------
243
  | Plugin deactivation
1
  <?php
2
  /*
3
  Plugin Name:Loco Automatic Translate Addon
4
+ Description:Auto language translator add-on for Loco Translate plugin to translate plugins and themes translation files into any language via fully automatic machine translations via yandex Translate API.
5
+ Version:1.5
6
  License:GPL2
7
  Text Domain:atlt
8
  Domain Path:languages
13
  use LocoAutoTranslateAddon\Helpers\Helpers;
14
  /**
15
  * @package Loco Automatic Translate Addon
16
+ * @version 1.5
17
  */
18
  if (!defined('ABSPATH')) {
19
  die('WordPress Environment Not Found!');
22
  define('ATLT_FILE', __FILE__);
23
  define('ATLT_URL', plugin_dir_url(ATLT_FILE));
24
  define('ATLT_PATH', plugin_dir_path(ATLT_FILE));
25
+ define('ATLT_VERSION', '1.5');
26
 
27
  class LocoAutoTranslate
28
  {
37
  add_action('wp_ajax_atlt_translation', array($this, 'atlt_translate_string_callback'), 100);
38
  add_action('init',array($this,'checkStatus'));
39
  add_action('plugins_loaded', array($this,'include_files'));
40
+
41
  }
42
 
43
  /**
67
  //require_once ATLT_PATH . "includes/init-api.php";
68
  include_once ATLT_PATH . 'includes/Register/LocoAutomaticTranslateAddonPro.php';
69
  }
70
+
71
  }
72
  public function checkStatus(){
73
  Helpers::checkPeriod();
106
  }
107
 
108
  /*
109
+ |------------------------------------------------------
110
+ | Send Request to yandex API
111
+ |------------------------------------------------------
112
+ */
113
+ public function yandex_api_call($stringArr,$target_language,$source_language,$requestType,$apiKey){
114
+ // create query string
115
+ $queryString='';
116
+ $langParam = $source_language.'-'.$target_language;
117
+
118
+ if(is_array($stringArr)){
119
+ foreach($stringArr as $str){
120
+ $queryString.='&text='.urlencode($str);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
122
+ }
123
+ // build query
124
+ $buildReqURL='';
125
+ $buildReqURL.='https://translate.yandex.net/api/v1.5/tr.json/translate';
126
+ $buildReqURL.='?key=' . $apiKey . '&lang=' . $langParam.'&format='.$requestType;
127
+ $buildReqURL.=$queryString;
128
+ // get API response
129
+ $response = wp_remote_get($buildReqURL, array('timeout'=>'180'));
130
+
131
+ if (is_wp_error($response)) {
132
+ return $response; // Bail early
133
+ }
134
+ $body = wp_remote_retrieve_body($response);
135
+ // convert string into assoc array
136
+ $data = json_decode( $body, true);
137
+ return $data;
138
+ }
139
 
 
140
 
141
  /*
142
  |----------------------------------------------------------------------
152
  // user status
153
  $status=Helpers::atltVerification();
154
  if($status['type']=="free" && $status['allowed']=="no"){
155
+ die(json_encode(array('code' => 800, 'message' => 'You have cons med daily limit')));
156
  }
 
 
 
 
157
  // get request vars
158
  if (empty($_REQUEST['data'])) {
159
  die(json_encode(array('code' => 900, 'message' => 'Empty request')));
160
  }
 
161
  if(isset($_REQUEST['data'])){
162
+ $responseArr=array();
163
+ $response=array();
164
+
165
  $requestData = $_REQUEST['data'];
166
  $targetLang=$_REQUEST['targetLan'];
167
  $sourceLang=$_REQUEST['sourceLan'];
168
+ if($targetLang=="nb" || $targetLang=="nn"){
169
  $targetLang="no";
170
  }
171
+
172
  $request_chars = $_REQUEST['requestChars'];
173
  $totalChars = $_REQUEST['totalCharacters'];
174
+ $requestType=$_REQUEST['strType'];
175
+ $apiType=$_REQUEST['apiType'];
176
+ $stringArr= json_decode(stripslashes($requestData),true);
177
+
178
+ if($apiType=="google"){
179
+ $g_api_key= Helpers::getAPIkey("google");
180
+ if(empty($g_api_key)||$g_api_key==""){
181
+ die(json_encode(array('code' => 902, 'message' => 'You have not Entered Google Translate API Key')));
182
+ }
183
+ $apiKey = $g_api_key;
184
+
185
+ if(is_array( $stringArr)&& !empty($stringArr))
186
+ {
187
+ $response=$this->translate_array($stringArr,$targetLang,$sourceLang, $apiKey);
188
+ if(is_array($response)&& count($response)>=1)
189
+ {
190
+ $responseArr['translatedString']=$response;
191
+ $responseArr['code']=200;
192
+ // grab translation count data
193
+ $responseArr['stats']= $this->saveStringsCount($request_chars,$totalChars,$apiType);
194
+ }else{
195
+
196
+ $responseArr['code']=500;
197
+ $responseArr['message']=$response;
198
+
199
+ }
200
+ }
201
+ }else{
202
+ // grab API keys
203
+ $api_key = Helpers::getAPIkey("yandex");
204
+
205
+ if(empty($api_key)|| $api_key==""){
206
+ die(json_encode(array('code' => 902, 'message' => 'You have not Entered yandex API Key')));
207
+ }
208
+ $apiKey = $api_key;
209
+ if(is_array( $stringArr)&& !empty($stringArr))
210
+ {
211
+ $response=$this->yandex_api_call($stringArr,$targetLang,$sourceLang,$requestType,$apiKey);
212
+
213
+ if(is_array($response) && $response['code']==200)
214
+ {
215
+ // grab translation count data
216
+ $responseArr['code']=200;
217
+ $responseArr['translatedString']= $response['text'];
218
+ $responseArr['stats']= $this->saveStringsCount($request_chars,$totalChars,$apiType);
219
+ }else{
220
+ $responseArr['code']=500;
221
+ $responseArr['message']=$response['errors']['http_request_failed'];
222
+ }
223
+ }
224
+ }
225
+
226
+ die(json_encode($responseArr, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
227
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  }
229
+
230
  }
231
 
232
+ }
233
+
234
+
235
+
236
+ public function saveStringsCount($request_chars,$totalChars,$apiType)
237
+ {
238
+ if($apiType=="google"){
239
+ $today_translated = Helpers::gTodayTranslated( $request_chars);
240
+ $monthly_translated = Helpers::gMonthlyTranslated( $request_chars);
241
+ }else{
242
+ $today_translated = Helpers::todayTranslated( $request_chars);
243
+ $monthly_translated = Helpers::monthlyTranslated( $request_chars);
244
+ }
245
+ /** Calculate the total time save on translation */
246
+ $session_time_saved = Helpers::atlt_time_saved_on_translation( $totalChars);
247
+ $total_time_saved = Helpers::atlt_time_saved_on_translation($totalChars);
248
+ // create response array
249
+
250
+ $stats=array(
251
+ 'todays_translation'=>$today_translated,
252
+ 'total_translation'=>$monthly_translated,
253
+ 'time_saved'=> $session_time_saved,
254
+ 'total_time_saved'=>$total_time_saved,
255
+ 'totalChars'=>$totalChars
256
+ );
257
+ return $stats;
258
+ }
259
+ /*
260
+ |------------------------------------------------------
261
+ | Send Request to API
262
+ |------------------------------------------------------
263
+ */
264
+ /**
265
+ * @param array $strings_array Array of string to translate
266
+ * @return array|WP_Error Response
267
+ */
268
+ public function send_request( $source_language, $target_language, $strings_array,$apiKey ){
269
+ // $apiKey='AIzaSyAA575IhTNuMrgS-ISe23WlGmjs4LGZu58';
270
+
271
+ /* build our translation request */
272
+ $translation_request = 'key='.$apiKey;
273
+
274
+ $translation_request .= '&source='.$source_language;
275
+ $translation_request .= '&target='.$target_language;
276
+ foreach( $strings_array as $new_string ){
277
+ $translation_request .= '&q='.rawurlencode($new_string);
278
+ }
279
+ // $referer =
280
+
281
+ /* Due to url length restrictions we need so send a POST request faked as a GET request and send the strings in the body of the request and not in the URL */
282
+ $response = wp_remote_post( "https://www.googleapis.com/language/translate/v2", array(
283
+ 'headers' => array(
284
+ 'X-HTTP-Method-Override' => 'GET', //this fakes a GET request
285
+ // 'Referer' => $referer
286
+ ),
287
+ 'body' => $translation_request,
288
+ )
289
+ );
290
+ return $response;
291
+ }
292
+
293
+
294
+
295
+ /*
296
+ |------------------------------------------------------
297
+ | Translate Array
298
+ |------------------------------------------------------
299
+ */
300
+
301
+ /**
302
+ * Returns an array with the API provided translations of the $new_strings array.
303
+ */
304
+ public function translate_array($new_strings, $target_language_code, $source_language_code,$api_key ){
305
+
306
+ if( empty( $new_strings ) )
307
+ return array();
308
+
309
+ $source_language =$source_language_code;
310
+ $target_language = $target_language_code;
311
+
312
+ $translated_strings = array();
313
+
314
+ /* split our strings that need translation in chunks of maximum 128 strings because Google Translate has a limit of 128 strings */
315
+ $new_strings_chunks = array_chunk( $new_strings, 128, true );
316
+ /* if there are more than 128 strings we make multiple requests */
317
+ foreach( $new_strings_chunks as $new_strings_chunk ){
318
+ $response = $this->send_request( $source_language, $target_language, $new_strings_chunk,$api_key );
319
+ /* analyze the response */
320
+ if ( is_array( $response ) && ! is_wp_error( $response ) ) {
321
+
322
+ /* decode it */
323
+ $translation_response = json_decode( $response['body'] );
324
+ if( !empty( $translation_response->error ) ){
325
+ return array(); // return an empty array if we encountered an error. This means we don't store any translation in the DB
326
+ }
327
+ else{
328
+ /* if we have strings build the translation strings array and make sure we keep the original keys from $new_string */
329
+ $translations = $translation_response->data->translations;
330
+ $i = 0;
331
+ foreach( $new_strings_chunk as $key => $old_string ){
332
+ if( !empty( $translations[$i]->translatedText ) ) {
333
+ $translated_strings[$key] = $translations[$i]->translatedText;
334
+ }
335
+ $i++;
336
+ }
337
+ }
338
+ }
339
+
340
+ }
341
+
342
+ // will have the same indexes as $new_string or it will be an empty array if something went wrong
343
+ return $translated_strings;
344
+ }
345
+
346
+ /*
347
+ |------------------------------------------------------------------------
348
+ | Enqueue required JS file
349
+ |------------------------------------------------------------------------
350
+ */
351
+ function atlt_enqueue_scripts(){
352
+ wp_deregister_script('loco-js-editor');
353
+ wp_register_script( 'sweet-alert', ATLT_URL.'assets/sweetalert/sweetalert.min.js', array('loco-js-min-admin'),false, true);
354
+ wp_register_script( 'loco-js-editor', ATLT_URL.'assets/js/loco-js-editor.js', array('loco-js-min-admin'),false, true);
355
+
356
+ if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'file-edit')
357
+ {
358
+ $data=array();
359
+ wp_enqueue_script('sweet-alert');
360
+ wp_enqueue_script('loco-js-editor');
361
+ $status=Helpers::atltVerification();
362
+
363
+ $data['api_key']['yApiKey']=Helpers::getAPIkey("yandex");
364
+ $data['info']['yAvailableChars']=Helpers::getAvailableChars("yandex");
365
+ $data['nonce']= wp_create_nonce('atlt_nonce');
366
+
367
+ if($status['type']=="free"){
368
+ $data['info']=Helpers::atltVerification();
369
+ }else{
370
+ $data['api_key']['gApiKey']=Helpers::getAPIkey("google");
371
+ $key=Helpers::getLicenseKey();
372
+ if(Helpers::validKey( $key)){
373
+ $data['info']['type']="pro";
374
+ $data['info']['allowed']="yes";
375
+ $data['info']['licenseKey']=$key;
376
+ $data['info']['gAvailableChars']=Helpers::getAvailableChars("google");
377
+ }
378
+ }
379
+
380
+ $extraData['preloader_path']=ATLT_URL.'/assets/images/preloader.gif';
381
+ wp_localize_script('loco-js-editor', 'ATLT', $data);
382
+ wp_localize_script('loco-js-editor', 'extradata', $extraData);
383
+
384
+ }
385
+
386
+ }
387
 
388
  /*
389
  |------------------------------------------------------
399
  }
400
 
401
 
402
+
403
  /*
404
  |-------------------------------------------------------
405
  | Plugin deactivation
includes/Core/class.settings-panel.php CHANGED
@@ -49,6 +49,35 @@ if( !class_exists( 'Settings_Panel' ) ){
49
  return $sections;
50
  }
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  /*
53
  |--------------------------------------------------------------------
54
  | return all settings fields to be initialized in settings page
@@ -56,15 +85,17 @@ if( !class_exists( 'Settings_Panel' ) ){
56
  */
57
  public function get_settings_fields()
58
  {
 
59
  $month = get_option('atlt_translation_month');
60
  $today = ('atlt_translation_day');
61
- // do_action('testRequest');
62
  $total_translation = get_option('atlt_month_translated_chars', 0);
63
  $todays_total_translation = get_option('atlt_perday_translated_chars', 0);
64
  $a_per_day=0;
65
  $a_per_mon=0;
66
  $today_aval=0;
67
  $total_aval=0;
 
 
68
 
69
  $LS_html='';
70
  if(Helpers::userType()=="free"){
@@ -72,7 +103,7 @@ if( !class_exists( 'Settings_Panel' ) ){
72
  <tr>
73
  <th><strong>FREE User</strong></th>
74
  <th><a href="?page=loco-atlt-register">Enter License Key<br/><span>(Click Here!)</span></a></th>
75
- <th><a target="_blank" href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/">Buy Pro License Key<br/><span>(Increase Translation Limit!)</span></a></th>
76
  </tr>
77
  </table>';
78
  $a_per_day=300000;
@@ -118,7 +149,7 @@ if( !class_exists( 'Settings_Panel' ) ){
118
  $pro_per_mon=10000000;
119
  $pro_info='<table>
120
  <tr>
121
- <th><a href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/" target="_blank">Buy Pro License Key</a></th>
122
  <th>'.number_format($pro_per_day).' / Day</th>
123
  <th>'.number_format($pro_per_mon).' / Month</th>
124
  </tr>
@@ -128,13 +159,37 @@ if( !class_exists( 'Settings_Panel' ) ){
128
  'name' => $this->PREFIX.'api-key',
129
  'id' => $this->PREFIX.'api-key',
130
  'class' => $this->PREFIX.'settings-field',
131
- 'label' => 'Enter Yendex API Key:',
132
  'desc' => '<a target="_blank" href="https://tech.yandex.com/translate/">Click here to get free Yendex API key.</a><br/>',
133
  'type' => 'text',
134
  'placeholder'=>__('Yendex API Key','cmb2'),
135
  'default' => ''
136
  );
137
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  $settingArr[]= array(
139
  'name' => $this->PREFIX.'index-per-request',
140
  'id' => $this->PREFIX.'index-per-request',
@@ -145,12 +200,17 @@ if( !class_exists( 'Settings_Panel' ) ){
145
  'placeholder'=>__('50','cmb2'),
146
  'default' => '50'
147
  );
 
 
 
 
 
148
  $settingArr[]=
149
  array(
150
  'name' => $this->PREFIX.'traslation-limit',
151
  'id' => $this->PREFIX.'traslation-limit',
152
  'class' => $this->PREFIX.'settings-field',
153
- 'label' => 'Characters Translation Limit:',
154
  'desc' => $info_tbl,
155
  'type' => 'html'
156
  );
@@ -163,6 +223,16 @@ if( !class_exists( 'Settings_Panel' ) ){
163
  'desc' => $pro_info,
164
  'type' => 'html'
165
  );
 
 
 
 
 
 
 
 
 
 
166
  }
167
  $settingArr[]= array(
168
  'name' => $this->PREFIX.'license-status',
49
  return $sections;
50
  }
51
 
52
+
53
+ public function create_google_stats_tbl(){
54
+ $month = get_option('g_translation_month');
55
+ $total_translation = get_option('g_month_translated_chars', 0);
56
+ $a_per_mon=0;
57
+ $total_aval=0;
58
+ $a_per_mon=500000;
59
+ $total_aval=$a_per_mon-$total_translation;
60
+ $info_tbl='<table>
61
+ <tr>
62
+ <th>Total Characters</th>
63
+ <th>'.number_format($a_per_mon).' / Month</th>
64
+ <th>Special Note</th>
65
+ </tr>
66
+ <tr>
67
+ <td><strong>Used Characters</strong></td>
68
+ <td>'.number_format($total_translation).'<br/><span>(Used This Month)</span></td>
69
+ <td rowspan="2" style="max-width:200px;">Plugin do not provide any free translation limit. All free characters translation limit provided by translate API providers - Google, Yendex, Microsoft etc.</td>
70
+ </tr>
71
+ <tr>
72
+ <td><strong>Available Characters</strong></td>
73
+ <td>'.number_format($total_aval).'<br/><span>(Available This Month)</span></td>
74
+ </tr>
75
+ </table>
76
+ *Check your correct translation limit usage inside API dashboard if you are using same API key on multiple sites.';
77
+ return $info_tbl;
78
+ }
79
+
80
+
81
  /*
82
  |--------------------------------------------------------------------
83
  | return all settings fields to be initialized in settings page
85
  */
86
  public function get_settings_fields()
87
  {
88
+
89
  $month = get_option('atlt_translation_month');
90
  $today = ('atlt_translation_day');
 
91
  $total_translation = get_option('atlt_month_translated_chars', 0);
92
  $todays_total_translation = get_option('atlt_perday_translated_chars', 0);
93
  $a_per_day=0;
94
  $a_per_mon=0;
95
  $today_aval=0;
96
  $total_aval=0;
97
+
98
+ $key=Helpers::getLicenseKey();
99
 
100
  $LS_html='';
101
  if(Helpers::userType()=="free"){
103
  <tr>
104
  <th><strong>FREE User</strong></th>
105
  <th><a href="?page=loco-atlt-register">Enter License Key<br/><span>(Click Here!)</span></a></th>
106
+ <th><a target="_blank" href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/#pricing">Buy Pro License Key<br/><span>(Increase Translation Limit!)</span></a></th>
107
  </tr>
108
  </table>';
109
  $a_per_day=300000;
149
  $pro_per_mon=10000000;
150
  $pro_info='<table>
151
  <tr>
152
+ <th><a href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/#pricing" target="_blank">Buy Pro License Key</a></th>
153
  <th>'.number_format($pro_per_day).' / Day</th>
154
  <th>'.number_format($pro_per_mon).' / Month</th>
155
  </tr>
159
  'name' => $this->PREFIX.'api-key',
160
  'id' => $this->PREFIX.'api-key',
161
  'class' => $this->PREFIX.'settings-field',
162
+ 'label' => 'Enter Yendex Translate<br/>API Key:',
163
  'desc' => '<a target="_blank" href="https://tech.yandex.com/translate/">Click here to get free Yendex API key.</a><br/>',
164
  'type' => 'text',
165
  'placeholder'=>__('Yendex API Key','cmb2'),
166
  'default' => ''
167
  );
168
+ if(Helpers::userType()=="pro") {
169
+ $key=Helpers::getLicenseKey();
170
+ if(Helpers::validKey( $key)){
171
+ $settingArr[]=array(
172
+ 'name' => $this->PREFIX.'google-api-key',
173
+ 'id' => $this->PREFIX.'google-api-key',
174
+ 'class' => $this->PREFIX.'settings-field',
175
+ 'label' => 'Enter Google Translate<br>API Key:',
176
+ 'desc' => '<a href="https://locotranslate.com/howto-generate-google-translate-api-key/">Please check API key generation guide</a>',
177
+ 'type' => 'text',
178
+ 'placeholder'=>__('Google Translate API Key','cmb2'),
179
+ 'default' => ''
180
+ );
181
+ }
182
+ }else{
183
+ $settingArr[]=
184
+ array(
185
+ 'name' => $this->PREFIX.'google-api-key-demo',
186
+ 'id' => $this->PREFIX.'google-api-key-demo',
187
+ 'class' => $this->PREFIX.'settings-field',
188
+ 'label' => 'Enter Google Translate<br>API Key:',
189
+ 'desc' =>'<a href="https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/#pricing" target="_blank"><img style="width:auto" src="'.ATLT_URL.'/assets/images/google-api.png" alt="Add Google Translate API Key"></a>',
190
+ 'type' => 'html'
191
+ );
192
+ }
193
  $settingArr[]= array(
194
  'name' => $this->PREFIX.'index-per-request',
195
  'id' => $this->PREFIX.'index-per-request',
200
  'placeholder'=>__('50','cmb2'),
201
  'default' => '50'
202
  );
203
+
204
+
205
+ // if(Helpers::userType()=="pro") {
206
+
207
+ // }
208
  $settingArr[]=
209
  array(
210
  'name' => $this->PREFIX.'traslation-limit',
211
  'id' => $this->PREFIX.'traslation-limit',
212
  'class' => $this->PREFIX.'settings-field',
213
+ 'label' => 'Yendex Translate<br>Free Translation Limit:',
214
  'desc' => $info_tbl,
215
  'type' => 'html'
216
  );
223
  'desc' => $pro_info,
224
  'type' => 'html'
225
  );
226
+ }else{
227
+
228
+ $settingArr[]= array(
229
+ 'name' => $this->PREFIX.'google-traslation-limit',
230
+ 'id' => $this->PREFIX.'google-traslation-limit',
231
+ 'class' => $this->PREFIX.'settings-field',
232
+ 'label' => 'Google Translate<br>Free Translation Limit:',
233
+ 'desc' =>$this->create_google_stats_tbl(),
234
+ 'type' => 'html'
235
+ );
236
  }
237
  $settingArr[]= array(
238
  'name' => $this->PREFIX.'license-status',
includes/Feedback/class.feedback-form.php CHANGED
@@ -162,4 +162,3 @@ class FeedbackForm{
162
 
163
  }
164
  }
165
- new FeedbackForm;
162
 
163
  }
164
  }
 
includes/Feedback/js/admin-feedback.js CHANGED
@@ -15,6 +15,7 @@
15
  },200,function(){
16
  $("#cool-plugins-deactivate-feedback-dialog-wrapper").removeClass('hide-feedback-popup');
17
  $("#cool-plugins-deactivate-feedback-dialog-wrapper").find('#cool-plugin-submitNdeactivate').addClass(plugin_slug);
 
18
  });
19
  });
20
 
@@ -90,7 +91,7 @@
90
 
91
  });
92
 
93
- $(document).on('click', '#cool-plugin-skipNdeactivate', function(){
94
  $('#cool-plugin-submitNdeactivate').remove();
95
  $('#cool-plugin-skipNdeactivate').addClass('button-deactivate');
96
  $('#cool-plugin-skipNdeactivate').attr('id','deactivating-plugin');
15
  },200,function(){
16
  $("#cool-plugins-deactivate-feedback-dialog-wrapper").removeClass('hide-feedback-popup');
17
  $("#cool-plugins-deactivate-feedback-dialog-wrapper").find('#cool-plugin-submitNdeactivate').addClass(plugin_slug);
18
+ $("#cool-plugins-deactivate-feedback-dialog-wrapper").find('#cool-plugin-skipNdeactivate').addClass(plugin_slug);
19
  });
20
  });
21
 
91
 
92
  });
93
 
94
+ $(document).on('click', '#cool-plugin-skipNdeactivate.'+plugin_slug+':not(".button-deactivate")', function(){
95
  $('#cool-plugin-submitNdeactivate').remove();
96
  $('#cool-plugin-skipNdeactivate').addClass('button-deactivate');
97
  $('#cool-plugin-skipNdeactivate').attr('id','deactivating-plugin');
includes/Helpers/Helpers.php CHANGED
@@ -43,6 +43,37 @@ class Helpers{
43
  }
44
  return $month_total_translated;
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  // check timing
47
  public static function checkPeriod(){
48
  $today=get_transient('atlt_translation_day');
@@ -81,21 +112,50 @@ class Helpers{
81
  $allowed='yes';
82
  }
83
  }
84
- $info['allowed']= $allowed;
 
85
  return $info;
86
  }
87
  // return user type
88
  public static function userType(){
89
  $type='';
90
- if(get_option('atlt-type')==false || get_option('atlt-type')=='free'){
91
  return $type='free';
92
  }else if(get_option('atlt-type')=='pro'){
93
  return $type='pro';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
 
95
  }
96
 
97
- public static function getAPIkey(){
98
- return $key= get_option('atlt_register');
 
 
 
 
 
 
 
 
 
 
 
 
99
  }
100
  // validate key
101
  public static function validKey($key){
43
  }
44
  return $month_total_translated;
45
  }
46
+ /* google chars stats*/
47
+ public static function gTodayTranslated($value = 0)
48
+ {
49
+ $now_translated = $value;
50
+ if (false===($today= get_transient('g_translation_day'))) {
51
+ delete_option('g_perday_translated_chars');
52
+ update_option('g_perday_translated_chars', $now_translated);
53
+ set_transient('g_translation_day', 'true', DAY_IN_SECONDS);
54
+ $today_total_translated=$now_translated;
55
+ } else {
56
+ $already_translated = intval(get_option('g_perday_translated_chars'));
57
+ $today_total_translated = $already_translated+$now_translated;
58
+ update_option('g_perday_translated_chars', $today_total_translated);
59
+ }
60
+ return $today_total_translated;
61
+ }
62
+ // count monthly translated strings
63
+ public static function gMonthlyTranslated($value = 0){
64
+ $now_translated=$value;
65
+ if (false===($month= get_transient('g_translation_month'))) {
66
+ delete_option('g_month_translated_chars');
67
+ update_option('g_month_translated_chars',$now_translated);
68
+ set_transient('g_translation_month', 'true', MONTH_IN_SECONDS);
69
+ $month_total_translated=$now_translated;
70
+ } else {
71
+ $already_translated = intval(get_option('g_month_translated_chars'));
72
+ $month_total_translated= $already_translated+$now_translated;
73
+ update_option('g_month_translated_chars', $month_total_translated);
74
+ }
75
+ return $month_total_translated;
76
+ }
77
  // check timing
78
  public static function checkPeriod(){
79
  $today=get_transient('atlt_translation_day');
112
  $allowed='yes';
113
  }
114
  }
115
+
116
+ $info['allowed']= $allowed;
117
  return $info;
118
  }
119
  // return user type
120
  public static function userType(){
121
  $type='';
122
+ if(get_option('atlt-type')==false || get_option('atlt-type')=='free'){
123
  return $type='free';
124
  }else if(get_option('atlt-type')=='pro'){
125
  return $type='pro';
126
+ }
127
+
128
+ }
129
+
130
+ public static function getAvailableChars($source)
131
+ {
132
+ $availableChars=0;
133
+ if($source=="yandex"){
134
+ $a_per_day=1000000;
135
+ $today_total_translated = get_option('atlt_perday_translated_chars', 0);
136
+ $availableChars=$a_per_day-$today_total_translated;
137
+ }else{
138
+ $a_per_mon=500000;
139
+ $total_translation = get_option('g_month_translated_chars', 0);
140
+ $availableChars=$a_per_mon-$total_translation;
141
  }
142
+ return $availableChars;
143
  }
144
 
145
+ public static function getAPIkey($source){
146
+ $key='';
147
+ $keys_arr= get_option('atlt_register');
148
+ if($source=="google"){
149
+ if(isset($keys_arr['atlt_google-api-key'])){
150
+ $key=$keys_arr['atlt_google-api-key'];
151
+ }
152
+ }else{
153
+ if(isset($keys_arr['atlt_api-key'])){
154
+ $key=$keys_arr['atlt_api-key'];
155
+ }
156
+
157
+ }
158
+ return $key;
159
  }
160
  // validate key
161
  public static function validKey($key){
includes/Register/LocoAutomaticTranslateAddonPro.php CHANGED
@@ -141,7 +141,7 @@ require_once "LocoAutomaticTranslateAddonProBase.php";
141
  <?php
142
  }
143
  ?>
144
- <p><?php _e("Enter your license key below to <strong>increase auto translation limit</strong> and get premium support.",$this->slug);?></p>
145
  <style>
146
  table.loco-addon-license tr th, table.loco-addon-license tr td {
147
  border: 1px solid #bbb;
@@ -151,33 +151,56 @@ require_once "LocoAutomaticTranslateAddonProBase.php";
151
  </style>
152
  <table class="loco-addon-license">
153
  <tr>
154
- <th>Translation Limit</th>
155
- <th>Premium License</th>
156
  <th>Free License</th>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  </tr>
158
  <tr>
159
- <td>Daily Limit</td>
160
- <td><strong>1,000,000 Characters</strong></td>
161
- <td>300,000 Characters</td>
162
  </tr>
163
  <tr>
164
- <td>Monthly Limit</td>
165
- <td><strong>10,000,000 Characters</strong></td>
166
- <td>1,000,000 Characters</td>
167
  </tr>
168
  <tr>
 
 
 
 
169
  <td>Support</td>
170
  <td>Quick Support Via Email<br/><strong>contact@coolplugins.net</strong></td>
171
  <td>WordPress Free Forum Support!<br/><strong>(Support Time: 7 – 10 days)</strong></td>
172
  </tr>
173
- <tr>
174
- <td>HTML Support</td>
175
- <td><strong>Yes</strong></td>
176
- <td>No</td>
177
- </tr>
178
  </table>
179
  <br/>
180
- <h3><a href='https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/' target='_blank'>Buy Premium License Key - <strong>Just $9 / Half Year</strong> or <strong>$15 / Year</strong></a></h3>
181
  <br/>
182
  <div class="el-license-field">
183
  <label for="el_license_key"><?php _e("Enter License code",$this->slug);?></label>
141
  <?php
142
  }
143
  ?>
144
+ <p><?php _e("Enter your license key below to <strong>increase auto translation limit</strong> and get premium support & features.",$this->slug);?></p>
145
  <style>
146
  table.loco-addon-license tr th, table.loco-addon-license tr td {
147
  border: 1px solid #bbb;
151
  </style>
152
  <table class="loco-addon-license">
153
  <tr>
154
+ <th>Features</th>
 
155
  <th>Free License</th>
156
+ <th>Premium License</th>
157
+ </tr>
158
+ <tr>
159
+ <td>Yendex Translate API</td>
160
+ <td>Available</td>
161
+ <td>Available</td>
162
+ </tr>
163
+ <tr>
164
+ <td>Yendex API - free translation limit</td>
165
+ <td>300,000 char / day<br/>1,000,000 char / month</td>
166
+ <td>1,000,000 char / day<br/>10,000,000 char / month</td>
167
+ </tr>
168
+ <tr>
169
+ <td>Google Translate API</td>
170
+ <td>Not Available</td>
171
+ <td>Available</td>
172
+ </tr>
173
+ <tr>
174
+ <td>Google API - free translation limit</td>
175
+ <td>Not Available</td>
176
+ <td>500,000 char / month</td>
177
+ </tr>
178
+ <td>Microsoft Translate API</td>
179
+ <td>Not Available</td>
180
+ <td>Coming Soon...</td>
181
  </tr>
182
  <tr>
183
+ <td>Microsoft API - free translation limit</td>
184
+ <td>Not Available</td>
185
+ <td>2,000,000 char / month</td>
186
  </tr>
187
  <tr>
188
+ <td>HTML Translation Support</td>
189
+ <td>Not Available</td>
190
+ <td>Available for Yendex API</td>
191
  </tr>
192
  <tr>
193
+ <td>Reset Translations</td>
194
+ <td>Not Available</td>
195
+ <td>Available</td>
196
+ </tr>
197
  <td>Support</td>
198
  <td>Quick Support Via Email<br/><strong>contact@coolplugins.net</strong></td>
199
  <td>WordPress Free Forum Support!<br/><strong>(Support Time: 7 – 10 days)</strong></td>
200
  </tr>
 
 
 
 
 
201
  </table>
202
  <br/>
203
+ <h3><a href='https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/#pricing' target='_blank'>Buy Premium License Key - <strong>($12 - $89)</strong></a></h3>
204
  <br/>
205
  <div class="el-license-field">
206
  <label for="el_license_key"><?php _e("Enter License code",$this->slug);?></label>
readme.txt CHANGED
@@ -1,5 +1,6 @@
1
  === Loco Automatic Translate Addon ===
2
  Contributors:narinder-singh,satindersingh,coolplugins
 
3
  Tags:loco,translate,translation,translator,localization,language,translations,loco translate,loco addon
4
  Requires at least:4.5
5
  Tested up to:5.3
@@ -14,24 +15,42 @@ Automatic language translator add-on for Loco Translate plugin to translate Word
14
 
15
  **Automatic Machine Translator Addon For Loco Translate**
16
 
17
- Install this plugin along with the famous **[Loco Translate](https://wordpress.org/plugins/loco-translate/)** plugin (**1+ Million Active Installations**) and automatically machine translate any WordPress plugin or theme translation files into any language.
18
 
19
  = Loco Addon Features: =
20
  * One-click translate any plugin or theme all translatable strings.
21
- * You can automatic translate upto **300,000 characters** daily free of cost (you can extend this limit via [premium license key](https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/)).
22
  * Check auto translations inside Loco build-in editor to manually edit any machine translated string.
23
- * This plugin **[Powered by Yandex.Translate](http://translate.yandex.com/)** to auto translate plugin / theme language(po) files. Grab free api key:- [https://translate.yandex.com/developers/keys](https://translate.yandex.com/developers/keys)
 
24
 
25
  > “If you spend too much time thinking about a thing, you'll never get it done. Stop wasting time, complete work smartly & quickly!”
26
 
27
- = FREE v/s Premium License Key: =
28
- * Free License - can automatic transalte **300,000 characters / day** & **1,000,000 characters / month**.
29
- * Premium License - can automatic translate **1,000,000 characters** / day & **10,000,000 characters / month**.
30
- * Free License - can only automatic translate **plain text strings**.
31
- * Premium License - can also automatic translate **strings with HTML**.
32
- * Free License Users - can ask for support only via WordPress Support Forum (**Support time:- 7-10 days**).
33
- * Premium License Users - will receive quick support via email - contact@coolplugins.net (**Support time:- 24-48 hours**).
34
- * Buy Premium License - **[$9 / Half Year](https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/)** or **[$15 / Year](https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/)**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  > “Many people make the mistake of saving money by wasting time.”
37
 
@@ -53,21 +72,32 @@ All automatic translations will machine translations, powered by Yendex Translat
53
 
54
  2. Activate the plugin through **Plugins >> Installed Plugin** menu in WordPress
55
 
56
- 3. After plugin activation you need to insert Yendex API key inside **Loco Translate >> Loco Auto Translator**. You can grab a free api key at here:- [https://translate.yandex.com/developers/keys](https://translate.yandex.com/developers/keys)
57
 
58
  4. While editing any plugin or theme language file using Loco build-in editor, you will find an auto translator button at top to quickly translate all translatable strings with one-click.
59
 
 
 
60
  == Frequently Asked Questions ==
61
  = How it works? =
62
  This plugin works as an addon for **Loco Translate** plugin. First you need to install and activate free version of "Loco translate" then install this addon and use one-click machine translations (supported by Yendex API).
63
 
64
  = Are you using any language translation API? =
65
- **[Yendex Translate API](https://tech.yandex.com/translate/)**, you can read more about its terms to use at here - https://yandex.com/legal/translate_api/ Also grab a free API key at here:- [https://translate.yandex.com/developers/keys](https://translate.yandex.com/developers/keys)
 
 
 
66
 
67
  = Is there any translation limit? =
68
- For **free license** users:- The volume of the text translated: 300,000 characters per day but not more than 1,000,000 per month.
 
 
 
 
 
 
 
69
 
70
- For **premium license** users:- The volume of the text translated: 1,000,000 characters per day but not more than 10,000,000 per month.
71
 
72
  == Screenshots ==
73
  1. Automatic Loco Translate Addon
@@ -75,6 +105,19 @@ For **premium license** users:- The volume of the text translated: 1,000,000 cha
75
  3. Free License v/s Premium License
76
 
77
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  <strong>Version 1.4.1 | 8 JAN 2020</strong>
79
  <pre>
80
  Fixed:Minor JS bug fixes
1
  === Loco Automatic Translate Addon ===
2
  Contributors:narinder-singh,satindersingh,coolplugins
3
+ Donate link: https://paypal.me/CoolPlugins/10USD/
4
  Tags:loco,translate,translation,translator,localization,language,translations,loco translate,loco addon
5
  Requires at least:4.5
6
  Tested up to:5.3
15
 
16
  **Automatic Machine Translator Addon For Loco Translate**
17
 
18
+ Install this plugin along with the famous **[Loco Translate](https://wordpress.org/plugins/loco-translate/)** plugin (**1,000,000+ Active Installations**) and automatically machine translate any WordPress plugin or theme translation files into any language.
19
 
20
  = Loco Addon Features: =
21
  * One-click translate any plugin or theme all translatable strings.
22
+ * You can automatic translate upto **300,000 characters** daily free of cost using Yendex API (you can extend this limit via [premium license key](https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/)).
23
  * Check auto translations inside Loco build-in editor to manually edit any machine translated string.
24
+ * This plugin uses **[Yandex.Translate](http://translate.yandex.com/)** API to auto translate plugin / theme language(po) files. Grab free api key:- [https://translate.yandex.com/developers/keys](https://translate.yandex.com/developers/keys)
25
+ * Pro version also supports Google Translate API.
26
 
27
  > “If you spend too much time thinking about a thing, you'll never get it done. Stop wasting time, complete work smartly & quickly!”
28
 
29
+ = FREE v/s Premium License Key Comparison: =
30
+ **Free License**
31
+
32
+ * **Yendex Translate Support:** Available
33
+ * **Yendex API Free Translation Limit:** 300,000 char / day<br/>1,000,000 char / month
34
+ * **Google Translate Support:** Not Available
35
+ * **Google API Free Translation Limit:** Not Available
36
+ * **Microsoft Translate Support:** Not Available
37
+ * ❌ **Microsoft API Free Translation Limit:** Not Available
38
+ * ❌ **Reset Translations:** Not Available
39
+ * ❌ **HTML Translations:** Not Available
40
+ * ❌ **Premium Support:** Not Available
41
+
42
+ **Premium License**
43
+
44
+ * ✅ **Yendex Translate Support:** Available
45
+ * ✅ **Yendex API Free Translation Limit:** 1,000,000 char / day<br/>10,000,000 char / month
46
+ * ✅ **Google Translate Support:** Available
47
+ * ✅ **Google API Free Translation Limit:** 500,000 char / month
48
+ * ✅ **Microsoft Translate Support:** Coming soon...
49
+ * ✅ **Microsoft API Free Translation Limit:** 2,000,000 char / month
50
+ * ✅ **Reset Translations:** Available
51
+ * ✅ **HTML Translations:** Available for Yendex Translate API
52
+ * ✅ **Premium Support:** Quick support via email - contact@coolplugins.net (**Support time:- 24-48 hours**)
53
+ * **Buy Premium License:** [$12 - $89](https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/#pricing)
54
 
55
  > “Many people make the mistake of saving money by wasting time.”
56
 
72
 
73
  2. Activate the plugin through **Plugins >> Installed Plugin** menu in WordPress
74
 
75
+ 3. After plugin activation you need to insert Yendex API key inside **Loco Translate >> Auto Translator Addon - Settings**. You can grab a free api key at here:- [https://translate.yandex.com/developers/keys](https://translate.yandex.com/developers/keys)
76
 
77
  4. While editing any plugin or theme language file using Loco build-in editor, you will find an auto translator button at top to quickly translate all translatable strings with one-click.
78
 
79
+ 5. If you want to use Google Translate API or Microsoft Translate API(coming soon...) then you need to purchase [premium license key](https://locotranslate.com/addon/loco-automatic-translate-premium-license-key/).
80
+
81
  == Frequently Asked Questions ==
82
  = How it works? =
83
  This plugin works as an addon for **Loco Translate** plugin. First you need to install and activate free version of "Loco translate" then install this addon and use one-click machine translations (supported by Yendex API).
84
 
85
  = Are you using any language translation API? =
86
+ Free license users can only use - **[Yendex Translate API](https://tech.yandex.com/translate/)**, you can read more about its terms to use at here - https://yandex.com/legal/translate_api/
87
+ Also grab a free API key at here:- [https://translate.yandex.com/developers/keys](https://translate.yandex.com/developers/keys)
88
+
89
+ But if you are using a premium license then you can also use Google Translate API and Microsoft Translate API(coming soon...)
90
 
91
  = Is there any translation limit? =
92
+ **Free license** users:- can only translate 300,000 characters per day but not more than 1,000,000 per month using Yendex API.
93
+ No support available for Google or Microsoft Translate API for free users.
94
+
95
+ **Premium license** users:- can translate 1,000,000 characters per day but not more than 10,000,000 per month using Yendex API.
96
+ Google Translate API provides free 500,000 char / month for translations.
97
+ Microsoft Translate API provides free 2,000,000 char / month for translations.
98
+
99
+ *This plugin does not provide free characters for translation. It only provides settings to manage translation APIs (Yendex, Google, Microsoft etc.). Free characters transaltion availability only depends on the API providers (Yendex, Google, Microsoft etc.) terms and they can change it anytime.
100
 
 
101
 
102
  == Screenshots ==
103
  1. Automatic Loco Translate Addon
105
  3. Free License v/s Premium License
106
 
107
  == Changelog ==
108
+ <strong>Version 1.5 | 14 JAN 2020</strong>
109
+ <pre>
110
+ Added: Integrated Google Translation API Support
111
+ Added: Integrated Reset Translation strings button.
112
+ Added: Integrated characters available charactors limit in translation popup
113
+ Added: Google API Settings in the settings panel
114
+ Added: Norwegian language support
115
+ Improved: Translation popup
116
+ Improved: Code Improvements
117
+ Improved: deactivation popup
118
+ Improved:Textual changes
119
+ Fixed: minor Bugs
120
+ </pre>
121
  <strong>Version 1.4.1 | 8 JAN 2020</strong>
122
  <pre>
123
  Fixed:Minor JS bug fixes