plugin updates

This commit is contained in:
Tony Volpe
2024-07-16 13:57:46 +00:00
parent 41f50eacc4
commit 8f93917880
1529 changed files with 259452 additions and 25451 deletions

View File

@@ -0,0 +1,447 @@
#jutranslation {
font-family: 'Open Sans', Helvetica, Arial, sans-serif !important;
}
#jutranslation a {
text-decoration: none;
}
/* START WordPress only
-----------------------------------------------*/
div#jutranslation.wordpress div.control-group table#jutranslations-languages.table.table-striped {
width: 80%;
text-align: left;
}
div#jutranslation.wordpress div.control-group table#jutranslations-languages tbody tr td {
padding: 0 10px;
}
div#jutranslation.wordpress div.control-group.edition table {
width: 90%;
}
@media only screen and (min-width: 1920px) {
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(1) {
width: 35%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(2) {
width: 22%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(3) {
width: 22%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(4) {
width: 22%;
}
div#jutranslation.wordpress tr.do_table_filters td input.do_table_filter_reference,
div#jutranslation.wordpress tr.do_table_line td input.do_table_reference,
div#jutranslation.wordpress tr.do_table_filters td input.do_table_filter_language,
div#jutranslation.wordpress tr.do_table_line td input.do_table_language,
div#jutranslation.wordpress div.control-group.edition td input.do_table_filter_override,
div#jutranslation.wordpress div.control-group.edition td input.do_table_override {
min-width: 310px;
}
}
@media only screen and (min-width: 1480px) and (max-width: 1920px) {
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(1) {
width: 25%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(2) {
width: 22%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(3) {
width: 22%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(4) {
width: 22%;
}
div#jutranslation.wordpress tr.do_table_filters td input.do_table_filter_reference,
div#jutranslation.wordpress tr.do_table_line td input.do_table_reference,
div#jutranslation.wordpress tr.do_table_filters td input.do_table_filter_language,
div#jutranslation.wordpress tr.do_table_line td input.do_table_language,
div#jutranslation.wordpress div.control-group.edition td input.do_table_filter_override,
div#jutranslation.wordpress div.control-group.edition td input.do_table_override {
min-width: 250px;
}
}
@media only screen and (min-width: 1230px) and (max-width: 1480px) {
div#jutranslation.wordpress div.control-group.edition table {
width: 100%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(1) {
width: 35%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(2) {
width: auto;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(3) {
width: auto;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(4) {
width: auto;
}
div#jutranslation.wordpress tr.do_table_filters td input.do_table_filter_reference,
div#jutranslation.wordpress tr.do_table_line td input.do_table_reference,
div#jutranslation.wordpress tr.do_table_filters td input.do_table_filter_language,
div#jutranslation.wordpress tr.do_table_line td input.do_table_language,
div#jutranslation.wordpress div.control-group.edition td input.do_table_filter_override,
div#jutranslation.wordpress div.control-group.edition td input.do_table_override {
min-width: 200px;
}
}
@media only screen and (min-width: 740px) and (max-width: 1230px) {
div#jutranslation.wordpress div.control-group.edition table {
width: 100%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(1) {
width: 35%;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(2) {
width: auto;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(3) {
width: auto;
}
#jutranslation.wordpress > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(4) {
width: auto;
}
div#jutranslation.wordpress tr.do_table_filters td input.do_table_filter_reference,
div#jutranslation.wordpress tr.do_table_line td input.do_table_reference,
div#jutranslation.wordpress tr.do_table_filters td input.do_table_filter_language,
div#jutranslation.wordpress tr.do_table_line td input.do_table_language,
div#jutranslation.wordpress div.control-group.edition td input.do_table_filter_override,
div#jutranslation.wordpress div.control-group.edition td input.do_table_override {
min-width: 120px;
}
}
/* END WordPress only
-----------------------------------------------*/
#jutranslations-languages div.original_content a.jutranslation-override,
#jutranslations-languages div.original_content span a {
height: auto;
width: auto;
border: none;
text-shadow: none;
box-shadow: none;
background-color: #1d6cb0;
border-radius: 2px;
padding: 2px 10px;
font-size: 12px;
text-transform: uppercase;
color: #fff;
line-height: 35px;
margin-right: 5px;
transition: all 0.2s ease-in;
}
#jutranslations-languages div.original_content a.jutranslation-override:hover,
#jutranslations-languages div.original_content a.jutranslation-override:active,
#jutranslations-languages div.original_content a.jutranslation-override:focus,
#jutranslations-languages div.original_content span a:hover,
#jutranslations-languages div.original_content span a:active,
#jutranslations-languages div.original_content span a:focus {
box-shadow: 1px 1px 12px #ccc;
text-decoration: none;
}
#jutranslations-languages div.original_content a.jutranslation-edition {
height: auto;
width: auto;
border: none;
text-shadow: none;
box-shadow: none;
background-color: #F9A541;
border-radius: 2px;
padding: 2px 10px;
font-size: 12px;
text-transform: uppercase;
color: #fff;
line-height: 35px;
margin-right: 5px;
transition: all 0.2s ease-in;
}
#jutranslations-languages div.original_content a.jutranslation-edition:hover,
#jutranslations-languages div.original_content a.jutranslation-edition:active,
#jutranslations-languages div.original_content a.jutranslation-edition:focus {
box-shadow: 1px 1px 12px #ccc;
text-decoration: none;
}
#jutranslations-languages div.original_content a.jutranslation-share {
height: auto;
width: auto;
border: none;
text-shadow: none;
box-shadow: none;
background-color: #7AC143;
border-radius: 2px;
padding: 2px 10px;
font-size: 12px;
text-transform: uppercase;
color: #fff;
line-height: 35px;
margin-right: 5px;
transition: all 0.2s ease-in;
}
#jutranslations-languages div.original_content a.jutranslation-share:hover,
#jutranslations-languages div.original_content a.jutranslation-share:active,
#jutranslations-languages div.original_content a.jutranslation-share:focus {
box-shadow: 1px 1px 12px #ccc;
text-decoration: none;
}
#jutranslations-languages thead tr th {
font-size: 14px;
text-transform: uppercase;
font-weight: bold;
line-height: 30px;
border-bottom: 1px solid #eee;
}
#jutranslations-languages tbody tr td.current_version,
#jutranslations-languages tbody tr td div.original_content {
font-weight: normal;
}
#jutranslations-languages tbody tr td {
font-weight: bold;
}
div#jutranslation.wordpress div.control-group p,
#jutranslation div.control-group div.controls p {
font-weight: bold;
text-transform: uppercase;
padding-left: 8px;
}
#jutranslations-languages tbody tr td {
vertical-align: middle;
}
#jutranslation .do_table_reference_copy,
#jutranslation .do_table_language_copy,
#jutranslation .do_table_override_copy {
font-size: 15px;
padding: 2px 2px 2px 5px;
vertical-align: middle;
}
#jutranslation > div.tab-description.alert.alert-info {
display: none;
}
#jutranslation .do_table_buttons {}
.jutranslation-share.just-added {
transition: all 1s ease-in;
color: #2167da;
font-weight: bold;
}
#jutranslation tr.do_table_heading td {
font-size: 14px;
text-transform: uppercase;
font-weight: bold;
line-height: 30px;
border-bottom: 1px solid #eee;
}
#jutranslation tr.do_table_filters {
height: 80px;
}
#jutranslation div.control-group.edition input {
border: 1px solid #ccc;
border-radius: 0;
box-shadow: none;
padding: 5px;
margin: 3px 0;
}
#jutranslation tr.do_table_filters > td:nth-child(1) {
vertical-align: middle;
}
#jutranslation tr.do_table_filters td input.do_table_filter_empty_reference,
#jutranslation tr.do_table_filters td input.do_table_filter_empty_language,
#jutranslation tr.do_table_filters td input.do_table_filter_empty_override {
margin: 0;
}
#jutranslation div.control-group.edition-message {
background-color: #2DAEF0;
padding: 15px;
color: #fff;
font-size: 15px;
}
#jutranslation #jutranslation_show_edition,
#jutranslation #jutranslation_cancel_edition {
margin: 10px 5px;
}
@media only screen and (min-width: 1680px) {
#jutranslation > div.control-group.edition > table > tbody > tr.do_table_heading > td:nth-child(1) {
min-width: 400px;
}
}
#jutranslation div.control-group.edition table tbody tr td textarea {
box-shadow: 1px 1px 12px #ccc;
border: 1px solid #888;
border-radius: 0;
transition: all 0.2s ease-in;
}
body > form > div:nth-child(3) > textarea {
border: 1px solid #ccc;
border-radius: 0;
box-shadow: none;
padding: 5px;
transition: all 0.2s ease-in;
}
#jutranslation div.control-group.edition tr td a i {
color: #444;
}
.wordpress .table-striped tbody > tr:nth-child(odd) > td,
.wordpress .table-striped tbody > tr:nth-child(odd) > th {
background-color: #f9f9f9;
}
.wordpress .dashicons-arrow-right-alt2 {
font-size: 15px;
vertical-align: sub;
}
a.disabled {
background-color: #c3c2c2 !important;
color: #333 !important;
cursor: default;
position: relative;
}
#jutranslation_toast {
position: fixed;
top: 40px;
right: 20px;
padding: 14px 15px;
background-color: #323232;
color: #FFFFFF;
font-size: 14px;
border-radius: 2px;
z-index: 1000;
}
.bootbox.modal {
opacity: 1;
top: 10%;
left: 50%;
position: fixed;
background-color: #ffffff;
overflow: hidden;
z-index: 1050;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
.modal-body {
position: relative;
overflow-y: auto;
max-height: 400px;
padding: 15px;
}
.bootbox-body {
font-size: 1.2em;
}
.bootbox-close-button {
display: none;
}
.modal-footer {
margin-bottom: 0;
text-align: right;
-webkit-border-radius: 0 0 6px 6px;
-moz-border-radius: 0 0 6px 6px;
border-radius: 0 0 6px 6px;
-webkit-box-shadow: inset 0 1px 0 #ffffff;
-moz-box-shadow: inset 0 1px 0 #ffffff;
box-shadow: inset 0 1px 0 #ffffff;
background-color: inherit;
border: 0;
padding: 5px 15px 15px;
position: relative;
display: block;
}
.bootbox-cancel, .bootbox-accept {
transition: box-shadow 0.2s cubic-bezier(0.4, 0, 1, 1), background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
outline: none;
cursor: pointer;
text-decoration: none;
text-align: center;
line-height: 36px;
vertical-align: middle;
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0;
overflow: hidden;
will-change: box-shadow;
background: 0 0;
border: none;
border-radius: 40px;
color: #656565;
position: relative;
height: 36px;
margin: 0 10px 0 0;
min-width: 64px;
padding: 0 16px;
display: inline-block;
width: unset;
}
.bootbox-cancel:hover, .bootbox-accept:hover {
-webkit-box-shadow: 0 2px 5px 0 #00000029, 0 2px 10px 0 #00000000;
-moz-box-shadow: 0 2px 5px 0 #00000029, 0 2px 10px 0 #00000000;
box-shadow: 0 2px 5px 0 #00000029, 0 2px 10px 0 #00000000;
}
.bootbox-accept {
background-color: #f88626;
border-color: #f88626;
color: #ffffff;
}
.modal-backdrop.fade {
display: none;
}
.modal-backdrop.fade.in {
display: block;
}
.modal-backdrop.show {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
min-height: 360px;
background: #000;
opacity: 0.7;
z-index: 998;
display: block;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><svg width='14px' height='14px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="uil-blank"><rect x="0" y="0" width="100" height="100" fill="none" class="bk"></rect><g transform="scale(0.55)"><circle cx="30" cy="150" r="30" fill="#7b92bd"><animate attributeName="opacity" from="0" to="1" dur="1s" begin="0" repeatCount="indefinite" keyTimes="0;0.5;1" values="0;1;1"></animate></circle><path d="M90,150h30c0-49.7-40.3-90-90-90v30C63.1,90,90,116.9,90,150z" fill="#545f85"><animate attributeName="opacity" from="0" to="1" dur="1s" begin="0.1" repeatCount="indefinite" keyTimes="0;0.5;1" values="0;1;1"></animate></path><path d="M150,150h30C180,67.2,112.8,0,30,0v30C96.3,30,150,83.7,150,150z" fill="#545f85"><animate attributeName="opacity" from="0" to="1" dur="1s" begin="0.2" repeatCount="indefinite" keyTimes="0;0.5;1" values="0;1;1"></animate></path></g></svg>

After

Width:  |  Height:  |  Size: 944 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,842 @@
var joomunited_url = 'https://www.joomunited.com/';
jQuery(document).ready(function($){
// Define jutranslation_ajax_action if doesn't exist
if (typeof jutranslation.ajax_action === 'undefined') {
jutranslation.ajax_action='';
}
//Load the available version from Joomunited
$.each(julanguages, function(){
var julanguage = this;
$.ajax({
url : joomunited_url + "index.php?option=com_jutranslation&task=translations.getTranslations",
type : 'POST',
data : julanguage,
success : function(data){
data = JSON.parse(data);
$('#jutranslations-languages tbody tr[data-slug="'+ julanguage.extension + '"]').each(function(){
var lang = $(this).data('lang');
var slug = $(this).data('slug');
//Is this language one of Joomunited has translated
var found = false;
//For each translation found add the version and an install btn
$.each(data.data,function(){
if(this.language === lang && this.extension === slug){
found = true;
//Add new version availability information
var html;
switch (versionCompare(julanguage.versions[this.language], this.extension_version, julanguage.revisions[this.language], this.revision)) {
case 1:
html = 'You already have the newer version<br/>The latest version on Joomunited is ' + this.extension_version + ' rev'+this.revision + '<a class="jutranslation-install" href="#" data-extension="' + this.extension + '" data-id="' + this.id + '">Install this version</a>';
break;
case 0:
html = 'You already have the latest version <a class="jutranslation-install" href="#" data-extension="' + this.extension + '" data-id="' + this.id + '">Reinstall</a>';
break;
case -1:
if (julanguage.versions[this.language]) {
install_update = 'Update';
} else {
install_update = 'Install';
}
html = 'There is a new version of language file available v' + this.extension_version + ' rev'+this.revision + '<a class="jutranslation-install" href="#" data-extension="' + this.extension + '" data-id="' + this.id + '">' + install_update + '</a>';
}
$('#jutranslations-languages tr[data-lang="'+ this.language + '"][data-slug="'+ julanguage.extension + '"] td .latest_version').html(html);
//Initialize all installation button
$('.jutranslation-install').unbind().bind('click',function(e){
e.preventDefault();
var $clicked_button = $(this);
var $parent_line = $clicked_button.parents('tr');
var slug = $clicked_button.parents('tr').data('slug');
//Get from Joomunited the translation
$.ajax({
url : joomunited_url + "index.php?option=com_jutranslation&task=translations.download",
type : 'POST',
data : {
extension : $clicked_button.data("extension"),
translation : $clicked_button.data("id")
},
success : function(result){
result = JSON.parse(result);
//Do not show language columns if it's en-US
var show_reference = true;
if(result.datas.language==='en-US'){
show_reference = false;
}
//auto save after download translation
var strings = {};
var modified = 0;
$.each(result.datas.strings,function(key,value){
strings[value.key] = value.language;
});
var ajax_data = {
action : jutranslation.ajax_action,
slug: slug,
strings : JSON.stringify(strings),
language : result.datas.language,
extension_version : result.datas.version,
revision : result.datas.revision,
modified : modified,
wp_nonce : jutranslation.token
};
ajax_data[jutranslation.token] = 1;
$.ajax({
type: 'POST',
url: jutranslation.base_url + 'task=jutranslation.saveStrings',
data: ajax_data,
success: function (result2) {
result2 = JSON.parse(result2);
if (result2.status === 'success') {
toast('Language is installed successfully');
$parent_line.find('.current_version').html(result.datas.version + ' rev' + result.datas.revision);
$parent_line.attr('data-version', result.datas.version);
if(modified){
$parent_line.find('.jutranslation-share').show().addClass('just-added');
}else{
$parent_line.find('.jutranslation-share').hide();
}
$parent_line.find('.latest_version').html('The language file has been updated');
$parent_line.find('.jutranslation-edition').removeClass('disabled');
} else {
alert('Error while updating language file');
}
}
});
//(end) auto save after download translation
}
});
});
}
});
//Check if a translation has been found on joomunited
var $line = $('#jutranslations-languages tr[data-lang="'+ lang + '"][data-slug="'+ julanguage.extension + '"]');
if(found===false){
$line.find('td .latest_version').html('No translation found');
}
if(!$line.attr('data-installed')){
$line.find('td .jutranslation-edition').addClass('disabled').attr({'data-toggle': 'tooltip','data-placement': 'top', 'data-tippy': 'Please install the latest available version first'});
} else {
$line.find('td .jutranslation-edition').attr({'data-toggle': 'tooltip','data-placement': 'top', 'data-tippy': 'Make sure you have the latest version installed before editing the original file'});
}
$line.find('td .jutranslation-override').attr({'data-toggle': 'tooltip','data-placement': 'top', 'data-tippy': 'Override the extension translation for your own needs, without modifying the original language file'});
tippy('.jutranslation-edition, .jutranslation-override', {
theme: 'wpmf',
animation: 'scale',
animateFill: false,
maxWidth: 300,
duration: 0,
arrow: true,
onShow(instance) {
instance.popper.hidden = false;
instance.setContent($(instance.reference).data('tippy'));
}
});
});
}
});
});
// Edit an installed version
$('.jutranslation-edition').click(function(e){
e.preventDefault();
var $clicked_button = $(this);
// Do nothing is disabled
if ($clicked_button.hasClass('disabled')) {
return;
}
var language = $clicked_button.parents('tr').data('lang');
var slug = $clicked_button.parents('tr').data('slug');
getStrings(language, slug, function(datas){
var table_option = {
language : language,
slug : slug,
confirm_button_action : function(e, $_content, close){
if(e!==undefined){
e.preventDefault();
}
if (typeof getAutoSave !== 'undefined') clearTimeout(getAutoSave);
var caller = this;
//Get the strings
var values = {};
var modified = 0;
$.each($_content.find('.do_table_line'),function(){
var value = $(this).find('.do_table_language').val();
if(value !== ''){
values[$(this).find('.do_table_constant').data('value')] = value;
}
//Check if something has been modified
if ($(this).find('.do_table_language').prop('defaultValue') !== $(this).find('.do_table_language').val()) {
modified = 1;
}
});
if (modified === 1) {
//Initialize ajax request datas
var ajax_data = {
action : jutranslation.ajax_action,
strings: JSON.stringify(values),
language: language,
slug: slug,
destination: 'edition',
modified: '1',
wp_nonce : jutranslation.token
};
ajax_data[jutranslation.token] = 1;
$.ajax({
type: 'POST',
url: jutranslation.base_url + 'task=jutranslation.saveStrings',
data: ajax_data,
success: function (result) {
result = JSON.parse(result);
if (result.status === 'success') {
//Close the edition
if(close) {
caller.cancel_button_action(e);
}
toast('Modifications saved');
$clicked_button.parents('tr').find('.jutranslation-share').show().addClass('just-added');
} else {
alert('Error while updating language file');
}
}
});
}else{
//Do nothing and close the edition
if(close) {
caller.cancel_button_action(e);
}
toast('Modifications saved');
}
},
columns : {
language : {
editable : true,
title : 'Language ' + language,
allow_copy : false
},
override : {
show : false
}
},
copy_destination : 'do_table_language',
after_init : function($_content){
//Add a message for translators before allowing to do anything
var message = '<p>This feature is for translators only, the content may be overwritten during the next language update. ' +
'If you only want to edit language strings for your own purpose please use the override feature.</p>' +
'<p><a href="#" id="jutranslation_show_edition" class="btn btn-lg btn-success button button-primary">OK got it, let me translate and share</a>' +
'<a href="#" id="jutranslation_cancel_edition" class="btn btn-lg btn-success button button-primary">Cancel</a></p>';
$_content.hide().after('<div class="control-group edition-message">' + message + '</div>');
//Click on ok edit button
$('#jutranslation_show_edition').click(function(){
$('#jutranslation .control-group.edition-message').remove();
$('#jutranslation .control-group.edition').show();
});
//Click on cancel edition button
$('#jutranslation_cancel_edition').click(function(){
$('#jutranslation .control-group.edition-message').remove();
$('#jutranslation .control-group.edition').remove();
$('#jutranslation .control-group').show();
});
}
};
//Generate the table
doTable(datas, table_option);
});
});
$('.jutranslation-override').click(function(e){
e.preventDefault();
var $clicked_button = $(this);
var language = $clicked_button.parents('tr').data('lang');
var slug = $clicked_button.parents('tr').data('slug');
//Do not show language columns if it's en-US
var show_language = true;
if(language==='en-US'){
show_language = false;
}
getStrings(language, slug, function(datas) {
var table_option = {
language : language,
confirm_button_action : function(e, $_content, close){
if(e!==undefined){
e.preventDefault();
}
if (typeof getAutoSave !== 'undefined') clearTimeout(getAutoSave);
var caller = this;
//Get the strings
var overrides = {};
$.each($_content.find('.do_table_line'),function(){
var value = $(this).find('.do_table_override').val();
if(value !== ''){
overrides[$(this).find('.do_table_constant').data('value')] = value;
}
});
//Initialize ajax request datas
var ajax_data = {
action : jutranslation.ajax_action,
strings : JSON.stringify(overrides),
language : this.language,
slug: slug,
destination : 'override',
wp_nonce : jutranslation.token
};
ajax_data[jutranslation.token] = 1;
$.ajax({
type : 'POST',
url : jutranslation.base_url + 'task=jutranslation.saveStrings',
data : ajax_data,
success : function(result){
result = JSON.parse(result);
if(result.status === 'success'){
$clicked_button.parents('tr').find('.jutranslation-override-count').html(Object.keys(overrides).length);
if(close) {
caller.cancel_button_action(e);
}
toast('Modifications saved');
}else{
alert('Error while updating language file');
}
}
});
},
columns : {
language : {
title : 'Language ' + language,
show : show_language
}
}
};
//Generate the table
doTable(datas, table_option);
});
});
//Share a translation to Joomunited
$('.jutranslation-share').click(function(e){
e.preventDefault();
if(typeof SqueezeBox !== 'undefined' ){
//Open Joomla lightbox
SqueezeBox.open(jutranslation.base_url + 'action=&task=jutranslation.showViewForm&wp_nonce=' + jutranslation.token + '&language=' + $(this).closest('tr').attr('data-lang'), {handler: 'iframe'});
}else{
//Open Wordpress lightbox
tb_show('Share with Joomunited',jutranslation.base_url + 'action=' + jutranslation.ajax_action + '&task=jutranslation.showViewForm&wp_nonce=' + jutranslation.token + '&slug=' + $(this).closest('tr').attr('data-slug') + '&language=' + $(this).closest('tr').attr('data-lang') + '&TB_iframe=true');
}
});
var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent';
var eventer = window[eventMethod];
var messageEvent = (eventMethod == 'attachEvent') ? 'onmessage' : 'message';
// Listen to message from jutranslation window
eventer(messageEvent, function (e) {
var res = e.data;
if(typeof res != 'undefined' && typeof res.type != 'undefined' && res.type === 'translation_login'){
$.ajax({
url : jutranslation.base_url + 'task=jutranslation.saveJuToken',
type: 'POST',
data: {
action : jutranslation.ajax_action,
token: res.token,
wp_nonce: jutranslation.token
},
success: function () {
}
});
}
}, false);
function doTable(datas, options) {
// DOM element containing the generated content
var $_content;
var default_options = {
language : null,
slug : null,
confirm_button_label: 'Save and close',
save_button_label: 'Save',
cancel_button_label: 'Cancel',
cancel_button_action: function (e) {
if(e!==undefined){
e.preventDefault();
}
$('#jutranslation .control-group.edition').remove();
$('#jutranslation .control-group').show();
},
confirm_button_action : function (e) {
if(e!==undefined){
e.preventDefault();
}
if (typeof getAutoSave !== 'undefined') clearTimeout(getAutoSave);
if (typeof getAutoSave !== "undefined") {
clearTimeout(getAutoSave);
}
options.cancel_button_action(e);
},
after_init : function () {},
columns : {
constant : {
show : true,
title : 'Constant',
allow_copy : false
},
reference : {
show : true,
editable : false,
title : 'Reference en-US',
allow_copy : true
},
language : {
show : true,
editable : false,
title : 'Language',
allow_copy : true
},
override : {
show : true,
editable : true,
title : 'Override',
allow_copy : false
}
},
copy_destination : 'do_table_override'
};
// Initialize options variable if not already
if(options === undefined){
var options = {};
}
// Merge the default options to the passed ones
options = $.extend(true, {}, default_options, options);
//Add a button to save
var content = '';
content += '<p class="do_table_buttons">';
content += ' <a href="#" class="do_table_confirm btn btn-primary button button-primary">' + options.confirm_button_label + '</a>';
content += ' <a href="#" class="do_table_save btn btn-primary button button-primary">' + options.save_button_label + '</a>';
content += ' <a href="#" class="do_table_cancel btn btn-primary button">' + options.cancel_button_label + '</a>';
content += '</p>';
//Create the table of strings
content += '<table>';
//Add columns names
content += '<tr class="do_table_heading">' +
' <td' + ( options.columns.constant.show?'':' class="hidden"' ) + '>' + options.columns.constant.title + '</td>' +
' <td' + ( options.columns.reference.show?'':' class="hidden"' ) + '>' + options.columns.reference.title + '</td>' +
' <td' + ( options.columns.language.show?'':' class="hidden"' ) + '>' + options.columns.language.title + '</td>' +
' <td' + ( options.columns.override.show?'':' class="hidden"' ) + '>' + options.columns.override.title + '</td>' +
'</tr>';
//Add filter inputs
content += '<tr class="do_table_filters">' +
' <td' + ( options.columns.constant.show?'':' class="hidden"' ) + '><input class="do_table_filter_constant" type="text" placeholder="Filter by constant"/></td>' +
' <td' + ( options.columns.reference.show?'':' class="hidden"' ) + '><input class="do_table_filter_reference" type="text" placeholder="Filter by reference"/><br/>Show only empty <input type="checkbox" class="do_table_filter_empty_reference"/><br/>Show only not empty <input type="checkbox" class="do_table_filter_not_empty_reference"/></td>' +
' <td' + ( options.columns.language.show?'':' class="hidden"' ) + '><input class="do_table_filter_language" type="text" placeholder="Filter by language"/><br/>Show only empty <input type="checkbox" class="do_table_filter_empty_language"/><br/>Show only not empty <input type="checkbox" class="do_table_filter_not_empty_language"/></td>' +
' <td' + ( options.columns.override.show?'':' class="hidden"' ) + '><input class="do_table_filter_override" type="text" placeholder="Filter by override"/><br/>Show only empty <input type="checkbox" class="do_table_filter_empty_override"/><br/>Show only not empty <input type="checkbox" class="do_table_filter_not_empty_override"/></td>' +
'</tr>';
$.each(datas, function(key,value){
content += '' +
'<tr class="do_table_line">' +
' <td' + ( options.columns.constant.show?'':' class="hidden"' ) + '>' +
' <span class="do_table_constant" data-value="' + htmlEntities(value.key) + '">' + htmlEntities(value.key) + '</span>' +
' </td>' +
' <td' + ( options.columns.reference.show?'':' class="hidden"' ) + '>' +
' <input type="text" class="do_table_reference" value="' + htmlEntities(value.reference) + '" ' + ( options.columns.reference.editable?'':'readonly="readonly"' ) + ' />' + (options.columns.reference.allow_copy?'<a title="copy" href="#" class="do_table_copy_reference"><i class="icon-arrow-right-4 dashicons dashicons-arrow-right-alt2"></i></a>':'') +
' </td>' +
' <td' + ( options.columns.language.show?'':' class="hidden"' ) + '>' +
' <input type="text" class="do_table_language" value="' + htmlEntities(value.language) + '" ' + ( options.columns.language.editable?'':'readonly="readonly"' ) + ' >' + (options.columns.language.allow_copy?'<a title="copy" href="#" class="do_table_copy_language"><i class="icon-arrow-right-4 dashicons dashicons-arrow-right-alt2"></i></a>':'') +
' </td>' +
' <td' + ( options.columns.override.show?'':' class="hidden"' ) + '>' +
' <input type="text" class="do_table_override" value="' + htmlEntities(value.override) + '" ' + ( options.columns.override.editable?'':'readonly="readonly"' ) + ' >' + (options.columns.override.allow_copy?'<a title="copy" href="#" class="do_table_copy_override"><i class="icon-arrow-right-4 dashicons dashicons-arrow-right-alt2"></i></a>':'') +
' </td>' +
'</tr>';
});
content += '</table>';
$('#jutranslation .control-group').after('<div class="control-group edition">' + content + '</div>');
$_content = $('#jutranslation .control-group.edition');
// Enable filtering
$_content.find('[class^="do_table_filter_"]').on("change keyup paste", function(){
//Texts filters
var filter_constant = $_content.find('.do_table_filter_constant').val();
var filter_reference = $_content.find('.do_table_filter_reference').val();
var filter_language = $_content.find('.do_table_filter_language').val();
var filter_override = $_content.find('.do_table_filter_override').val();
// Do not allow to check both filters
switch (1==1) {
case $(this).hasClass('do_table_filter_empty_reference') && $(this).is(':checked'):
$_content.find('.do_table_filter_not_empty_reference').attr('checked',null);
break;
case $(this).hasClass('do_table_filter_empty_language') && $(this).is(':checked'):
$_content.find('.do_table_filter_not_empty_language').attr('checked',null);
break;
case $(this).hasClass('do_table_filter_empty_override') && $(this).is(':checked'):
$_content.find('.do_table_filter_not_empty_override').attr('checked',null);
break;
case $(this).hasClass('do_table_filter_not_empty_reference') && $(this).is(':checked'):
$_content.find('.do_table_filter_empty_reference').attr('checked',null);
break;
case $(this).hasClass('do_table_filter_not_empty_language') && $(this).is(':checked'):
$_content.find('.do_table_filter_empty_language').attr('checked',null);
break;
case $(this).hasClass('do_table_filter_not_empty_override') && $(this).is(':checked'):
$_content.find('.do_table_filter_empty_override').attr('checked',null);
break;
}
if($(this).is('[class^="do_table_filter_empty"]')){
} else if ($(this).is('[class^="do_table_filter_not_empty"]')) {
}
$_content.find('.do_table_filter_not_empty_reference');
//Empty filters
var filter_empty_reference = $_content.find('.do_table_filter_empty_reference').is(":checked");
var filter_empty_language = $_content.find('.do_table_filter_empty_language').is(":checked");
var filter_empty_override = $_content.find('.do_table_filter_empty_override').is(":checked");
var filter_not_empty_reference = $_content.find('.do_table_filter_not_empty_reference').is(":checked");
var filter_not_empty_language = $_content.find('.do_table_filter_not_empty_language').is(":checked");
var filter_not_empty_override = $_content.find('.do_table_filter_not_empty_override').is(":checked");
// Show all rows
$_content.find('tr.do_table_line').show();
// Filtering is active
if(filter_constant !== '' || filter_reference !== '' || filter_language !== '' || filter_override != '' || filter_empty_reference!==false || filter_empty_language !== false || filter_empty_override !== false || filter_not_empty_reference!==false || filter_not_empty_language !== false || filter_not_empty_override !== false){
// Show only rows matching search
$_content.find('.do_table_line').filter(function(){
//Filter by empty reference
if(filter_empty_reference && $(this).find('.do_table_reference').val() !== ''){
return true;
}
//Filter by empty language
if(filter_empty_language && $(this).find('.do_table_language').val() !== ''){
return true;
}
//Filter by empty override
if(filter_empty_override && $(this).find('.do_table_override').val() !== ''){
return true;
}
//Filter by not empty reference
if(filter_not_empty_reference && $(this).find('.do_table_reference').val() === ''){
return true;
}
//Filter by empty language
if(filter_not_empty_language && $(this).find('.do_table_language').val() === ''){
return true;
}
//Filter by empty override
if(filter_not_empty_override && $(this).find('.do_table_override').val() === ''){
return true;
}
//Filter by constant
if(filter_constant !== ''){
var regex = new RegExp(escapeRegExp(filter_constant), 'i');
if(!regex.test($(this).find('.do_table_constant').data('value'))){
return true;
}
}
//Filter by reference
if(filter_reference !== ''){
var regex = new RegExp(escapeRegExp(filter_reference), 'i');
if(!regex.test($(this).find('.do_table_reference').val())){
return true;
}
}
//Filter by current language
if(filter_language !== ''){
var regex = new RegExp(escapeRegExp(filter_language), 'i');
if(!regex.test($(this).find('.do_table_language').val())){
return true;
}
}
//Filter by override
if(filter_override !== ''){
var regex = new RegExp(escapeRegExp(filter_override), 'i');
if(!regex.test($(this).find('.do_table_override').val())){
return true;
}
}
return false;
}).hide();
return;
}
});
var getAutoSave;
var autoSave = () => {
clearTimeout(getAutoSave);
getAutoSave = setTimeout(function () {
bootbox.confirm(jutranslationCmd.warning_auto_save, function (result) {
clearTimeout(getAutoSave);
if (result) {
options.confirm_button_action(undefined, $_content, false);
}
});
}, 300000)
};
// Enable copy from one input to another
$_content.find('[class^="do_table_copy_"]').click(function(e){
e.preventDefault();
//Get the value from clicked element
if($(this).hasClass('do_table_copy_reference')){
var value = $(this).parents('tr').find('.do_table_reference').val();
}else if($(this).hasClass('do_table_copy_language')){
var value = $(this).parents('tr').find('.do_table_language').val();
}else if($(this).hasClass('do_table_copy_override')){
var value = $(this).parents('tr').find('.do_table_override').val();
}
//Copy value to destination input
autoSave();
$(this).parents('tr').find('.'+options.copy_destination).val(value);
});
//Save and close
$_content.find('.do_table_confirm').click(function(e){
clearTimeout(getAutoSave);
options.confirm_button_action(e, $_content, true);
});
//Confirm the current action
$_content.find('.do_table_save').click(function(e){
clearTimeout(getAutoSave);
options.confirm_button_action(e, $_content, false);
});
//Cancel the current action
$_content.find('.do_table_cancel').click(function(e, $_content){
clearTimeout(getAutoSave);
options.cancel_button_action(e);
});
$('#jutranslation .control-group').not('.edition').hide();
$_content.find('.do_table_line input').focus(function(){
var $this = $(this);
var $this_line = $this.parents('tr');
//Do nothing if already hidden
if($(this).is(":hidden")){
return;
}
//Remove all old textarea
$this_line.find('textarea').remove();
$this_line.find('input').each(function(){
// Get the input value
var val = $(this).val();
// Add a textarea after the inpu
$('<textarea style="width:' + $(this).css('width') + '" ' + ($(this).is('[readonly="readonly"]')?'readonly="readonly"':'') + '>' + htmlEntities(val) + '</textarea>').insertAfter(this);
// Hide the input
$(this).hide();
});
// Remove textarea on focus out
$this.siblings('textarea').focus().focusout(function(){
$this.val(($(this).val()));
autoSave();
$this_line.find('input').show();
$this_line.find('textarea').hide(); //Hide instead of remove to avoid html5fallback.js error
});
});
options.after_init.call(options, $_content);
}
function getStrings(language, slug, done_function) {
var strings = {};
$.ajax({
type: 'POST',
url: jutranslation.base_url + 'task=jutranslation.getTranslation',
data: {
action : jutranslation.ajax_action,
language: language,
slug: slug,
wp_nonce : jutranslation.token
},
success: function (result) {
result = JSON.parse(result);
if (result.status === 'success') {
done_function(result.datas.strings);
} else {
alert('Error while loading strings');
}
}
});
}
/**
* Escape a string to allow using it literally in a regex
* @param string
* @return string escaped
*/
function escapeRegExp(string) {
return string.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
/**
* Secure a string to use it in html content
* @param string to espace
* @return {string} escaped string
*/
function htmlEntities(string){
return String(string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
/**
* Compare two version numbers and their revisions
* @param version1
* @param version2
* @param revision_version1
* @param revision_version2
* @return int 1 if version1>version2, -1 if version1<version2 , 0 if version1==version2
*/
function versionCompare(version1, version2, revision_version1, revision_version2){
if(version1==='') {
version1 = '0';
}
if(version2==='') {
version2 = '0';
}
version1 = version1.split('.');
version2 = version2.split('.');
if(typeof revision_version1 === 'undefined'){
revision_version1 = 0;
}
if(typeof revision_version2 === 'undefined'){
revision_version2 = 0;
}
for(var ij=0; ij < version1.length; ij++ ) {
if(typeof version2[ij] === 'undefined'){
//Version 1 has the longest version
for(var ik=ij; ik < version1.length; ik++){
//Check if it has another thing as 0 trailing
if(parseInt(version[1]) > 0){
//Latest version is upper
return 1;
}
}
//End only with 0 version numbers, it's equal
if(revision_version1 > revision_version2){
return 1;
} else if(revision_version1 < revision_version2){
return -1;
}
return 0;
} else {
if(parseInt(version1[ij]) > parseInt(version2[ij])) {
return 1;
} else if(parseInt(version1[ij]) < parseInt(version2[ij])) {
return -1;
}
}
}
//Version 2 has the longest version or is equal
for(var ik=ij; ik < version2.length; ik++){
//Check if it has another thing as 0 trailing
if(parseInt(version2[ik]) > 0){
//Latest version is upper
return -1;
}
}
//End only with 0 version numbers, it's equal
if(revision_version1 > revision_version2){
return 1;
} else if(revision_version1 < revision_version2){
return -1;
}
return 0;
}
function toast(text) {
$('#jutranslation_toast').remove();
$('body').append('<div id="jutranslation_toast">' + text + '</div>');
setTimeout(function() {
$('#jutranslation_toast').remove();
}, 2000);
}
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,778 @@
<?php
/**
* Jutranslation main file
*
* @package Joomunited\WPMediaFolder\Jutranslation
*/
namespace Joomunited\WPMediaFolder\Jutranslation;
/**
* Class Jutranslation
*/
class Jutranslation
{
/**
* Extension slug
*
* @var string $extension_slug
*/
public static $extension_slug;
/**
* Extension real name
*
* @var string $extension_name
*/
public static $extension_name;
/**
* Extension text domain
*
* @var string $text_domain
*/
public static $text_domain;
/**
* Language file
*
* @var string $language_file
*/
public static $language_file;
/**
* The main plugin php file
*
* @var string $main_plugin_file
*/
public static $main_plugin_file;
/**
* Initialize Jutranslation
*
* @param string $main_plugin_file Main plugin file
* @param string $extension_slug Extension slug
* @param string $extension_name Extension name
* @param string $text_domain Text domain
* @param string $language_file Language file
*
* @return void
*/
public static function init($main_plugin_file, $extension_slug, $extension_name, $text_domain, $language_file)
{
self::$main_plugin_file = $main_plugin_file;
self::$extension_slug = $extension_slug;
self::$extension_name = $extension_name;
self::$text_domain = $text_domain;
self::$language_file = plugin_dir_path(self::$main_plugin_file) . $language_file;
//Load override file
add_action('load_textdomain', array(__CLASS__, 'overrideLanguage'), 1, 2);
add_filter(self::$extension_slug . '_get_addons', function ($addons) {
$addon = new \stdClass();
$addon->main_plugin_file = Jutranslation::$main_plugin_file;
$addon->extension_name = Jutranslation::$extension_name;
$addon->extension_slug = Jutranslation::$extension_slug;
$addon->text_domain = Jutranslation::$text_domain;
$addon->language_file = Jutranslation::$language_file;
$addons[$addon->extension_slug] = $addon;
return $addons;
});
//Only need Jutranslation on admin side
if (!is_admin()) {
return;
}
// Check if the current user
add_action('admin_init', function () {
if (current_user_can('manage_options')) {
//Initialize needed ajax mehtods
add_action(
'wp_ajax_jutranslation_' . Jutranslation::$extension_slug,
array(__CLASS__, 'dispatchQuery')
);
}
});
}
/**
* Ajax queries dispatcher
*
* @return void
*/
public static function dispatchQuery()
{
check_ajax_referer('jutranslation', 'wp_nonce');
if (!isset($_REQUEST['task'])) {
die;
}
switch ($_REQUEST['task']) {
case 'jutranslation.saveJuToken':
self::saveJuToken();
break;
case 'jutranslation.saveStrings':
self::saveStrings();
break;
case 'jutranslation.getTranslation':
self::getTranslation();
break;
case 'jutranslation.showViewForm':
self::showViewForm();
break;
}
}
/**
* Return the main html content for jutranslation
*
* @return void
*/
public static function getInput()
{
echo '<div id="jutranslation" class="wordpress">';
echo '<div class="control-group">';
//Declare all js and css to include
wp_enqueue_script(
'jutranslation-tippy-core',
plugin_dir_url(self::$main_plugin_file) . 'jutranslation/assets/js/tippy/tippy-core.js',
array('jquery')
);
wp_enqueue_script(
'jutranslation-tippy',
plugin_dir_url(self::$main_plugin_file) . 'jutranslation/assets/js/tippy/tippy.js',
array('jquery')
);
wp_enqueue_style(
'jutranslation-style-tippy',
plugin_dir_url(self::$main_plugin_file) . 'jutranslation/assets/js/tippy/tippy.css'
);
wp_enqueue_script('jutranslation-bootstrap', plugin_dir_url(self::$main_plugin_file) . 'jutranslation/assets/js/bootstrap.min.js');
wp_enqueue_script('jutranslation-bootbox', plugin_dir_url(self::$main_plugin_file) . 'jutranslation/assets/js/bootbox.js');
wp_localize_script('jutranslation-bootbox', 'jutranslationCmd', array(
'Delete' => 'Delete',
'Edit' => 'Edit',
'CANCEL' => 'Cancel',
'OK' => 'Ok',
'CONFIRM' => 'Confirm',
'Save' => 'Save',
'warning_auto_save' => 'You have unsaved translation changes, save it!',
));
wp_enqueue_script('jutranslation', plugin_dir_url(self::$main_plugin_file) . 'jutranslation/assets/js/jutranslation.js');
wp_enqueue_style('jutranslation', plugin_dir_url(self::$main_plugin_file) . 'jutranslation/assets/css/jutranslation.css');
wp_localize_script('jutranslation', 'jutranslation', array(
'token' => wp_create_nonce('jutranslation'),
'ajax_action' => 'jutranslation_' . self::$extension_slug ,
'base_url' => admin_url('admin-ajax.php').'?'
));
add_thickbox();
//Get all installed languages
$installed_languages = array();
foreach (wp_get_installed_translations('core') as $type) {
foreach ($type as $lang => $value) {
$lang = str_replace('_', '-', $lang);
$installed_languages[] = $lang;
}
}
//Add Polylang languages
if (function_exists('pll_languages_list')) {
foreach (pll_languages_list(array('fields' => 'locale')) as $pll_language) {
$lang = str_replace('_', '-', $pll_language);
$installed_languages[] = $lang;
}
}
//Add WPML languages
if (!function_exists('pll_languages_list') && function_exists('icl_get_languages')) {
foreach (icl_get_languages() as $wpml_language) {
$lang = str_replace('_', '-', $wpml_language['default_locale']);
$installed_languages[] = $lang;
}
}
//Add default en-US language
if (!isset($installed_languages['en-US'])) {
$installed_languages = array_merge(array('en-US'), $installed_languages);
}
$installed_languages = array_unique($installed_languages);
//Get addons
$addons = apply_filters(self::$extension_slug . '_get_addons', array());
ksort($addons);
$languages = array();
foreach ($installed_languages as $installed_language) {
foreach ($addons as $addon) {
$langObject = new \stdClass();
$langObject->extension = $addon;
$langObject->installed = false;
$langObject->extension_version = '';
$langObject->language_version = '';
$langObject->revision = '1';
$langObject->languageCode = $installed_language;
$langObject->modified = '0';
$languages[] = $langObject;
}
}
//Check if language is installed
foreach ($languages as &$language) {
if (str_replace('-', '_', $language->languageCode) === 'en_US') {
$file = $language->extension->language_file;
} else {
$file = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'plugins';
$file .= DIRECTORY_SEPARATOR . $language->extension->text_domain . '-';
$file .= str_replace('-', '_', $language->languageCode) . '.mo';
}
if (file_exists($file)) {
$language->installed = true;
// Load language file
$mo = new \MO();
$mo->import_from_file($file);
//Assign it to the language
if (isset($mo->headers['Version'])) {
$language->language_version = $mo->headers['Version'];
}
if (isset($mo->headers['Revision'])) {
$language->revision = $mo->headers['Revision'];
}
if (isset($mo->headers['Modified'])) {
$language->modified = $mo->headers['Modified'];
} else {
//The header has not been found, so the language file has not been add by jutranslation
$language->modified = '1';
}
}
//Check for language override
$language->overrided = 0;
$file = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'plugins';
$file .= DIRECTORY_SEPARATOR . $language->extension->text_domain . '-';
$file .= str_replace('-', '_', $language->languageCode) . '.override.mo';
if (file_exists($file)) {
// Load language file
$mo = new \MO();
$mo->import_from_file($file);
$language->overrided = 0;
//Check if a translation exists for each entry
foreach ($mo->entries as $entry) {
if (is_array($entry->translations) || $entry->translations instanceof Countable) {
if (count($entry->translations)) {
$language->overrided++;
}
}
}
}
}
unset($language);
//Show documentation link
echo '<p>You can refer to the
<a href="https://www.joomunited.com/documentation/ju-translation-translate-wordpress-and-joomla-extensions"
target="_blank">documentation page on Joomunited</a> for more informations about extension translation</p>';
echo '<p>';
foreach ($addons as $addon) {
//Get extension version
$plugin_data = get_plugin_data($addon->main_plugin_file);
$extension_version = $plugin_data['Version'];
echo 'Current ' . esc_html($addon->extension_name) . ' version is ' . esc_html($extension_version) . '<br/>';
}
echo '</p>';
$julanguages = array();
echo '<table id="jutranslations-languages" class="table table-striped" >
<thead >
<tr>
<th ' . (count($addons) > 1 ? '' : 'style="display:none;"') . '>Plugin</th>
<th>Language</th>
<th>Current version</th>
<th>Latest available version</th>
</tr>
</thead>
<tbody>';
foreach ($languages as $language) {
echo '<tr data-slug="' . esc_attr($language->extension->extension_slug) . '" data-lang="' . esc_attr($language->languageCode) .
'" data-installed="' . esc_attr($language->installed) . '" data-version="' . esc_attr($language->extension_version) . '">';
echo '<td ' . (count($addons) > 1 ? '' : 'style="display:none;"') . '>' .
esc_html($language->extension->extension_name) . '</td>';
echo '<td>' . esc_html($language->languageCode) . '</td>';
echo '<td class="current_version">' .
esc_html($language->installed ? ($language->language_version ? ($language->revision ? esc_html($language->language_version .
' rev' . $language->revision) : $language->language_version . ' rev' .
$language->revision) : 'Unknown') : 'Not installed') . '</td>';
echo '<td><div class="original_content">';
echo '<span class="latest_version"><img src="' .
esc_attr(plugin_dir_url(self::$main_plugin_file) . 'jutranslation/assets/images/radio.svg') .
'" alt="loading"/></span><br/>';
echo '<div style="display: inline-block; position: relative"><a class="jutranslation-override" href="#" data-language="' . esc_attr($language->languageCode) .
'">Override (<span class="jutranslation-override-count">' . esc_html($language->overrided) . '</span>)</a></div> ';
if ($language->languageCode !== 'en-US') {
//Reference en-US file can't be modified
echo '<div style="display: inline-block; position: relative"><a class="jutranslation-edition" href="#" data-language="' .
esc_attr($language->languageCode) . '">Edit original file</a></div>';
}
//No sharing for en-US
if ($language->languageCode !== 'en-US') {
echo ' <a class="jutranslation-share" style="' . (($language->modified === '0') ? 'display:none' : '') .
'" href="#" data-language="' . esc_attr($language->languageCode) . '">Share with Joomunited</a>';
}
echo '</div><div class="temporary_content"></div></td>';
echo '</tr>';
if (!isset($julanguages[$language->extension->extension_slug])) {
$plugin_data = get_plugin_data($language->extension->main_plugin_file);
$julanguages[$language->extension->extension_slug] = array();
$julanguages[$language->extension->extension_slug]['extension'] = $language->extension->extension_slug;
$julanguages[$language->extension->extension_slug]['extension_version'] = $plugin_data['Version'];
$julanguages[$language->extension->extension_slug]['language_version'] = $language->language_version;
$julanguages[$language->extension->extension_slug]['languages'] = array();
$julanguages[$language->extension->extension_slug]['versions'] = array();
$julanguages[$language->extension->extension_slug]['revisions'] = array();
}
$julanguages[$language->extension->extension_slug]['languages'][] = $language->languageCode;
$julanguages[
$language->extension->extension_slug]['versions'][$language->languageCode
] = $language->language_version;
$julanguages[
$language->extension->extension_slug]['revisions'][$language->languageCode
] = $language->revision;
}
echo '</tbody>
</table>';
echo '<script type="text/javascript">julanguages = ' . json_encode($julanguages) . ';</script>';
echo '</div></div>';
}
/**
* Save a post translation for a given language
*
* @return void
*/
protected static function saveStrings()
{
//Security check
if (!wp_verify_nonce($_REQUEST['wp_nonce'], 'jutranslation')) {
echo json_encode(array('status' => 'error', 'message' => 'nonce error'));
die();
}
//Get and check language
$language = $_POST['language'];
if (!$language) {
echo json_encode(array('status' => 'error', 'message' => 'language empty'));
die();
}
if (!preg_match('/^[a-z]{2,3}(?:-[a-zA-Z]{4})?(?:-[A-Z]{2,3})?$/', $language)) {
echo json_encode(array('status' => 'error', 'message' => 'invalid language code'));
die();
}
$plugin = $_POST['slug'];
if (!$plugin) {
echo json_encode(array('status' => 'error', 'message' => 'plugin empty'));
die();
}
if (!preg_match('/^[a-zA-Z-_]+$/', $plugin)) {
echo json_encode(array('status' => 'error', 'message' => 'invalid plugin slug'));
die();
}
$addons = apply_filters(self::$extension_slug . '_get_addons', array());
if (!isset($addons[$plugin])) {
echo json_encode(array('status' => 'error', 'message' => 'plugin not found'));
die();
}
//Get the file to write to
$destination = $_POST['destination'];
$file = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'plugins';
$file .= DIRECTORY_SEPARATOR . $addons[$plugin]->text_domain . '-' . str_replace('-', '_', $language);
$extension_version = '';
$revision = '';
switch ($destination) {
case 'override':
$file .= '.override.mo';
break;
case 'edition':
//Disallow editing main en-US file
if ($language === 'en-US') {
echo json_encode(
array('status' => 'error', 'message' => 'editing main reference file not allowed')
);
die();
}
$file .= '.mo';
//Get informations about previous installed file
// Load language file
$mo = new \MO();
$mo->import_from_file($file);
//Get the file version
if (isset($mo->headers['Version']) && $mo->headers['Version']) {
$extension_version = $mo->headers['Version'];
} else {
//Use the current extension version
$plugin_data = get_plugin_data($addons[$plugin]->main_plugin_file);
$extension_version = $plugin_data['Version'];
}
//Get the file revision
if (isset($mo->headers['Revision'])) {
$revision = $mo->headers['Revision'];
} else {
//Use the current extension version
$revision = (int)$_POST['revision'];
}
break;
default: //Case new language version installation from Joomunited
//Get the version
$extension_version = $_POST['extension_version'];
if (!$extension_version) {
echo json_encode(array('status' => 'error', 'message' => 'version empty'));
die();
}
//Get revision
$revision = (int)$_POST['revision'];
$file .= '.mo';
break;
}
//Check version number
if ($destination !== 'override' &&
!preg_match('/^([0-9]+)\.([0-9]+)(\.([0-9]+))?(\.([0-9]+))?$/', $extension_version)) {
echo json_encode(array('status' => 'error', 'message' => 'invalid version number'));
die();
}
$modified = 0;
if (isset($_POST['modified'])) {
$modified = $_POST['modified'];
}
//Get strings and remove slashes auto added by WP
$strings = stripslashes($_POST['strings']);
//Check if strings is a valid array
$strings = json_decode($strings);
if ($strings === false || !is_object($strings) || !count((array)$strings)) {
$strings = new \stdClass();
}
// Load translation class
$mo = new \MO();
//Generate the file header
if ($destination !== 'override') {
$mo->headers['Version'] = $extension_version;
$mo->headers['Revision'] = $revision;
$mo->headers['Modified'] = (int)$modified;
}
foreach ($strings as $code => $string) {
//Only save reference language empty strings
if ($string !== '' || $language === 'en-US') {
$entry = &$mo->make_entry($code, $string);
$mo->entries[$code] = &$entry;
}
}
//Create parents folders of language file
wp_mkdir_p(dirname($file));
//Write the language file
if ($mo->export_to_file($file)) {
echo json_encode(array('status' => 'success', 'message' => 'file created'));
die();
}
echo json_encode(array('status' => 'error', 'message' => 'writing file failed'));
die();
}
/**
* Get a translation file content
*
* @return void
*/
protected static function getTranslation()
{
check_ajax_referer('jutranslation', 'wp_nonce');
//Get and check language
$language = $_POST['language'];
if (!$language) {
echo json_encode(array('status' => 'error', 'message' => 'language empty'));
die();
}
if (!preg_match('/^[a-z]{2,3}(?:-[a-zA-Z]{4})?(?:-[A-Z]{2,3})?$/', $language)) {
echo json_encode(array('status' => 'error', 'message' => 'invalid language code'));
die();
}
$plugin = $_POST['slug'];
if (!$plugin) {
echo json_encode(array('status' => 'error', 'message' => 'plugin empty'));
die();
}
if (!preg_match('/^[a-zA-Z-_]+$/', $plugin)) {
echo json_encode(array('status' => 'error', 'message' => 'invalid plugin slug'));
die();
}
$addons = apply_filters(self::$extension_slug . '_get_addons', array());
if (!isset($addons[$plugin])) {
echo json_encode(array('status' => 'error', 'message' => 'plugin not found'));
die();
}
//Get the language file for reference language en-US
$file = $addons[$plugin]->language_file;
$mo = new \MO();
$mo->import_from_file($file);
//Retrieve reference the strings
$reference_strings = array();
foreach ($mo->entries as $entry) {
$reference_strings[$entry->singular] = $entry->translations[0];
}
//Get the default language file for this language
$file = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'plugins';
$file .= DIRECTORY_SEPARATOR . $addons[$plugin]->text_domain . '-';
$file .= str_replace('-', '_', $language) . '.mo';
$mo = new \MO();
$mo->import_from_file($file);
//Retrieve default strings
$language_strings = array();
foreach ($mo->entries as $entry) {
$language_strings[$entry->singular] = $entry->translations[0];
}
//Get the override file content if exists
$file = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'plugins';
$file .= DIRECTORY_SEPARATOR . $addons[$plugin]->text_domain . '-';
$file .= str_replace('-', '_', $language) . '.override.mo';
if (file_exists($file)) {
$mo = new \MO();
$mo->import_from_file($file);
//Retrieve override strings
$override_strings = array();
foreach ($mo->entries as $entry) {
$override_strings[$entry->singular] = $entry->translations[0];
}
} else {
$override_strings = array();
}
//Generate the final variable cotaining all strings
$final_result = array();
foreach (array(
'reference_strings' => $reference_strings,
'language_strings' => $language_strings,
'override_strings' => $override_strings) as $variable => $strings) {
foreach ($strings as $constant => $value) {
if (empty($final_result[$constant])) {
$obj = new \stdClass();
$obj->key = $constant;
$obj->reference = '';
$obj->language = '';
$obj->override = '';
$final_result[$constant] = $obj;
}
switch ($variable) {
case 'reference_strings':
$final_result[$constant]->reference = $value;
break;
case 'language_strings':
$final_result[$constant]->language = $value;
break;
case 'override_strings':
$final_result[$constant]->override = $value;
break;
}
}
}
echo json_encode(
array('status' => 'success', 'datas' => array('language' => $language, 'strings' => $final_result))
);
die();
}
/**
* Show submit form to share translation
*
* @throws Exception If language or code invalid
*
* @return void
*/
protected static function showViewForm()
{
check_ajax_referer('jutranslation', 'wp_nonce');
echo '<!doctype html>';
echo '<html lang="en">';
echo '<head>';
echo ' <meta charset="utf-8">';
echo ' <title>Share with Joomunited</title>';
echo '</head>';
echo '<body>';
//Get and check language
$language = $_GET['language'];
if (!$language) {
throw new \Exception('language empty');
}
if (!preg_match('/^[a-z]{2,3}(?:-[a-zA-Z]{4})?(?:-[A-Z]{2,3})?$/', $language)) {
throw new \Exception('invalid language code');
}
$plugin = $_GET['slug'];
if (!$plugin) {
echo json_encode(array('status' => 'error', 'message' => 'plugin empty'));
die();
}
if (!preg_match('/^[a-zA-Z-_]+$/', $plugin)) {
echo json_encode(array('status' => 'error', 'message' => 'invalid plugin slug'));
die();
}
$addons = apply_filters(self::$extension_slug . '_get_addons', array());
if (!isset($addons[$plugin])) {
echo json_encode(array('status' => 'error', 'message' => 'plugin not found'));
die();
}
$file = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'languages' . DIRECTORY_SEPARATOR . 'plugins';
$file .= DIRECTORY_SEPARATOR . $addons[$plugin]->text_domain . '-' . str_replace('-', '_', $language) . '.mo';
if (!file_exists($file)) {
throw new Exception('language file doesn\'t exist');
}
//Get informations
$mo = new \MO();
$mo->import_from_file($file);
//Check if the file has been modified by the user
if (isset($mo->headers['Modified']) && $mo->headers['Modified'] !== '1') {
throw new Exception('language file not modified');
}
$strings = array();
//Check if a translation exists for each entry
foreach ($mo->entries as $entry) {
$strings[$entry->singular] = $entry->translations[0];
}
$strings = json_encode($strings);
$ju_user_token = get_option('ju_user_token');
//Get the current extension version
$plugin_data = get_plugin_data($addons[$plugin]->main_plugin_file);
$version = $plugin_data['Version'];
echo '<form method="POST" '.
' action="https://www.joomunited.com/index.php?option=com_jutranslation&task=contribution.share">';
echo '<input type="hidden" name="extension" value="' . esc_attr($addons[$plugin]->extension_slug) . '" />';
echo '<input type="hidden" name="extension_language" value="' . esc_attr($language) . '" />';
echo '<input type="hidden" name="extension_version" value="' . esc_attr($version) . '" />';
echo '<input type="hidden" name="user_token" value="' . esc_attr(!empty($ju_user_token) ? $ju_user_token : '') . '" />';
echo '<input type="hidden" name="site_url" value="' . esc_url(admin_url()) . '" />';
echo '<input type="hidden" name="extension_updated" value="1" />';
//phpcs:ignore PHPCompatibility.Constants.NewConstants.ent_html401Found -- no support php5.3
echo '<textarea style="display: none" name="strings">' . esc_html(htmlentities($strings, ENT_COMPAT | ENT_HTML401, 'UTF-8')) . '</textarea>';
echo '</form>';
//Add waiting image
echo '<div style="text-align:center"><img src="' .
esc_url(plugin_dir_url(self::$main_plugin_file)) . 'jutranslation/assets/images/preview_loader.gif"></div>';
//Submit automatically the form on page loading
echo '<script type="text/javascript">document.forms[0].submit();</script>';
echo '</body>';
echo '</html>';
wp_die();
}
/**
* Save Ju Token
*
* @return void
*/
protected static function saveJuToken()
{
//Security check
if (!wp_verify_nonce($_REQUEST['wp_nonce'], 'jutranslation')) {
echo json_encode(array('status' => 'error', 'message' => 'nonce error'));
die();
}
if (isset($_POST['token'])) {
update_option('ju_user_token', $_POST['token']);
}
}
/**
* Load overrided languages
*
* @param string $text_domain Text domain to load
* @param string $mofile Mo file to load
*
* @return void;
*/
public static function overrideLanguage($text_domain, $mofile)
{
//Only for our plugin and addons
$addons = apply_filters(self::$extension_slug . '_get_addons', array());
foreach ($addons as $addon) {
if ($text_domain === $addon->text_domain) {
$path_parts = explode(DIRECTORY_SEPARATOR, $mofile);
$filename = $path_parts[count($path_parts) - 1];
$filename_parts = explode('.', $filename);
//Return if it's action already for overrode file
if (count($filename_parts) > 2 || $filename_parts[count($filename_parts) - 2] === 'override') {
return;
}
//Load the overrode file
$path_parts[count($path_parts) - 1] = str_replace(
'.mo',
'.override.mo',
$path_parts[count($path_parts) - 1]
);
if (file_exists(implode(DIRECTORY_SEPARATOR, $path_parts))) {
load_textdomain($text_domain, implode(DIRECTORY_SEPARATOR, $path_parts));
}
}
}
}
}