From b1bf3aa54cd80c93bfbaa3a5f28ac5e471c627e2 Mon Sep 17 00:00:00 2001 From: spleen1981 <43221199+spleen1981@users.noreply.github.com> Date: Tue, 31 Aug 2021 00:13:52 +0200 Subject: [PATCH] Raw merge of qtranslate-slug 1.1.8 as qtranslate-xt module Initial merge with minimal modifications to both qtranslate-xt core and qtranslate-slug to incorporate the latter as a module. Module can be enabled through a checkbox in qtranslate-xt advanced settings. Heavy code cleanup and harmonization yet to be performed. Settings page also to be incorporated in qtranslate-xt page --- admin/qtx_admin_modules.php | 4 +- admin/qtx_admin_settings.php | 39 + modules/qtx_modules_handler.php | 21 +- modules/slugs/assets/css/qts-default.css | 16 + modules/slugs/assets/css/qts-default.min.css | 1 + modules/slugs/assets/css/qts-settings.css | 53 + modules/slugs/assets/js/qts-nav-menu-min.js | 1 + modules/slugs/assets/js/qts-nav-menu.js | 167 + .../slugs/assets/js/qts-settings-upgrade.js | 69 + modules/slugs/assets/js/qts-settings.js | 19 + .../includes/class-qtranslate-slug-widget.php | 62 + .../slugs/includes/class-qtranslate-slug.php | 2722 +++++++++++++++++ .../qtranslate-slug-settings-options.php | 179 ++ .../includes/qtranslate-slug-settings.php | 815 +++++ modules/slugs/includes/termmeta-core.php | 226 ++ modules/slugs/languages/qts-es_ES.mo | Bin 0 -> 5991 bytes modules/slugs/languages/qts-es_ES.po | 142 + modules/slugs/languages/qts-pt_PT.mo | Bin 0 -> 8618 bytes modules/slugs/languages/qts-pt_PT.po | 343 +++ modules/slugs/languages/qts.pot | 313 ++ modules/slugs/readme.txt | 296 ++ modules/slugs/slugs.php | 182 ++ modules/slugs/version.txt | 162 + qtranslate_core.php | 5 - qtranslate_options.php | 1 + 25 files changed, 5830 insertions(+), 8 deletions(-) create mode 100644 modules/slugs/assets/css/qts-default.css create mode 100644 modules/slugs/assets/css/qts-default.min.css create mode 100644 modules/slugs/assets/css/qts-settings.css create mode 100644 modules/slugs/assets/js/qts-nav-menu-min.js create mode 100644 modules/slugs/assets/js/qts-nav-menu.js create mode 100644 modules/slugs/assets/js/qts-settings-upgrade.js create mode 100644 modules/slugs/assets/js/qts-settings.js create mode 100644 modules/slugs/includes/class-qtranslate-slug-widget.php create mode 100644 modules/slugs/includes/class-qtranslate-slug.php create mode 100644 modules/slugs/includes/qtranslate-slug-settings-options.php create mode 100644 modules/slugs/includes/qtranslate-slug-settings.php create mode 100644 modules/slugs/includes/termmeta-core.php create mode 100644 modules/slugs/languages/qts-es_ES.mo create mode 100644 modules/slugs/languages/qts-es_ES.po create mode 100644 modules/slugs/languages/qts-pt_PT.mo create mode 100644 modules/slugs/languages/qts-pt_PT.po create mode 100644 modules/slugs/languages/qts.pot create mode 100644 modules/slugs/readme.txt create mode 100644 modules/slugs/slugs.php create mode 100644 modules/slugs/version.txt diff --git a/admin/qtx_admin_modules.php b/admin/qtx_admin_modules.php index eae9ec15..b38c4cb7 100644 --- a/admin/qtx_admin_modules.php +++ b/admin/qtx_admin_modules.php @@ -63,7 +63,9 @@ public static function check_module( $module_def, $func_is_active = 'is_plugin_a break; } } - } else { + } else if (is_bool($integration_plugin)){ + $active = $integration_plugin; + } else { $active = call_user_func( $func_is_active, $integration_plugin ); } diff --git a/admin/qtx_admin_settings.php b/admin/qtx_admin_settings.php index 7fe5fb39..63a0b652 100644 --- a/admin/qtx_admin_settings.php +++ b/admin/qtx_admin_settings.php @@ -244,6 +244,8 @@ private function add_configuration_inspector() { } private function add_sections( $nonce_action ) { + global $q_config; + $admin_sections = array(); $admin_sections['general'] = __( 'General', 'qtranslate' ); $admin_sections['advanced'] = __( 'Advanced', 'qtranslate' ); @@ -256,6 +258,10 @@ private function add_sections( $nonce_action ) { $admin_sections['integration'] = __( 'Integration', 'qtranslate' ); $admin_sections['import'] = __( 'Import', 'qtranslate' ) . '/' . __( 'Export', 'qtranslate' ); $admin_sections['languages'] = __( 'Languages', 'qtranslate' ); + + if ($q_config['slugs_enabled']) + $admin_sections['slugs'] = __( 'Slugs', 'qtranslate' ); + $admin_sections['troubleshooting'] = __( 'Troubleshooting', 'qtranslate' ); ?> @@ -272,6 +278,10 @@ private function add_sections( $nonce_action ) { $this->add_general_section(); $this->add_advanced_section(); $this->add_integration_section(); + + if ($q_config['slugs_enabled']) + $this->add_slugs_section(); + $this->add_troubleshooting_section(); // Allow to load additional services do_action( 'qtranslate_configuration', $this->options_uri ); @@ -693,6 +703,17 @@ private function add_advanced_section() { printf( __( 'The color in use is taken from your profile option %s, the third color.', 'qtranslate' ), '"' . qtranxf_translate_wp( 'Admin Color Scheme' ) . '"' ) ?>

+ + + + +

+ + close_section( 'advanced' ); @@ -826,6 +847,24 @@ class="qtranxs_explanation"> close_section( 'integration' ); } + + private function add_slugs_section() { + global $q_config; + $this->open_section( 'slugs' ); ?> + + + + + + +
+

here.', 'qtranslate' ), get_admin_url().'options-general.php?page=qtranslate-slug-settings' ) ?>

+
+ + + close_section( 'slugs', false ); + } private function add_troubleshooting_section() { $this->open_section( 'troubleshooting' ); ?> diff --git a/modules/qtx_modules_handler.php b/modules/qtx_modules_handler.php index 88c154cc..7ab4eceb 100644 --- a/modules/qtx_modules_handler.php +++ b/modules/qtx_modules_handler.php @@ -18,6 +18,9 @@ public static function load_modules_enabled() { if ( ! is_array( $options_modules ) ) { return null; } + + self::update_manual_enabled_modules(); + foreach ( $def_modules as $def_module ) { if ( ! array_key_exists( $def_module['id'], $options_modules ) ) { continue; @@ -28,6 +31,16 @@ public static function load_modules_enabled() { } } } + + public static function update_manual_enabled_modules() { + global $q_config; + $options_modules = get_option( 'qtranslate_modules', array() ); + + if ($q_config['slugs_enabled'] && $options_modules['slugs']!=1){ + $options_modules['slugs']=1; + update_option( 'qtranslate_modules', $options_modules ); + } + } /** * Retrieve the definitions of the built-in integration modules. @@ -89,8 +102,12 @@ public static function get_modules_defs() { 'name' => 'Yoast SEO', 'plugin' => 'wordpress-seo/wp-seo.php', 'incompatible' => 'wp-seo-qtranslate-x/wordpress-seo-qtranslate-x.php' - ) - ); + ), + array( 'id' => 'slugs', + 'name' => 'Slugs', + 'plugin' => true, + 'incompatible' => 'qtranslate-slug/qtranslate-slug.php' + )); } } diff --git a/modules/slugs/assets/css/qts-default.css b/modules/slugs/assets/css/qts-default.css new file mode 100644 index 00000000..c700de08 --- /dev/null +++ b/modules/slugs/assets/css/qts-default.css @@ -0,0 +1,16 @@ +.qts_type_image .qts_lang_item { + float: left; + margin-right: 7px; +} +.qts_type_image .qts_lang_item.last-child { + margin-right: 0; +} +.qts_lang_item{ + margin-top: 7px; + margin-bottom: 7px; +} +.qts_both { + white-space: nowrap; + line-height:1em; +} +.qts_both img { margin-right: 4px } diff --git a/modules/slugs/assets/css/qts-default.min.css b/modules/slugs/assets/css/qts-default.min.css new file mode 100644 index 00000000..e8867d16 --- /dev/null +++ b/modules/slugs/assets/css/qts-default.min.css @@ -0,0 +1 @@ +.qts_type_image .qts_lang_item{float:left;margin-right:7px}.qts_type_image .qts_lang_item.last-child{margin-right:0}.qts_lang_item{margin-top:7px;margin-bottom:7px}.qts_both{white-space:nowrap;line-height:1em}.qts_both img{margin-right:4px} \ No newline at end of file diff --git a/modules/slugs/assets/css/qts-settings.css b/modules/slugs/assets/css/qts-settings.css new file mode 100644 index 00000000..a4709404 --- /dev/null +++ b/modules/slugs/assets/css/qts-settings.css @@ -0,0 +1,53 @@ +/*messages*/ +.error {color:#cc0000;} + +.settings_page_qtranslate-slug-settings .form-table th { + width: 15%; + min-width: 15% !important; +} + +.settings_page_qtranslate-slug-settings .form-table td > span { + display: inline-block; + min-width: 100px; +} + +.settings_page_qtranslate-slug-settings .form-table label { + display: block; + margin-bottom: 8px; +} + +.settings_page_qtranslate-slug-settings .qts-slug { + width: 35%; +} + +#qts-loading { + display: none; + position: relative; + margin-left: 5px; + vertical-align: middle; +} + +div.updated.success{ + border-color: #298e00; + background-color: #D4EDC9; +} + +.error a.button-primary { + color: white !important; + text-decoration: none !important; +} + +.ko { + color: #c00; +} +/* v1.1.18 */ +#edittag #qts_term_slugs { display: none; } +.term-slug-wrap .qts_term_block input { + width: 86.5%; +} + +.qts_term_block label { + display: inline-block; + min-width: 120px; +} + \ No newline at end of file diff --git a/modules/slugs/assets/js/qts-nav-menu-min.js b/modules/slugs/assets/js/qts-nav-menu-min.js new file mode 100644 index 00000000..95d44e45 --- /dev/null +++ b/modules/slugs/assets/js/qts-nav-menu-min.js @@ -0,0 +1 @@ +jQuery(document).ready(function(t){function i(){t(".item-title").each(function(){n[t(this).closest("li").attr("id")]=[],n[t(this).closest("li").attr("id")].Title=t(this).find("span").html(),"undefined"==typeof n[t(this).closest("li").attr("id")].Original&&(n[t(this).closest("li").attr("id")].Original=n[t(this).closest("li").attr("id")].Title)}),t(".menu-item").each(function(){this_label=t(this).find("input.edit-menu-item-title"),this_title=t(this).find("input.edit-menu-item-attr-title"),n[t(this).attr("id")][this_label.attr("id")]=this_label.val(),n[t(this).attr("id")][this_title.attr("id")]=this_title.val()})}function e(){regexp=new RegExp("(.*?)","i"),t(".item-title").each(function(){(matches=n[t(this).closest("li").attr("id")].Original.match(regexp))&&t(this).closest("li").find(".link-to-original a").text(matches[1])}),regexp2=new RegExp("(.*?)","i"),t(".menu-item").each(function(){this_label=t(this).find("input.edit-menu-item-title"),this_title=t(this).find("input.edit-menu-item-attr-title"),"all"===d?(this_label.val(n[t(this).attr("id")][this_label.attr("id")]),this_title.val(n[t(this).attr("id")][this_title.attr("id")])):((matches=n[t(this).attr("id")][this_label.attr("id")].match(regexp2))&&this_label.val(matches[1]),(matches2=n[t(this).attr("id")][this_title.attr("id")].match(regexp2))&&this_title.val(matches2[1]))})}function a(){t(".menu-item").each(function(){this_label=t(this).find("input.edit-menu-item-title"),this_title=t(this).find("input.edit-menu-item-attr-title"),this_label.val(n[t(this).attr("id")][this_label.attr("id")]),this_title.val(n[t(this).attr("id")][this_title.attr("id")]),t(this).find(".link-to-original a").text(n[t(this).closest("li").attr("id")].Original)})}var n=[],s=wpNavMenu.addMenuItemToBottom;wpNavMenu.addMenuItemToBottom=function(t,a){s(t,a),i(),e()};var l=wpNavMenu.addMenuItemToTop;wpNavMenu.addMenuItemToTop=function(t,a){l(t,a),i(),e()};var d=t("#qt-languages :radio:checked").val();i(),e(),t(document).ajaxComplete(function(){d=t("#qt-languages :radio:checked").val(),e()}),t("#qt-languages :radio").change(function(){d=t("#qt-languages :radio:checked").val(),e()}),t(".submit-add-to-menu").click(function(){d=t("#qt-languages :radio:checked").val(),e()}),t(document.body).on("change","input.edit-menu-item-title",null,function(){regexp=new RegExp("(.*?)","i");var i=n[t(this).closest("li").attr("id")][t(this).attr("id")],e=t(this).val();regexp.test(i)&&(n[t(this).closest("li").attr("id")][t(this).attr("id")]=i.replace(regexp,""+e+""))}),t(document.body).on("change","input.edit-menu-item-attr-title",null,function(){regexp=new RegExp("(.*?)","i");var i=n[t(this).closest("li").attr("id")][t(this).attr("id")],e=t(this).val();qts_new_string=""+e+"","undefined"==typeof i||""==i?(n[t(this).closest("li").attr("id")][t(this).attr("id")]=qts_new_string,t(this).val(qts_new_string)):regexp.test(i)?n[t(this).closest("li").attr("id")][t(this).attr("id")]=i.replace(regexp,qts_new_string):(t(this).val(i+qts_new_string),n[t(this).closest("li").attr("id")][t(this).attr("id")]=i+qts_new_string)}),t(".menu-save").click(function(){a()}),window.onbeforeunload=function(){a()}}); \ No newline at end of file diff --git a/modules/slugs/assets/js/qts-nav-menu.js b/modules/slugs/assets/js/qts-nav-menu.js new file mode 100644 index 00000000..7b96e9b7 --- /dev/null +++ b/modules/slugs/assets/js/qts-nav-menu.js @@ -0,0 +1,167 @@ +jQuery(document).ready(function($){ + var qts_menuitemlang = []; + // Change titles (and values) when user add new item to the menu: + var oldAddMenuItemToBottom = wpNavMenu.addMenuItemToBottom; + wpNavMenu.addMenuItemToBottom = function( menuMarkup, req ) { + oldAddMenuItemToBottom( menuMarkup, req ); + saveLang(); + changeTitles(); + }; + var oldAddMenuItemToTop = wpNavMenu.addMenuItemToTop; + wpNavMenu.addMenuItemToTop = function( menuMarkup, req ) { + oldAddMenuItemToTop( menuMarkup, req ); + saveLang(); + changeTitles(); + }; + + // Change titles (and values) when document is ready: + var lang = $('#qt-languages :radio:checked').val(); + saveLang(); + changeTitles(); + + /** + * Change titles when there is a click on pagination + * on show all pages tab. + * + * It happens when there are a large number of pages. + */ + $( document ).ajaxComplete(function() { + lang = $('#qt-languages :radio:checked').val(); + changeTitles(); + }); + + // Change titles (and values) when language is changed: + $('#qt-languages :radio').change( function() { + lang = $('#qt-languages :radio:checked').val(); + + changeTitles(); + }); + + // Change titles (and values) when new menu is added: + $('.submit-add-to-menu').click( function() { + lang = $('#qt-languages :radio:checked').val(); + changeTitles(); + }); + + // Update original value when user changed a value: + $(document.body).on('change', 'input.edit-menu-item-title', null, function() { + regexp = new RegExp('(.*?)', 'i'); + + + var qts_old_value = qts_menuitemlang[ $(this).closest("li").attr("id") ][ $(this).attr("id")], + qts_new_value = $(this).val(); + + if( regexp.test(qts_old_value ) ) { + qts_menuitemlang[ $(this).closest("li").attr("id") ][ $(this).attr("id")] = qts_old_value.replace( regexp,'' + qts_new_value + ''); + } + + }); + + + + + // Update original title="" value when user changed a value: + $(document.body).on('change', 'input.edit-menu-item-attr-title', null, function() { + regexp = new RegExp('(.*?)', 'i'); + var qts_old_value = qts_menuitemlang[ $(this).closest("li").attr("id") ][ $(this).attr("id")], + qts_new_value = $(this).val(); + qts_new_string = ''+ qts_new_value + ''; + if(typeof qts_old_value === "undefined" || qts_old_value == "" ) { + qts_menuitemlang[ $(this).closest("li").attr("id") ][ $(this).attr("id")] = qts_new_string; + $(this).val( qts_new_string ); + } else if( regexp.test(qts_old_value ) ) { + qts_menuitemlang[ $(this).closest("li").attr("id") ][ $(this).attr("id")] = qts_old_value.replace( regexp,qts_new_string); + } else { + $(this).val( qts_old_value + qts_new_string ); + qts_menuitemlang[ $(this).closest("li").attr("id") ][ $(this).attr("id")] = qts_old_value + qts_new_string; + } + + }); + + + + // Change titles (and values): + function saveLang() { + $('.item-title').each( function() { + qts_menuitemlang[ $(this).closest("li").attr("id") ] = []; + qts_menuitemlang[ $(this).closest("li").attr("id") ]['Title'] = $(this).find("span").html(); + + if( typeof qts_menuitemlang[ $(this).closest("li").attr("id") ]['Original'] === "undefined" ) { + qts_menuitemlang[ $(this).closest("li").attr("id") ]['Original'] = qts_menuitemlang[ $(this).closest("li").attr("id") ]['Title']; + } + }); + $('.menu-item').each( function() { + + this_label = $(this).find('input.edit-menu-item-title'); + this_title = $(this).find('input.edit-menu-item-attr-title'); + + qts_menuitemlang[ $(this).attr("id") ][this_label.attr("id") ] = this_label.val(); + qts_menuitemlang[ $(this).attr("id") ][this_title.attr("id") ] = this_title.val(); + + }); + + } + // Change titles (and values): + function changeTitles() { + // Change menu item titles and links (on the right side): + // TODO: review, and dump + regexp = new RegExp('(.*?)', 'i'); + $('.item-title').each( function() { + if (matches = qts_menuitemlang[ $(this).closest("li").attr("id") ]['Original'].match(regexp)) { + $(this).closest('li').find('.link-to-original a').text( matches[1] ); + } + + }); + // Change menu item title inputs (on the right side): Navigation Label, Title Attribute... + regexp2 = new RegExp('(.*?)', 'i'); + $('.menu-item').each( function() { + this_label = $(this).find('input.edit-menu-item-title'); + this_title = $(this).find('input.edit-menu-item-attr-title'); + if( lang === "all") { + this_label.val(qts_menuitemlang[ $(this).attr("id") ][this_label.attr("id") ] ); + this_title.val(qts_menuitemlang[ $(this).attr("id") ][this_title.attr("id") ] ); + } else { + + if (matches = qts_menuitemlang[ $(this).attr("id") ][this_label.attr("id") ].match(regexp2)) { + this_label.val( matches[1] ); + } + + if (matches2 = qts_menuitemlang[ $(this).attr("id") ][this_title.attr("id") ].match(regexp2)) { + this_title.val( matches2[1] ); + } + } + }); + + // Change menu item checkbox labels (on the left side): + // TODO: fix this, not a show stopper + /*$('label.menu-item-title').each( function() { + var textNode = $(this).contents().get(1); + });*/ + } + + // Restore the original input values: + function restoreValues(){ + + $('.menu-item').each( function() { + + this_label = $(this).find('input.edit-menu-item-title'); + this_title = $(this).find('input.edit-menu-item-attr-title'); + + this_label.val( qts_menuitemlang[ $(this).attr("id") ][this_label.attr("id") ] ); + this_title.val( qts_menuitemlang[ $(this).attr("id") ][this_title.attr("id") ] ); + $(this).find('.link-to-original a').text( qts_menuitemlang[ $(this).closest("li").attr("id") ]['Original']); + }); + } + + // Just before saving restore the original input values: + $('.menu-save').click(function() { + restoreValues(); + }); + + // Just before leaving the page (or refresh) restore the original input values: + window.onbeforeunload = function(){ + restoreValues(); + return; + }; + +}); \ No newline at end of file diff --git a/modules/slugs/assets/js/qts-settings-upgrade.js b/modules/slugs/assets/js/qts-settings-upgrade.js new file mode 100644 index 00000000..7e3834af --- /dev/null +++ b/modules/slugs/assets/js/qts-settings-upgrade.js @@ -0,0 +1,69 @@ +jQuery(document).ready(function($) { + + function _debug(msg) { + if(window.console) { + console.debug(msg); + } + } + var upgrade_box = $('#qts-upgrade-box'), + upgrade_form = $('#qts-upgrade-form'), + upgrade_button = $('#qts-upgrade-button'), + notice_status = function(_status) { + upgrade_box.removeClass().addClass(_status); + }, + block_form = function(_block) { + if (_block) { + $('#qts-loading').show(); + upgrade_button.attr('disabled', true); + } else { + $('#qts-loading').hide(); + upgrade_button.attr('disabled', false); + } + + }, + check_types = function(_response) { + + block_form(false); + upgrade_form.find('.message').remove(); + + switch (_response.status) { + default: + case 0: + upgrade_form.prepend('

'+_response.message+'

'); + break; + case 1: + notice_status('updated success'); + upgrade_form.remove(); + upgrade_box.append('

'+_response.message+'

'); + upgrade_box.delay(2500).fadeTo(1300, 0, function(){ upgrade_box.remove(); }); + break; + case 2: + var data_ = '

'+_response.message+'

'; + data_ += ''; + + upgrade_form.prepend(data_); + + break; + } + }, + start_upgrade = function(_event) { + _event.preventDefault(); + + notice_status('updated'); + block_form(true); + + var package_ = {}; + package_.action = $('#qts-upgrade-action').val(); + package_.nonce = $('#qts-upgrade-nonce').val(); + if ( $('#qts-slug-type').length ) + package_.type = $('#qts-slug-type').val(); + + $.post(ajaxurl, package_, check_types); + }; + + upgrade_button.bind('click', start_upgrade); +}); \ No newline at end of file diff --git a/modules/slugs/assets/js/qts-settings.js b/modules/slugs/assets/js/qts-settings.js new file mode 100644 index 00000000..56caa3e1 --- /dev/null +++ b/modules/slugs/assets/js/qts-settings.js @@ -0,0 +1,19 @@ +/*############### Error messages ######################*/ +jQuery(function(){ + + var error_msg = jQuery("#message p[class='setting-error-message']"); + // look for admin messages with the "setting-error-message" error class + if (error_msg.length != 0) { + // get the title + var error_setting = error_msg.attr('title'); + + // look for the label with the "for" attribute=setting title and give it an "error" class (style this in the css file!) + jQuery("label[for='" + error_setting + "']").addClass('error'); + + // look for the input with id=setting title and add a red border to it. + jQuery("input[id='" + error_setting + "']").attr('style', 'border-color: red'); + } + + + +}); \ No newline at end of file diff --git a/modules/slugs/includes/class-qtranslate-slug-widget.php b/modules/slugs/includes/class-qtranslate-slug-widget.php new file mode 100644 index 00000000..f2727fd1 --- /dev/null +++ b/modules/slugs/includes/class-qtranslate-slug-widget.php @@ -0,0 +1,62 @@ + 'qts_widget', 'description' => __('Allows your visitors to choose a Language.','qts') ); + parent::__construct('qtranslateslug', __('Language selector (QTS)', 'qts'), $widget_ops); + } + + function widget($args, $instance) { + extract($args); + + echo $before_widget; + $title = empty($instance['title']) ? __('Language', 'qts') : apply_filters('widget_title', $instance['title']); + $hide_title = empty($instance['hide-title']) ? false : 'on'; + $type = $instance['type']; + $short_text = ($instance['short_text'] == 'on') ? true : false ; + + if( $type!='text' && $type!='image' && $type!='both' && $type!='dropdown' ) $type='text'; + + if( $hide_title!='on') + echo $before_title . $title . $after_title; + + qts_language_menu($type, array( 'id' => $this->id, 'short' => $short_text ) ); + + echo $after_widget; + } + + function update($new_instance, $old_instance) { + $instance = $old_instance; + $instance['title'] = $new_instance['title']; + $instance['hide-title'] = $new_instance['hide-title']; + $instance['type'] = $new_instance['type']; + $instance['short_text'] = $new_instance['short_text']; + + return $instance; + } + + function form($instance) { + $instance = wp_parse_args( (array) $instance, array( 'title' => '', 'hide-title' => false, 'type' => 'text' ) ); + $title = $instance['title']; + $hide_title = $instance['hide-title']; + $type = $instance['type']; + $short_text = isset($instance['short_text']) ? $instance['short_text'] : ''; + ?> +

+

+

+

+

+

+

+

+ + lang) ? $this->lang : $this->current_lang; + } + + /** + * return the current / temp language + * we store and use it all the way! + * @since 1.1.9 + */ + private function get_currentlang() { + return $this->current_lang; + } + + /** + * return the enabled languages + * we store and use it all the way! + * @since 1.1.9 + */ + private function get_enabled_languages() { + return $this->enabled_languages; + } + + /** + * return the enabled languages + * we store and use it all the way! + * @since 1.1.9 + */ + private function get_url_path_mode() { + return $this->url_path_mode; + } + + /** + * getter: options + * @since 1.0 + */ + public function get_options() { + $this->set_options(); + return $this->options; + } + + /** + * Returns the correct prefix for the function names of the different supported translation plugins. + * Will return 'qtranxf_' if qtranslate-x is used, 'qtrans_' otherwise. + * + * @return string the function name prefix for translation functions from other plugins + * @since 1.1.9 + */ + + private function get_plugin_prefix(){ + + return $this->plugin_prefix; + } + + + /** + * setter: options | permalink_structure + * + * @since 1.0 + */ + public function set_options() { + + if (empty($this->options)) { + $this->options = get_option(QTS_OPTIONS_NAME); + } + + if (!$this->options) { + add_option(QTS_OPTIONS_NAME, array()); + } + + if (is_null($this->permalink_structure)) { + $this->permalink_structure = get_option('permalink_structure'); + } + } + + /** + * Sets the prefix for the active fork. See get_plugin_prefix + * @since 1.1.9 + * + */ + private function set_plugin_prefix(){ + if ('' === $this->plugin_prefix){ + if (is_plugin_active('qtranslate-x/qtranslate.php') || defined( 'QTRANSLATE_FILE' ) ){ + $this->plugin_prefix = 'qtranxf_'; + } else { + $this->plugin_prefix = 'qtrans_'; + } + } + } + + /** + * Sets the url path mode based on the qtranslate or fork settings. + * + */ + + private function set_url_path_mode(){ + if ('' === $this->url_path_mode){ + if (is_plugin_active('qtranslate-x/qtranslate.php') || defined( 'QTRANSLATE_FILE' ) ){ + $this->url_path_mode = QTX_URL_PATH; + } else { + $this->url_path_mode = QT_URL_PATH; + } + } + } + + /** + * setter: options | permalink_structure + * + * @since 1.0 + */ + public function save_options($new_options = false) { + if (!$new_options || empty($new_options)) { + return; + } + + if (count($this->options) != count($new_options)) { + return; + } + + update_option(QTS_OPTIONS_NAME, $new_options); + $this->options = $new_options; + } + + + + /** + * getter: meta key + * + * @since 1.0 + */ + public function get_meta_key( $force_lang = false ) { + + $lang = $this->get_lang(); + + if ($force_lang) { + $lang = $force_lang; + } + + return sprintf($this->meta_key, $lang); // returns: _qts_slug_en + } + + + + /** + * check dependences for activation + * + * @since 1.0 + */ + static function block_activate() { + global $wp_version; + include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); + return ( + version_compare($wp_version, "4.0", "<" ) || + !( defined( 'QTRANSLATE_FILE' ) || + ( is_plugin_active('qtranslate/qtranslate.php') || + is_plugin_active('qtranslate/qtranslate-x.php') || + is_plugin_active('mqtranslate/mqtranslate.php') || + is_plugin_active('qtranslate-x/qtranslate.php')) ) + ); + } + + + + + /** + * check if exists qtranslate and do the installation, support multisite + * + * @since 1.0 + */ + public function install() { + global $wpdb; + + /*if ( self::block_activate() ) { + if (is_admin()) { + add_action('admin_notices', array(&$this, 'notice_dependences')); + } + }*/ + + if ( function_exists('is_multisite') && is_multisite() ) { + + if (isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) { + + $old_blog = $wpdb->blogid; + $blogids = $wpdb->get_col($wpdb->prepare("SELECT blog_id FROM $wpdb->blogs")); + foreach ($blogids as $blog_id) { + switch_to_blog($blog_id); + $this->activate(); + } + switch_to_blog($old_blog); + return; + } + } + + $this->activate(); + } + + + + /** + * activates and do the installation + * + * @since 1.0 + */ + private function activate() { + global $wp_rewrite; + + $this->set_options(); + + $qts_version = get_option('qts_version'); + + // checks version and do the installation + if ( !$qts_version || $qts_version != QTS_VERSION ) { + + // install termmeta table using functions from Simple-Term-Meta + // ( http://wordpress.org/extend/plugins/simple-term-meta/ ) + install_term_meta_table(); + + // update installed option + update_option('qts_version', QTS_VERSION); + } + + // regenerate rewrite rules in db + add_action( 'generate_rewrite_rules', array(&$this, 'modify_rewrite_rules') ); + flush_rewrite_rules(); + } + + + + /** + * register front end styles and enqueue + * + * @since 1.1.7 + */ + public function register_plugin_styles() { + wp_register_style( 'qts_front_styles', plugins_url( '/assets/css/qts-default.css', dirname(__FILE__ ) ) ); + wp_enqueue_style( 'qts_front_styles' ); + } + /** + * register minified front end styles and enqueue + * 43LC: easier duplicating the function :| + * @since 1.1.8 + */ + public function register_plugin_styles_min() { + wp_register_style( 'qts_front_styles', plugins_url( '/assets/css/qts-default.min.css', dirname(__FILE__ ) ) ); + wp_enqueue_style( 'qts_front_styles' ); + } + + + + /** + * print front end styles + * + * @since 1.1.7 + */ + public function print_plugin_styles() { + + $css_path = dirname(__FILE__).'/assets/css/qts-default.css'; + + if (!file_exists($css_path) || !is_readable($css_path)) { + return; + } + + $default_css_file = file_get_contents($css_path, FILE_USE_INCLUDE_PATH); + + $css = "\n"; + echo $css; + } + + + + /** + * actions when deactivating the plugin + * + * @since 1.0 + */ + public function deactivate() { + global $wp_rewrite; + + // regenerate rewrite rules in db + remove_action( 'generate_rewrite_rules', array(&$this, 'modify_rewrite_rules') ); + $wp_rewrite->flush_rules(); + } + + + + /** + * admin notice: update your old data + * + * @since 1.0 + */ + function notice_update(){ + global $current_screen; + + if ($current_screen->id != 'settings_page_qtranslate-slug-settings') { + + echo "
" . PHP_EOL; + echo "

Qtranslate Slug:

" . PHP_EOL; + printf("

%s %s

", __('Please update your old data to the new system.', 'qts'), add_query_arg(array('page' => 'qtranslate-slug-settings'), 'options-general.php'), __('upgrade now', 'qts')) . PHP_EOL; + echo "
" . PHP_EOL; + } + } + + + + /** + * admin notice: update your old data + * + * @since 1.0 + */ + function notice_dependences(){ + + $ornewer=__('or newer','qts'); + $info_url=admin_url('plugin-install.php?tab=plugin-information'); + echo '
' . PHP_EOL; + echo '

Qtranslate Slug:

' . PHP_EOL; + echo '

'; + printf(__('This plugin requires at least %s and either %s, or %s, or %s', 'qts'), + 'WordPress 4.0', + 'qTranslate-X (2.9 '.$ornewer.')', + 'mqTranslate (2.6.2.4 '.$ornewer.')', + 'qTranslate (2.5.8 '.$ornewer.')'); + echo '

' . PHP_EOL; + echo '
' . PHP_EOL; + } + + + + /** + * checks if old table 'qtranslate_slug' exists and is not empty + * + * @return object | false + * + * @since 1.0 + */ + public function check_old_data() { + global $wpdb; + + if ($this->old_data === false) { + return false; + } + + $table_name = $wpdb->get_var("SHOW TABLES LIKE '{$wpdb->prefix}qtranslate_slug'"); + + if (!empty($table_name)) { + $this->old_data = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}qtranslate_slug"); + } + + if ( empty($table_name) || empty($this->old_data) ) { + $this->old_data = false; + } + + return $this->old_data; + } + + + + /** + * actions when deactivating the plugin + * + * @since 1.0 + */ + private function check_old_versions() { + + if ( $this->check_old_data() ) { + add_action('admin_notices', array(&$this, 'notice_update')); + } + } + + function qtranslate_updated_settings(){ + global $q_config; + $options_modules = get_option( 'qtranslate_modules', array() ); + + if ($q_config['slugs_enabled']){ + $this->install(); + $options_modules['slugs']=1; + }else{ + $this->deactivate(); + $options_modules['slugs']=2; + } + update_option( 'qtranslate_modules', $options_modules ); + } + + /** + * Initialise the Class with all hooks + * + * @since 1.0 + */ + function init() { + global $q_config; + if (!$q_config['slugs_enabled']) + return; + + load_plugin_textdomain( 'qts', false, basename( plugin_dir_path( dirname( __FILE__ ) ) ) . '/languages' ); + + // checking plugin activate + if ( self::block_activate() ) { + if (is_admin()) { + add_action('admin_notices', array(&$this, 'notice_dependences')); + } + return; + } else { + remove_action('admin_notices', array(&$this, 'notice_dependences')); + } + if ( is_admin() ) { + include_once(dirname(__FILE__).'/qtranslate-slug-settings.php'); + } + + //global $q_config; + + // until we get a proper function, this will make it for it. + $this->current_lang = $q_config['language']; + $this->enabled_languages = $q_config['enabled_languages']; + $this->default_language = $q_config['default_language']; + $this->set_plugin_prefix(); + $this->set_url_path_mode(); + + if ( is_admin() ) { + + $this->check_old_versions(); + + + // add filters + add_filter( 'qts_validate_post_slug', array(&$this, 'validate_post_slug'), 0, 3 ); + add_filter( 'qts_validate_post_slug', array(&$this, 'unique_post_slug'), 1, 3 ); + add_filter( 'qts_validate_term_slug', array(&$this, 'validate_term_slug'), 0, 3 ); + add_filter( 'qts_validate_term_slug', array(&$this, 'unique_term_slug'), 1, 3 ); + add_filter( 'wp_get_object_terms', array(&$this, 'get_object_terms'), 0, 4 ); + add_filter( 'get_terms', array(&$this, 'get_terms'), 0, 3 ); + + // admin actions + add_action( 'admin_menu', array(&$this, 'add_slug_meta_box') ); + add_action( 'admin_menu', array(&$this, 'remove_defaultslug_meta_box') ); + add_action( 'save_post', array(&$this, 'save_postdata'), 605, 2 ); + add_action( 'delete_term', array(&$this, 'delete_term'), 0, 3); + add_action( 'created_term', array(&$this, 'save_term'), 605, 3); + add_action( 'edited_term', array(&$this, 'save_term'), 605, 3 ); + add_action( 'admin_head', array(&$this, 'hide_slug_box'), 900 ); + + add_action( 'init', array(&$this, 'taxonomies_hooks'), 805 ); + + add_action( 'admin_head', array(&$this, 'hide_quick_edit'), 600 ); + if(!defined('QTRANSLATE_FILE')) + add_action( 'admin_init', array(&$this, 'fix_nav_menu') ); + + } else { + + add_filter( 'request', array(&$this, 'filter_request') ); + + // adds external style file + $qts_options = $this->get_options(); + if ( !isset($qts_options[QTS_PREFIX.'styles']) || $qts_options[QTS_PREFIX.'styles'] == "file" ) { + add_action( 'wp_enqueue_scripts', array( &$this, 'register_plugin_styles' ) ); + } elseif ($qts_options[QTS_PREFIX.'styles'] == "minified" ) { + add_action( 'wp_enqueue_scripts', array( &$this, 'register_plugin_styles_min' ) ); + } elseif ($qts_options[QTS_PREFIX.'styles'] == "inline" ) { + add_action( 'wp_print_styles', array( &$this, 'print_plugin_styles' ), 20 ); + } + } + //FIXME: query vars are broken + add_filter( 'query_vars', array(&$this, 'query_vars')); + add_action( 'generate_rewrite_rules', array(&$this, 'modify_rewrite_rules') ); + + // remove from qtranslate the discouraged meta http-equiv, inline styles + // (including flag URLs) and wrong hreflang links + + remove_action('wp_head', $this->get_plugin_prefix() . 'header'); + if( "qtranxf_" === $this->get_plugin_prefix() ) { + remove_action('wp_head', $this->get_plugin_prefix() . 'wp_head'); + } + + // add proper hreflang links + add_action('wp_head',array(&$this, 'qtranslate_slug_header_extended')); + + // remove some Qtranslate filters + remove_filter( 'page_link', $this->get_plugin_prefix() . 'convertURL' ); + remove_filter( 'post_link', $this->get_plugin_prefix() . 'convertURL' ); + remove_filter( 'category_link', $this->get_plugin_prefix() . 'convertURL' ); + remove_filter( 'tag_link', $this->get_plugin_prefix() . 'convertURL' ); + + //FIXME: query vars are broken + add_filter( 'qts_permastruct' , array(&$this, 'get_extra_permastruct'), 0, 2); + add_filter( 'qts_url_args', array(&$this, 'parse_url_args'), 0, 1); + add_filter( 'home_url', array(&$this, 'home_url'), 10, 4); + add_filter( 'post_type_link', array(&$this, 'post_type_link'), 600, 4 ); + add_filter( 'post_link', array(&$this, 'post_link'), 0, 3 ); + add_filter( '_get_page_link', array(&$this, '_get_page_link'), 0, 2 ); + add_filter( 'term_link', array(&$this, 'term_link'), 600, 3 ); + + add_filter( 'single_term_title', $this->get_plugin_prefix() . 'useTermLib', 805 ); + add_filter( 'get_blogs_of_user', array(&$this, 'blog_names'), 1 ); + add_action( 'widgets_init', array(&$this, 'widget_init'), 100 ); + // Add specific CSS class to body class based on current lang + add_filter('body_class', array($this, 'qts_body_class'), 600, 1 ); + + add_filter( 'nav_menu_attr_title', array($this, 'qts_filter_attr_title'), 0, 3 ); + + + } + + /** + * Filters menu link attribute + * + * @since 1.1.9 + */ + function qts_filter_attr_title( $attr_title ) { + return $this->qts_quickuse($attr_title); + } + + + /** + * Adds proper links to the content with available translations. + * Fixes issue #25 + * + * @global $qtranslate_slug used to convert the url + * @global $q_config available languages + * + * @since 1.1.8 + */ + public function qtranslate_slug_header_extended(){ + if(is_404()) { return; } + + //taken from qtx but see our #341 ticket for clarification + echo ''.PHP_EOL; + foreach($this->get_enabled_languages() as $language) { + + echo ''."\n"; + } + } + + + /** + * Add a class based on the current language + * @param array $classes list of classes + */ + public function qts_body_class( $classes ) { + $classes[] = call_user_func($this->get_plugin_prefix() . 'getLanguage'); + return $classes; + } + + /** + * Finds the translated slug of the given post + * based on: https://wordpress.org/support/topic/permalink-for-other-languages + * @param int $id the post id + * @param string $lang which language to look for + * @return string the slug or empty if not found + * @author vbkun + * @since 1.1.13 + */ + public function get_slug($id, $lang){ + $slugArray = get_post_meta( $id, '_qts_slug_'.$lang ); + return !empty($slugArray) ? $slugArray[0] : ""; + } + + // TODO: properly test this + /** + * Get text in $lang, or in the current lang + * + * @package Qtranslate Slug + * @since 1.1.9 + * @param string $text the whole text + * @param string $lang (optional) get the text in this language, or if empty, the current + * @return array the text in the required language + */ + public function qts_quickuse( $text,$lang='' ){ + $lang = '' == $lang ? $this->current_lang : $lang; + $parsed_text = call_user_func($this->get_plugin_prefix() . 'getSortedLanguages',$text); + if( !empty($parsed_text[$lang])){ + return $parsed_text[$lang]; + } + } + + + /** + * Adds news rules to translate the URL bases, + * this function must be called on flush_rewrite or 'flush_rewrite_rules' + * + * @param object $wp_rewrite + * + * @since 1.0 + */ + public function modify_rewrite_rules() { + + // post types rules + $post_types = get_post_types( array('_builtin' => false ), 'objects'); + foreach ( $post_types as $post_type ) { + $this->generate_extra_rules( $post_type->name ); + } + + // taxonomies rules + $taxonomies = $this->get_public_taxonomies(); + foreach ( $taxonomies as $taxonomy ) { + $this->generate_extra_rules( $taxonomy->name ); + } + } + + + + /** + * Helper: news rules to translate the URL bases + * + * @param string $name name of extra permastruct + * @param string $type 'post_type' or 'taxonomy' + * + * @since 1.0 + */ + private function generate_extra_rules( $name = false ) { + global $wp_rewrite; + + foreach ($this->get_enabled_languages() as $lang): + + if ( $base = $this->get_base_slug( $name, $lang) ): + + $struct = $wp_rewrite->extra_permastructs[$name]; + + if ( is_array( $struct ) ) { + if ( count( $struct ) == 2 ) + $rules = $wp_rewrite->generate_rewrite_rules( "/$base/%$name%", $struct[1] ); + else + $rules = $wp_rewrite->generate_rewrite_rules( "/$base/%$name%", $struct['ep_mask'], $struct['paged'], $struct['feed'], $struct['forcomments'], $struct['walk_dirs'], $struct['endpoints'] ); + } else { + $rules = $wp_rewrite->generate_rewrite_rules( "/$base/%$name%" ); + } + + $wp_rewrite->rules = array_merge($rules, $wp_rewrite->rules); + + endif; + + endforeach; + } + + + + /** + * Helper that gets a base slug stored in options + * + * @param string $name of extra permastruct + * @return string base slug for 'post_type' and 'language' or false + * + * @since 1.0 + */ + public function get_base_slug($name = false, $lang = false) { + + if ( !$name || !$lang ) { + return false; + } + + if ( taxonomy_exists($name) ) { + $type = 'taxonomy'; + } else if ( post_type_exists($name) ) { + $type = 'post_type'; + } else { + return false; + } + + $qts_options = $this->get_options(); + + $option_name = QTS_PREFIX . $type . '_' . $name; + + if ( !isset($qts_options[$option_name]) || empty($qts_options[$option_name]) ) { + return false; + } + + if (isset($qts_options[$option_name][$lang])) { + return $qts_options[$option_name][$lang]; + } + + return false; + } + + + + /** + * Helper: returns public built-in and not built-in taxonomies + * + * @return array of public taxonomies objects + * + * @since 1.0 + */ + private function get_public_taxonomies() { + + $builtin = get_taxonomies( array( 'public' => true, 'show_ui' => true, '_builtin' => true ), 'object'); + $taxonomies = get_taxonomies( array( 'public' => true, 'show_ui' => true, '_builtin' => false ), 'object' ); + + return array_merge( $builtin, $taxonomies ); + } + + + + /** + * parse and adds $_GET args passed to an url + * + * @param string $url parameters + * @param string $lang processed + * @return string converted url + * + * @since 1.0 + */ + public function parse_url_args( $url ) { + global $q_config; //TODO: q_config : url_info, url_mode + + if (is_admin()) { + return $url; + } + + $url = preg_replace('/&/', '&', $url); + + // if no permalink structure ads ?lang=en + $base_query = parse_url($_SERVER['REQUEST_URI']); + // FIXME: why we do this : + $base_args = isset($base_query['query']) ? wp_parse_args($base_query['query']) : array(); + + if ( empty($this->permalink_structure) || $q_config['url_mode'] == 1 ) { + $base_args['lang'] = $this->get_lang(); + + } + + // rebuild query with all args + $url = add_query_arg($base_args, $url); + + $url = str_replace('/?', '?', $url); // TODO: hack: improve this code + $url = str_replace('?', '/?', $url); // TODO: hack: improve this code + + return $url; + } + + + + /** + * Fix get_page_by_path when querying vars + * + * @param $query_vars objec query vars founded + * @return object $query_vars processed + * + * @since 1.0 + */ + public function query_vars( $query_vars ) { + global $wp, $wp_rewrite; + + $wp->query_vars = array(); + $post_type_query_vars = array(); + + // Fetch the rewrite rules. + $rewrite = $wp_rewrite->wp_rewrite_rules(); + + if ( ! empty($rewrite) ) { + // If we match a rewrite rule, this will be cleared. + $error = '404'; + $wp->did_permalink = true; + + if ( isset($_SERVER['PATH_INFO']) ) { + $pathinfo = $_SERVER['PATH_INFO']; + } else { + $pathinfo = ''; + } + $pathinfo_array = explode('?', $pathinfo); + $pathinfo = str_replace("%", "%25", $pathinfo_array[0]); + $req_uri = $_SERVER['REQUEST_URI']; + $req_uri_array = explode('?', $req_uri); + $req_uri = $req_uri_array[0]; + $self = $_SERVER['PHP_SELF']; + $home_path = parse_url(home_url()); + + if ( isset($home_path['path']) ) { + $home_path = $home_path['path']; + } else { + $home_path = ''; + } + $home_path = trim($home_path, '/'); + + // Trim path info from the end and the leading home path from the + // front. For path info requests, this leaves us with the requesting + // filename, if any. For 404 requests, this leaves us with the + // requested permalink. + $req_uri = str_replace($pathinfo, '', $req_uri); + $req_uri = trim($req_uri, '/'); + $req_uri = preg_replace("|^$home_path|", '', $req_uri); + $req_uri = trim($req_uri, '/'); + if ($GLOBALS['q_config']['url_mode'] == $this->get_url_path_mode()) { + $req_uri = preg_replace("/^{$GLOBALS['q_config']['language']}(\/|$)/", '', $req_uri); + } + $pathinfo = trim($pathinfo, '/'); + $pathinfo = preg_replace("|^$home_path|", '', $pathinfo); + $pathinfo = trim($pathinfo, '/'); + $self = trim($self, '/'); + $self = preg_replace("|^$home_path|", '', $self); + $self = trim($self, '/'); + + // The requested permalink is in $pathinfo for path info requests and + // $req_uri for other requests. + if ( ! empty($pathinfo) && !preg_match('|^.*' . $wp_rewrite->index . '$|', $pathinfo) ) { + $request = $pathinfo; + } else { + // If the request uri is the index, blank it out so that + // we don't try to match it against a rule. + if ( $req_uri == $wp_rewrite->index ) + $req_uri = ''; + $request = $req_uri; + } + + $wp->request = $request; + + // Look for matches. + $request_match = $request; + if ( empty( $request_match ) ) { + // An empty request could only match against ^$ regex + if ( isset( $rewrite['$'] ) ) { + $wp->matched_rule = '$'; + $query = $rewrite['$']; + $matches = array(''); + } + } else if ( $req_uri != 'wp-app.php' ) { + foreach ( (array) $rewrite as $match => $query ) { + // If the requesting file is the anchor of the match, prepend it to the path info. + if ( ! empty($req_uri) && strpos($match, $req_uri) === 0 && $req_uri != $request ) { + $request_match = $req_uri . '/' . $request; + } + + if ( preg_match("#^$match#", $request_match, $matches) || preg_match("#^$match#", urldecode($request_match), $matches) ) { + + if ( $wp_rewrite->use_verbose_page_rules && preg_match( '/pagename=\$matches\[([0-9]+)\]/', $query, $varmatch ) ) { + // this is a verbose page match, lets check to be sure about it + if ( ! $page_foundid = $this->get_page_by_path( $matches[ $varmatch[1] ] ) ) { + continue; + } else { + wp_cache_set('qts_page_request', $page_foundid); // caching query :) + } + } + + // Got a match. + $wp->matched_rule = $match; + break; + } + } + } + + if ( isset( $wp->matched_rule ) ) { + // Trim the query of everything up to the '?'. + $query = preg_replace("!^.+\?!", '', $query); + + // Substitute the substring matches into the query. + $query = addslashes(WP_MatchesMapRegex::apply($query, $matches)); + + $wp->matched_query = $query; + + // Parse the query. + parse_str($query, $perma_query_vars); + + // If we're processing a 404 request, clear the error var + // since we found something. + unset( $_GET['error'] ); + unset( $error ); + } + + // If req_uri is empty or if it is a request for ourself, unset error. + if ( empty($request) || $req_uri == $self || strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false ) { + unset( $_GET['error'] ); + unset( $error ); + + if ( isset($perma_query_vars) && strpos($_SERVER['PHP_SELF'], 'wp-admin/') !== false ) { + unset( $perma_query_vars ); + } + + $wp->did_permalink = false; + } + } + + return count(array_diff($query_vars, $wp->public_query_vars)) > 0 ? $query_vars : $wp->public_query_vars; + } + + + + /** + * Function called when query parameters are processed by Wordpress. + * + * @param $query query parameters + * @return array() $query processed + * + * @since 1.0 + */ + function filter_request( $query ) { + global $wp_query, $wp; + // FIXME: why is this here? it breaks custom variables getter + // https://wordpress.org/support/topic/cant-retrieve-public-query-variables + if ((isset($wp->matched_query) || empty($query)) && ! isset($query['s']) ) { + $query = wp_parse_args($wp->matched_query); + } + + foreach (get_post_types() as $post_type) { + if ( array_key_exists($post_type, $query) && !in_array($post_type, array('post', 'page')) ) { + $query['post_type'] = $post_type; + } + } + + $page_foundit = false; + + // -> page + if ( isset($query['pagename']) || isset($query['page_id']) ): + + $page = wp_cache_get('qts_page_request'); + if (!$page) { + $page = isset($query['page_id']) ? get_post($query['page_id']) : $this->get_page_by_path($query['pagename']); + } + + if (!$page) { + return $query; + } + + $id = $page->ID; + $cache_array = array($page); + update_post_caches($cache_array, 'page'); // caching query :) + wp_cache_delete('qts_page_request'); + $query['pagename'] = get_page_uri($page); + $function = 'get_page_link'; + + // -> custom post type + elseif ( isset($query['post_type']) ): + if (count($query) == 1) { + $function = 'get_post_type_archive_link'; + $id = $query['post_type']; + } else { + $page_slug = ( isset($query['name']) && !empty($query['name']) ) ? $query['name'] : $query[$query['post_type']]; + $page = $this->get_page_by_path($page_slug, OBJECT, $query['post_type']); + if (!$page) return $query; + $id = $page->ID; + $cache_array = array($page); + update_post_caches($cache_array, $query['post_type']); // caching query :) + $query['name'] = $query[$query['post_type']] = get_page_uri($page); + $function = 'get_post_permalink'; + } + // -> post + elseif ( isset($query['name']) || isset($query['p']) ): + + $post = isset($query['p']) ? get_post($query['p']) : $this->get_page_by_path($query['name'], OBJECT, 'post'); + if (!$post) { + return $query; + } + $query['name'] = $post->post_name; + $id = $post->ID; + $cache_array = array($post); + update_post_caches($cache_array); + $function = 'get_permalink'; + + // -> category + elseif ( ( isset($query['category_name']) || isset($query['cat'])) ): + if ( isset($query['category_name']) ) { + $term_slug = $this->get_last_slash( $query['category_name'] ); + } + $term = isset($query['cat']) ? get_term($query['cat'], 'category') : $this->get_term_by('slug', $term_slug, 'category'); + if (!$term) { + return $query; + } + $cache_array = array($term); + update_term_cache($cache_array, 'category'); // caching query :) + $id = $term->term_id; + $query['category_name'] = $term->slug; // uri + $function = 'get_category_link'; + + // -> tag + elseif ( isset($query['tag']) ): + + $term = $this->get_term_by('slug', $query['tag'], 'post_tag'); + if (!$term) { + return $query; + } + $cache_array = array($term); + update_term_cache($cache_array, 'post_tag'); // caching query :) + $id = $term->term_id; + $query['tag'] = $term->slug; + $function = 'get_tag_link'; + + endif; + + + // -> taxonomy + $taxonomies = get_taxonomies( array( 'public' => true, '_builtin' => false ) ); + foreach ($taxonomies as $term_name): + if ( isset($query[$term_name]) ) { + + $term_slug = $this->get_last_slash( $query[$term_name] ); + $term = $this->get_term_by('slug', $term_slug, $term_name); + if (!$term) { + return $query; + } + $cache_array = array($term); + update_term_cache($cache_array, $term_name); // caching query :) + $id = $term; + $query[$term_name] = $term->slug; + $function = 'get_term_link'; + + } + endforeach; + + // -> home url + if ( empty($query) ) { + + $function = 'home_url'; + $id = ''; + + } + + // -> search + if (isset($query['s'])) { + + $id = $query['s']; + $function="get_search_link"; + + } + + if ( isset($function) ) { + + // parse all languages links + foreach( $this->get_enabled_languages() as $lang ) { + + $this->lang = $lang; + $this->current_url[$lang] = esc_url(apply_filters('qts_url_args', call_user_func($function, $id))); + } + + $this->lang = false; + } + + return $query; + } + + + + /** + * Parse a hierarquical name and extract the last one + * + * @param string $lang Page path + * @return string + * + * @since 1.0 + */ + public function get_current_url( $lang = false ) { + + if (!$lang) { + $lang = $this->get_lang(); + } + + if (isset($this->current_url[$lang]) && !empty($this->current_url[$lang])) { + return $this->current_url[$lang]; + } + return ''; + } + + + + /** + * Parse a hierarquical name and extract the last one + * + * @param string $slug Page path + * @return string + * + * @since 1.0 + */ + private function get_last_slash($slug) { + + $slug = rawurlencode( urldecode( $slug ) ); + $slug = str_replace('%2F', '/', $slug); + $slug = str_replace('%20', ' ', $slug); + $exploded_slug = explode('/', $slug); + + return array_pop( $exploded_slug ); + } + + + + /** + * Retrieves a page id given its path. + * + * @param string $page_path Page path + * @param string $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT. + * @param string $post_type Optional. Post type. Default page. + * @return mixed Null when complete. + * + * @since 1.0 + */ + private function get_page_id_by_path($page_path, $output = OBJECT, $post_type = 'page') { + global $wpdb; + + $page_path = rawurlencode(urldecode($page_path)); + $page_path = str_replace('%2F', '/', $page_path); + $page_path = str_replace('%20', ' ', $page_path); + $parts = explode( '/', trim( $page_path, '/' ) ); + $parts = array_map( 'esc_sql', $parts ); + $parts = array_map( 'sanitize_title_for_query', $parts ); + $in_string = "'". implode( "','", $parts ) . "'"; + $meta_key = $this->get_meta_key(); + $post_type_sql = $post_type; + $wpdb->escape_by_ref( $post_type_sql ); + + $pages = $wpdb->get_results( "SELECT $wpdb->posts.ID, $wpdb->posts.post_parent, $wpdb->postmeta.meta_value FROM $wpdb->posts,$wpdb->postmeta WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id AND $wpdb->postmeta.meta_key = '$meta_key' AND $wpdb->postmeta.meta_value IN ($in_string) AND ($wpdb->posts.post_type = '$post_type_sql' OR $wpdb->posts.post_type = 'attachment')", OBJECT_K ); + + $revparts = array_reverse( $parts ); + + $foundid = 0; + foreach ( (array) $pages as $page ) { + if ( $page->meta_value == $revparts[0] ) { + $count = 0; + $p = $page; + while ( $p->post_parent != 0 && isset( $pages[ $p->post_parent ] ) ) { + $count++; + $parent = $pages[ $p->post_parent ]; + if ( ! isset( $revparts[ $count ] ) || $parent->meta_value != $revparts[ $count ] ) { + break; + } + $p = $parent; + } + + if ( $p->post_parent == 0 && $count+1 == count( $revparts ) && $p->meta_value == $revparts[ $count ] ) { + $foundid = $page->ID; + break; + } + } + } + + if ( $foundid ) { + return $foundid; + + } else { + + $last_part = array_pop($parts); + $page_id = $wpdb->get_var( "SELECT ID FROM $wpdb->posts WHERE post_name = '$last_part' AND (post_type = '$post_type_sql' OR post_type = 'attachment')" ); + + if ( $page_id ) { + return $page_id; + } + } + + return null; + } + + + + + /** + * Retrieves a page given its path. + * + * @param string $page_path Page path + * @param string $output Optional. Output type. OBJECT, ARRAY_N, or ARRAY_A. Default OBJECT. + * @param string $post_type Optional. Post type. Default page. + * @return mixed Null when complete. + * + * @since 1.0 + */ + private function get_page_by_path($page_path, $output = OBJECT, $post_type = 'page') { + + $foundid = $this->get_page_id_by_path($page_path, $output, $post_type); + if ( $foundid ) { + return get_post( $foundid, $output ); + } + + return null; + } + + + + /** + * Ignores if the mod_rewrite func is the caller + * + * @return boolean + * + * @since 1.0 + */ + private function ignore_rewrite_caller() { + + $backtrace = debug_backtrace(); + + $ignore_functions = array('mod_rewrite_rules', 'save_mod_rewrite_rules', 'flush_rules', 'rewrite_rules', 'wp_rewrite_rules', 'query_vars'); + + if ( isset($backtrace['function']) ) { + if (in_array($backtrace['function'], $ignore_functions)) { + return true; + } + } else { + foreach ($backtrace as $trace) { + if ( isset($trace['function']) && in_array($trace['function'], $ignore_functions) ) { + return true; + } + } + } + + return false; + } + + + /** + * Retrieve the home url for a given site. + * + * @param int $blog_id (optional) Blog ID. Defaults to current blog. + * @param string $path (optional) Path relative to the home url. + * @param string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https'. + * @return string Home url link with optional path appended. + * + * @since 1.0 + */ + public function home_url($url, $path, $scheme, $blog_id) { + if ( !in_array( $scheme, array( 'http', 'https' ) ) ) { + $scheme = is_ssl() && !is_admin() ? 'https' : 'http'; + } + + if ( empty( $blog_id ) || !is_multisite() ) { + $url = get_option( 'home' ); + } else { + $url = get_blog_option( $blog_id, 'home' ); + } + + if ( 'http' != $scheme ) { + $url = str_replace( 'http://', "$scheme://", $url ); + } + + $ignore_caller = $this->ignore_rewrite_caller(); + + if ( !empty( $path ) && is_string( $path ) && strpos( $path, '..' ) === false ) { + $url .= '/' . ltrim( $path, '/' ); + } + + if ( !$ignore_caller ) { + $url = call_user_func($this->get_plugin_prefix() . 'convertURL', $url, $this->get_lang(), true); + } + + return $url; + } + + + + /** + * Filter that changes the permastruct depending .. on what? + * + * @param string $permastruct default permastruct given b wp_rewrite + * @param string $name the name of the extra permastruct + * @return string processed permastruct + * + * @since 1.0 + */ + public function get_extra_permastruct( $permastruct = false, $name = false ) { + + if ( !$name || !$permastruct ) { + return ''; + } + + if ( $base = $this->get_base_slug($name, $this->get_lang()) ) { + return "/$base/%$name%"; + } + + return $permastruct; + } + + + + /** + * Filter that translates the slug parts in a page link + * + * @param $link the link for the page generated by Wordpress + * @param $id the id of the page + * @return the link translated + * + * @since 1.0 + */ + public function post_type_link( $link, $post, $leavename, $sample ) { + global $wp_rewrite; + + if ( is_wp_error( $post ) ) { + return $post; + } + + $post_link = apply_filters( 'qts_permastruct', $wp_rewrite->get_extra_permastruct($post->post_type), $post->post_type); + + $slug = get_post_meta( $post->ID, $this->get_meta_key(), true ); + if (!$slug) { + $slug = $post->post_name; + } + + $draft_or_pending = isset($post->post_status) && in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) ); + + $post_type = get_post_type_object($post->post_type); + + if ( !empty($post_link) && ( !$draft_or_pending || $sample ) ) { + if ( ! $leavename ) { + if ( $post_type->hierarchical ) + $slug = $this->get_page_uri($post->ID); + $post_link = str_replace("%$post->post_type%", $slug, $post_link); + } + + $post_link = home_url( user_trailingslashit($post_link) ); + + } else { + + if ( $post_type->query_var && ( isset($post->post_status) && !$draft_or_pending ) ) { + $post_link = add_query_arg($post_type->query_var, $slug, ''); + } else { + $post_link = add_query_arg(array('post_type' => $post->post_type, 'p' => $post->ID), ''); + } + + $post_link = home_url($post_link); + } + + return $post_link; + } + + + + /** + * Filter that translates the slug in a post link + * + * @param $link the link generated by wordpress + * @param $post the post data + * @param $leavename parameter used by get_permalink. Whether to keep post name or page name. + * @return the link translated + * + * @since 1.0 + */ + public function post_link( $link, $post, $leavename ) { + global $q_config; //TODO: q_config : url_mode + + $rewritecode = array( + '%year%', + '%monthnum%', + '%day%', + '%hour%', + '%minute%', + '%second%', + $leavename? '' : '%postname%', + '%post_id%', + '%category%', + '%author%', + $leavename? '' : '%pagename%', + ); + + if ( empty($post->ID) ) { + return false; + } + + $permalink = $this->permalink_structure; + + if ( '' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')) ) { + $unixtime = strtotime($post->post_date); + + $category = ''; + if ( strpos($permalink, '%category%') !== false ) { + $cats = get_the_category($post->ID); + if ( $cats ) { + usort($cats, '_usort_terms_by_ID'); // order by ID + + $category = get_term_meta($cats[0]->term_id, $this->get_meta_key(), true ); + if (!$category) $category = $cats[0]->slug; + + if ( $parent = $cats[0]->parent ) + $category = $this->get_category_parents($parent, false, '/', true) . $category; + } + // show default category in permalinks, without + // having to assign it explicitly + if ( empty($category) ) { + $default_category = get_category( get_option( 'default_category' ) ); + + $default_category_slug = get_term_meta($default_category->term_id, $this->get_meta_key(), true ); + if (!$default_category_slug) $default_category_slug = $default_category->slug; + + $category = is_wp_error( $default_category ) ? '' : $default_category_slug; + } + } + + $author = ''; + if ( strpos($permalink, '%author%') !== false ) { + $authordata = get_userdata($post->post_author); + $author = $authordata->user_nicename; + } + + $date = explode(" ",date('Y m d H i s', $unixtime)); + + $post_slug = get_post_meta($post->ID, $this->get_meta_key(), true ); + if (!$post_slug) { + $post_slug = $post->post_name; + } + + $rewritereplace = + array( + $date[0], + $date[1], + $date[2], + $date[3], + $date[4], + $date[5], + $post_slug, + $post->ID, + $category, + $author, + $post_slug, + ); + $permalink = home_url( str_replace($rewritecode, $rewritereplace, $permalink)); + if ($q_config['url_mode'] != 1) { + $permalink = user_trailingslashit($permalink, 'single'); + } + } else { // if they're not using the fancy permalink option + $permalink = home_url('?p=' . $post->ID); + } + + return $permalink; + } + + + + /** + * Retrieve category parents with separator. + * + * @param int $id Category ID. + * @param bool $link Optional, default is false. Whether to format with link. + * @param string $separator Optional, default is '/'. How to separate categories. + * @param bool $nicename Optional, default is false. Whether to use nice name for display. + * @param array $visited Optional. Already linked to categories to prevent duplicates. + * @return string + * + * @since 1.0 + */ + private function get_category_parents( $id, $link = false, $separator = '/', $nicename = false, $visited = array() ) { + + $chain = ''; + if(phpversion() >= 5.4) { + $parent = get_category( $id ); + } else { + $parent = &get_category( $id ); + } + + if ( is_wp_error( $parent ) ) { + return $parent; + } + + if ( $nicename ) { + + $name = get_term_meta($parent->term_id, $this->get_meta_key(), true ); + if (!$name) { + $name = $parent->slug; + } + } else { + $name = $parent->name; + } + + if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) { + $visited[] = $parent->parent; + $chain .= $this->get_category_parents( $parent->parent, $link, $separator, $nicename, $visited ); + } + + if ( $link ) { + $chain .= 'name ) ) . '">'.$name.'' . $separator; + } else { + $chain .= $name.$separator; + } + + return $chain; + } + + + + + + /** + * Filter that translates the slug parts in a page link + * + * @param $link the link for the page generated by Wordpress + * @param $id the id of the page + * @return the link translated + * + * @since 1.0 + */ + public function _get_page_link( $link, $id ) { + global $post, $wp_rewrite, $q_config; //TODO: q_config : url_mode + + $current_post = $post; + + if ( !$id ) { + $id = (int) $post->ID; + } else { + if(phpversion() >= 5.4) { + $current_post = get_post($id); + } else { + $current_post = &get_post($id); + } + } + + $draft_or_pending = in_array( $current_post->post_status, array( 'draft', 'pending', 'auto-draft' ) ); + + $link = $wp_rewrite->get_page_permastruct(); + + if ( !empty($link) && ( isset($current_post->post_status) && !$draft_or_pending ) ) { + + $link = str_replace('%pagename%', $this->get_page_uri($id), $link); + + $link = trim($link, '/'); // hack + $link = home_url("/$link/"); // hack + + if ($q_config['url_mode'] != 1) + $link = user_trailingslashit($link, 'page'); + + } else { + + $link = home_url("?page_id=$id"); + } + + return $link; + } + + + + /** + * Builds URI for a page. + * + * Sub pages will be in the "directory" under the parent page post name. + * + * @param mixed $page Page object or page ID. + * @return string Page URI. + * + * @since 1.0 + */ + private function get_page_uri($page) { + + if ( ! is_object($page) ) { + $page = get_post($page); + } + + $uri = get_post_meta( $page->ID, $this->get_meta_key(), true ); + if (!$uri) { + $uri = $page->post_name; + } + + // A page cannot be it's own parent. + if ( $page->post_parent == $page->ID ) { + return $uri; + } + + while ($page->post_parent != 0) { + $page = get_post($page->post_parent); + + $page_name = get_post_meta( $page->ID, $this->get_meta_key(), true ); + if (!$page_name) { + $page_name = $page->post_name; + } + + $uri = $page_name . "/" . $uri; + } + + return $uri; + } + + + + /** + * Filter that translates the slug parts in a term link + * + * @param $link the link for the page generated by Wordpress + * @param $term object + * @param $taxonomy object + * @return the link translated + * + * @since 1.0 + */ + public function term_link( $link, $term, $taxonomy ) { + global $wp_rewrite; + + // parse normal term names for ?tag=tagname + if (empty($this->permalink_structure)) { return $link; } + + if ( !is_object($term) ) { + if ( is_int($term) ) { + $term = &get_term($term, $taxonomy); + } else { + $term = $this->get_term_by('slug', $term, $taxonomy); + } + } + + if ( !is_object($term) ) { + $term = new WP_Error('invalid_term', __('Empty Term', 'qts')); + } + + if ( is_wp_error( $term ) ) { + return $term; + } + + $taxonomy = $term->taxonomy; + + $termlink = apply_filters( 'qts_permastruct', $wp_rewrite->get_extra_permastruct($taxonomy), $taxonomy); + + $slug = get_term_meta( $term->term_id, $this->get_meta_key(), true ); + if (!$slug) { + $slug = $term->slug; + } + + $t = get_taxonomy($taxonomy); + + if ( empty($termlink) ) { + if ( 'category' == $taxonomy ) { + $termlink = '?cat=' . $term->term_id; + } elseif ( $t->query_var ) { + $termlink = "?$t->query_var=$slug"; + } else { + $termlink = "?taxonomy=$taxonomy&term=$slug"; + } + $termlink = home_url($termlink); + } else { + if ( $t->rewrite['hierarchical'] ) { + $hierarchical_slugs = array(); + $ancestors = get_ancestors($term->term_id, $taxonomy); + foreach ( (array)$ancestors as $ancestor ) { + $ancestor_term = get_term($ancestor, $taxonomy); + + $ancestor_slug = get_term_meta( $ancestor_term->term_id, $this->get_meta_key(), true ); + if (!$ancestor_slug) { + $ancestor_slug = $ancestor_term->slug; + } + + $hierarchical_slugs[] = $ancestor_slug; + } + $hierarchical_slugs = array_reverse($hierarchical_slugs); + $hierarchical_slugs[] = $slug; + $termlink = str_replace("%$taxonomy%", implode('/', $hierarchical_slugs), $termlink); + } else { + $termlink = str_replace("%$taxonomy%", $slug, $termlink); + } + $termlink = home_url( user_trailingslashit($termlink, 'category') ); + } + return $termlink; + } + + + + /** + * Get all Term data from database by Term field and data. + * + * @param (string) $field Either 'slug', 'name', or 'id' + * @param (string|int) $value Search for this term value + * @param (string) $taxonomy Taxonomy Name + * @param (string) $output Constant OBJECT, ARRAY_A, or ARRAY_N + * @param (string) $filter Optional, default is raw or no WordPress defined filter will applied. + * @return (mixed) Term Row from database. Will return false if $taxonomy does not exist or $term was not found. + * + * @since 1.0 + */ + private function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw') { + global $wpdb; + + $original_field = $field; + + if ( ! taxonomy_exists($taxonomy) ) { + return false; + } + + if ( 'slug' == $field ) { + $field = 'm.meta_key = \''.$this->get_meta_key().'\' AND m.meta_value'; + $value = sanitize_title($value); + if ( empty($value) ) + return false; + } else if ( 'name' == $field ) { + // Assume already escaped + $value = stripslashes($value); + $field = 't.name'; + } else { + $term = get_term( (int) $value, $taxonomy, $output, $filter); + if ( is_wp_error( $term ) ) + $term = false; + return $term; + } + + $term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t, $wpdb->term_taxonomy AS tt, $wpdb->termmeta AS m WHERE t.term_id = tt.term_id AND tt.term_id = m.term_id AND tt.taxonomy = %s AND $field = %s LIMIT 1", $taxonomy, $value) ); + + if ( !$term && 'slug' == $original_field ) { + $field = 't.slug'; + $term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND $field = %s LIMIT 1", $taxonomy, $value) ); + } + + if ( !$term ) { + return false; + } + + wp_cache_add($term->term_id, $term, $taxonomy); + + $term = apply_filters('get_term', $term, $taxonomy); + $term = apply_filters("get_$taxonomy", $term, $taxonomy); + $term = sanitize_term($term, $taxonomy, $filter); + + if ( $output == OBJECT ) { + return $term; + } elseif ( $output == ARRAY_A ) { + return get_object_vars($term); + } elseif ( $output == ARRAY_N ) { + return array_values(get_object_vars($term)); + } else { + return $term; + } + } + + + + /** + * Fix for: + * - Taxonomy names in Taxonomy Manage page + * - 'Popular Tags' in Taxonomy (Tags) Manage page + * - Category filter dropdown menu in Post Manage page + * - Category list in Post Edit page + * - 'Most Used' tags list in Post Edit page (but have issues when saving) + * + * @param (array) $terms + * @param (string|array) $taxonomy + * @since 1.2 + */ + function get_terms($terms, $taxonomy) { + + global $pagenow; + + if ( $pagenow != 'admin-ajax.php' ) { + + $meta = get_option('qtranslate_term_name'); + $lang = call_user_func($this->get_plugin_prefix() . 'getLanguage'); + + + if ( !empty( $terms ) ) { + foreach ($terms as $term_index => $term) { + // after saving, dont do anything + if( ( isset($_POST['action'] ) && $_POST['action'] == "editedtag") || + !is_object( $term ) ) { + return $terms; + } + if( isset( $meta[$term->name][$lang] ) ) { + $term->name = $meta[$term->name][$lang]; + } + } + } + } + return $terms; + } + + + + /** + * Fix for: + * - Taxonomy & custom taxonomy names in Post Manage page + * - List of tags already added to the post in Post + * - Edit page (but have issues when saving) + * + * @param (array) $terms + * @param (int|array) $obj_id + * @param (string|array) $taxonomy + * @param (array) $taxonomy + * @since 1.2 + */ + function get_object_terms($terms, $obj_id, $taxonomy, $args) { + + global $pagenow; + + // Although in post edit page the tags are translated, + // but when saving/updating the post Wordpress considers + // the translated tags as new tags. Due to this + // issue I limit this 'hack' to the post manage + // page only. + if ( $pagenow == 'edit.php' ) { + + // $taxonomy output seems to be wrapped + // in single quotes, thus remove them to + // make the output valid + $tax = str_replace("'", "", $taxonomy); + + // get the name from qtx + $meta = get_option('qtranslate_term_name'); + $lang = call_user_func($this->get_plugin_prefix() . 'getLanguage'); + + if ( !empty( $terms ) ) { + foreach ($terms as $term) { + if( isset( $meta[$term->name][$lang] ) ) { + $term->name = $meta[$term->name][$lang]; + } + } + } + + } + return $terms; + } + + + + /** + * hide quickedit slug + * + * @since 1.0 + */ + public function hide_quick_edit() { + echo "" . PHP_EOL; + echo "" . PHP_EOL; + } + + + + /** + * Hide auttomatically the wordpress slug box in edit terms page + * + * @since 1.0 + */ + public function hide_slug_box() { + global $pagenow; + switch ( $pagenow ): + case 'edit-tags.php': + + echo "" . PHP_EOL; + echo "" . PHP_EOL; + break; + /* + case 'post.php': + + echo "" . PHP_EOL; + echo "" . PHP_EOL; + break;*/ + endswitch; + } + /** + * Hide auttomatically the wordpress slug box in edit posts page + * User should still be able to use it if needed + * @since 1.0 + */ + public function remove_defaultslug_meta_box() { + + if (is_admin()) { + if( !current_user_can('manage_options') ) { + remove_meta_box('slugdiv', 'post', 'normal'); + } + } + } + + /** + * Creates a metabox for every post, page and post type avaiable + * + * @since 1.0 + */ + public function add_slug_meta_box() { + + if ( function_exists( 'add_meta_box' ) ) { + + $context = apply_filters("qts_admin_meta_box_context","side"); + $priority = apply_filters("qts_admin_meta_box_priority","high"); + + add_meta_box( 'qts_sectionid', __('Slug QTS', 'qts'), array(&$this, 'draw_meta_box'), 'post', $context, $priority); + add_meta_box( 'qts_sectionid', __('Slug QTS', 'qts'), array(&$this, 'draw_meta_box'), 'page', $context, $priority); + + foreach ( get_post_types( array('_builtin' => false ) ) as $ptype ) { + add_meta_box( 'qts_sectionid', __('Slug QTS', 'qts'), array(&$this, 'draw_meta_box'), $ptype, $context, $priority ); + } + } + } + + + + /** + * Shows the fields where insert the translated slugs in the post and page edit form. + * + * @param $post (object) current post object + * + * @since 1.0 + */ + public function draw_meta_box( $post ) { + global $q_config; // //TODO: q_config : language_name + + // Use nonce for verification + echo "" . PHP_EOL; + echo "" . PHP_EOL; + + foreach ($this->enabled_languages as $lang): + + $slug = get_post_meta( $post->ID, $this->get_meta_key($lang), true); + + $value = ( $slug ) ? htmlspecialchars( $slug , ENT_QUOTES ) : ''; + + echo "" . PHP_EOL; + echo "" . PHP_EOL; + echo "" . PHP_EOL; + echo "" . PHP_EOL; + + endforeach; + + echo '
' . PHP_EOL; + } + + + + /** + * Sanitize title as slug, if empty slug + * + * @param $post (object) the post object + * @param $slug (string) the slug name + * @param $lang (string) the language + * @return the slug validated + * + * @since 1.0 + */ + public function validate_post_slug( $slug, $post, $lang ) { + + $post_title = trim(call_user_func($this->get_plugin_prefix() . 'use',$lang, $_POST['post_title'])); + $post_name = get_post_meta($post->ID, $this->get_meta_key($lang), true); + if (!$post_name) { + $post_name = $post->post_name; + } + + //TODO: if has a slug, test and use it + //TODO: and then replace the default slug with the dafault language slug + $name = ( $post_title == '' || strlen($post_title) == 0 ) ? $post_name : $post_title; + + $slug = trim($slug); + + $slug = (empty($slug)) ? sanitize_title($name) : sanitize_title($slug); + + return htmlspecialchars( $slug , ENT_QUOTES ); + } + + + + /** + * Validates post slug against repetitions per language + * + * @param $post (object) the post object + * @param $slug (string) the slug name + * @param $lang (string) the language + * @return the slug validated + * + * @since 1.0 + */ + public function unique_post_slug( $slug, $post, $lang ) { + + $original_status = $post->post_status; + + if ( in_array($post->post_status, array('draft', 'pending')) ) { + $post->post_status = 'publish'; + } + + $slug = $this->wp_unique_post_slug( $slug, $post->ID, $post->post_status, $post->post_type, $post->post_parent, $lang ); + + $post->post_status = $original_status; + + return $slug; + } + + + + /** + * Computes a unique slug for the post and language, when given the desired slug and some post details. + * + * @param string $slug the desired slug (post_name) + * @param integer $post_ID + * @param string $post_status no uniqueness checks are made if the post is still draft or pending + * @param string $post_type + * @param integer $post_parent + * @return string unique slug for the post, based on language meta_value (with a -1, -2, etc. suffix) + * + * @since 1.0 + */ + public function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent, $lang ) { + if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) ) { + return $slug; + } + + global $wpdb, $wp_rewrite; + + $feeds = $wp_rewrite->feeds; + if ( ! is_array( $feeds ) ) { + $feeds = array(); + } + + $meta_key = $this->get_meta_key($lang); + if ( 'attachment' == $post_type ) { + // Attachment slugs must be unique across all types. + $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1"; + $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID ) ); + + if ( $post_name_check || in_array( $slug, $feeds ) || apply_filters( 'wp_unique_post_slug_is_bad_attachment_slug', false, $slug ) ) { + $suffix = 2; + do { + // TODO: update unique_slug :: differs from current wp func ( 4.3.1 ) + $alt_post_name = substr ($slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"; + $post_name_check = $wpdb->get_var( $wpdb->prepare($check_sql, $alt_post_name, $post_ID ) ); + $suffix++; + } while ( $post_name_check ); + $slug = $alt_post_name; + } + } else { + // TODO: update unique_slug :: missing hieararchical from current wp func ( 4.3.1 ) + // Post slugs must be unique across all posts. + $check_sql = "SELECT $wpdb->postmeta.meta_value FROM $wpdb->posts,$wpdb->postmeta WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id AND $wpdb->postmeta.meta_key = '%s' AND $wpdb->postmeta.meta_value = '%s' AND $wpdb->posts.post_type = %s AND ID != %d LIMIT 1"; + $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $meta_key, $slug, $post_type, $post_ID ) ); + + // TODO: update unique_slug :: missing check for conflict with dates archive from current wp func ( 4.3.1 ) + if ( $post_name_check || in_array( $slug, $feeds ) || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) { + $suffix = 2; + do { + // TODO: update unique_slug :: same as above: differs from current wp func ( 4.3.1 ) + $alt_post_name = substr( $slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix"; + $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $meta_key, $alt_post_name, $post_type, $post_ID ) ); + $suffix++; + } while ( $post_name_check ); + $slug = $alt_post_name; + } + } + + return $slug; + } + + + + + /** + * Saves the translated slug when the page is saved + * + * @param $post_id the post id + * @param $post the post object + * + * @since 1.0 + */ + public function save_postdata( $post_id, $post ) { + + $post_type_object = get_post_type_object( $post->post_type); + + + if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) // check autosave + || (!isset($_POST['post_ID']) || $post_id != $_POST['post_ID']) // check revision + || (isset($_POST['qts_nonce']) && !wp_verify_nonce( $_POST['qts_nonce'], 'qts_nonce')) // verify nonce + || (!current_user_can($post_type_object->cap->edit_post, $post_id))) { // check permission + return $post_id; + } + foreach ($this->get_enabled_languages() as $lang) { + + // check required because it is not available inside quick edit + if (isset($_POST["qts_{$lang}_slug"])) { + $meta_name = $this->get_meta_key($lang); + $meta_value = apply_filters( 'qts_validate_post_slug', $_POST["qts_{$lang}_slug"], $post, $lang); + delete_post_meta($post_id, $meta_name); + update_post_meta($post_id, $meta_name, $meta_value); + } + } + } + + + + /** + * Display multiple input fields, one per language + * + * @param $term the term object + * + * @since 1.0 + */ + public function show_term_fields( $term ) { + global $q_config; //TODO: q_config : language_name + + // prints the fields in edit page + if (isset($_GET['action']) && $_GET['action'] == 'edit' ): + + echo "" . PHP_EOL; + echo "" . PHP_EOL; + + foreach( $this->enabled_languages as $lang ) { + + $slug = (is_object($term)) ? get_term_meta( $term->term_id, $this->get_meta_key($lang), true ) : ''; + + $value = ( $slug ) ? htmlspecialchars( $slug , ENT_QUOTES ) : ''; + + echo "" . PHP_EOL; + echo "" . PHP_EOL; + echo "" . PHP_EOL; + + } + + echo '
'; + + // prints the fields in new page + else: + echo "" . PHP_EOL; + echo "
" . PHP_EOL; + foreach( $this->enabled_languages as $lang ) { + + echo "
" . PHP_EOL; + + $slug = (is_object($term)) ? get_term_meta( $term->term_id, $this->get_meta_key($lang), true ) : ''; + + $value = ( $slug ) ? htmlspecialchars( $slug , ENT_QUOTES ) : ''; + + echo "" . PHP_EOL; + echo "" . PHP_EOL; + echo '
'; + + + } + echo '
'; + endif; + } + + + + /** + * Sanitize title as slug, if empty slug + * + * @param $term (object) the term object + * @param $slug (string) the slug name + * @param $lang (string) the language + * @return the slug validated + * + * @since 1.0 + */ + public function validate_term_slug( $slug, $term, $lang ) { + + global $q_config; //TODO: q_config : term_name + + $term_key = call_user_func($this->get_plugin_prefix() . 'split',$term->name); + // after split we will get array (with language code as a key ) + + $term_key = $term_key[$this->default_language]; + + $name_in_lang = $q_config['term_name'][$term_key][$lang]; + + $ajax_name = 'new' . $term->taxonomy; + $post_name = isset($_POST['name']) ? $_POST['name'] : ''; + $term_name = isset($_POST[$ajax_name]) ? trim($_POST[$ajax_name]) : $post_name; + + if (empty($term_name)) { + return $slug; + } + + $name = ( $name_in_lang == '' || strlen($name_in_lang) == 0 ) ? $term_name : $name_in_lang; + $slug = trim($slug); + $slug = (empty($slug)) ? sanitize_title($name) : sanitize_title($slug); + return htmlspecialchars( $slug , ENT_QUOTES ); + } + + + + /** + * Will make slug unique per language, if it isn't already. + * + * @param string $slug The string that will be tried for a unique slug + * @param object $term The term object that the $slug will belong too + * @param object $lang The language reference + * @return string Will return a true unique slug. + * + * @since 1.0 + */ + public function unique_term_slug($slug, $term, $lang) { + + global $wpdb; + + $meta_key_name = $this->get_meta_key($lang); + $query = $wpdb->prepare("SELECT term_id FROM $wpdb->termmeta WHERE meta_key = '%s' AND meta_value = '%s' AND term_id != %d ", $meta_key_name, $slug, $term->term_id); + $exists_slug = $wpdb->get_results($query); + + if ( empty($exists_slug) ) { + return $slug; + } + + // If we didn't get a unique slug, try appending a number to make it unique. + $query = $wpdb->prepare("SELECT meta_value FROM $wpdb->termmeta WHERE meta_key = '%s' AND meta_value = '%s' AND term_id != %d", $meta_key_name, $slug, $term->term_id); + + if ( $wpdb->get_var( $query ) ) { + $num = 2; + do { + $alt_slug = $slug . "-$num"; + $num++; + $slug_check = $wpdb->get_var( + $wpdb->prepare( + "SELECT meta_value FROM $wpdb->termmeta WHERE meta_key = '%s' AND meta_value = '%s'", + $meta_key_name, + $alt_slug) ); + } while ( $slug_check ); + $slug = $alt_slug; + } + + return $slug; + } + + + + /** + * Display multiple input fields, one per language + * + * @param $term_id the term id + * @param $tt_id the term taxonomy id + * @param $taxonomy the term object + * + * @since 1.0 + */ + public function save_term( $term_id, $tt_id, $taxonomy ) { + + $cur_screen = get_current_screen(); + if ( (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) // check autosave + || ( !current_user_can('edit_posts') ) // check permission + || ( isset($cur_screen) && $cur_screen->id === "nav-menus") + ) { + return $term_id; + } + + $term = get_term( $term_id, $taxonomy); + foreach( $this->get_enabled_languages() as $lang ) { + $meta_name = $this->get_meta_key($lang); + + //43LC: when at the post edit screen and creating a new tag + // the $slug comes from $_POST with the value of the post slug, + // not with the term slug. + if ($_POST['action'] == "editpost") { + // so we use the slug wp gave it + $term_slug = $term->slug; + } else { + // otherwise, its the edit term screen + $term_slug = $_POST["qts_{$lang}_slug"]; + } + + $meta_value = apply_filters( 'qts_validate_term_slug', $term_slug, $term, $lang); + + delete_term_meta($term_id, $meta_name); + update_term_meta($term_id, $meta_name, $meta_value); + } + } + + + + /** + * deletes termmeta rows associated with the term + * + * @since 1.0 + */ + public function delete_term($term_id, $tt_id, $taxonomy) { + global $wpdb; + + $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->termmeta WHERE term_id = %d", $term_id ) ); + } + + + + /** + * creates and prints the forms and hides the default fields + * @param object $term the term object + * @since 1.1.12 + * + * TODO: change Slug column and View link + * TODO: move code into js file + * + */ + public function qts_modify_term_form($term) { + echo "\n"; + } + + /** + * Helper for qts_modify_term_form_for + * @param string $id the term id + * @param object #term the term + * @param string $language the term name + * @param string $action the term name + * @return string $html the new input fields + * @since 1.1.12 + * TODO: use DocumentFragment + */ + private function qts_insert_term_input($id,$name, $termname, $language,$action){ + global $q_config; //TODO: q_config : language_name, term_name + $html = ""; + if( $action === "new") { + $html =" + var il = document.getElementsByTagName('input'), + d = document.createElement('div'), + l = document.createTextNode('".$name." (".$q_config['language_name'][$language].")'), + ll = document.createElement('label'), + i = document.createElement('input'), + ins = null; + for(var j = 0; j < il.length; j++) { + if(il[j].id=='".$id."') { + ins = il[j]; + break; + } + } + i.type = 'text'; + i.id = i.name = ll.htmlFor ='qtrans_term_".$language."'; + "; + } elseif ( $action === "edit") { + $html =" + var tr = document.createElement('tr'), + th = document.createElement('th'), + ll = document.createElement('label'), + l = document.createTextNode('".$name." (".$q_config['language_name'][$language].")'), + td = document.createElement('td'), + i = document.createElement('input'), + ins = document.getElementById('".$id."'); + i.type = 'text'; + i.id = i.name = ll.htmlFor ='qtrans_term_".$language."'; + "; + } + if(isset($q_config['term_name'][$termname][$language])) { + $html .=" + i.value = '".addslashes(htmlspecialchars_decode($q_config['term_name'][$termname][$language], ENT_QUOTES))."';"; + //43LC: applied ENT_QUOTES to both edit and new forms. + } else { + $html .=" + if (ins != null) + i.value = ins.value; + "; + } + + if($language == $this->default_language) { + $html .=" + i.onchange = function() { + var il = document.getElementsByTagName('input'), + ins = null; + for(var j = 0; j < il.length; j++) { + if(il[j].id=='".$id."') { + ins = il[j]; + break; + } + } + if (ins != null) + ins.value = document.getElementById('qtrans_term_".$language."').value; + }; + "; + } + if( $action === "new") { + $html .=" + if (ins != null) + ins = ins.parentNode; + d.className = 'form-field form-required'; + ll.appendChild(l); + d.appendChild(ll); + d.appendChild(i); + if (ins != null) + ins.parentNode.insertBefore(d,ins); + "; + } elseif ( $action === "edit") { + $html .=" + ins = ins.parentNode.parentNode; + tr.className = 'form-field form-required'; + th.scope = 'row'; + th.vAlign = 'top'; + ll.appendChild(l); + th.appendChild(ll); + tr.appendChild(th); + td.appendChild(i); + tr.appendChild(td); + ins.parentNode.insertBefore(tr,ins); + "; + } + return $html; + } + /** + * adds support for qtranslate in taxonomies + * + * @since 1.0 + */ + public function taxonomies_hooks() { + + $taxonomies = $this->get_public_taxonomies(); + + if ($taxonomies) { + foreach ($taxonomies as $taxonomy ) { + add_action( $taxonomy->name.'_add_form', array(&$this, 'qts_modify_term_form')); + add_action( $taxonomy->name.'_edit_form', array(&$this, 'qts_modify_term_form')); + add_action( $taxonomy->name.'_add_form_fields', array(&$this, 'show_term_fields')); + add_action( $taxonomy->name.'_edit_form_fields', array(&$this, 'show_term_fields') ); + add_filter('manage_edit-'.$taxonomy->name.'_columns', array(&$this, 'taxonomy_columns')); + add_filter('manage_'.$taxonomy->name.'_custom_column', array(&$this, 'taxonomy_custom_column'), 0, 3); + } + } + } + + + + /* + * Bug fix for slug column in taxonomies + * + * @since 1.0 + */ + public function taxonomy_columns($columns) { + unset($columns['slug']); + unset($columns['posts']); + + $columns['qts-slug'] = __('Slug', 'qts'); + $columns['posts'] = __('Posts', 'qts'); + + return $columns; + } + + + + /* + * Bug fix for slug column in taxonomies + * + * @since 1.0 + */ + public function taxonomy_custom_column($str, $column_name, $term_id) { + + switch ($column_name) { + case 'qts-slug': + echo get_term_meta($term_id, $this->get_meta_key(), true); + break; + } + return false; + } + + + + + /** + * Bug fix for multisite blog names + * + * @since 1.0 + */ + public function blog_names($blogs) { + + foreach ($blogs as $blog) { + $blog->blogname = __($blog->blogname); + } + + return $blogs; + } + + + + /** + * Initialise the Language Widget selector + * + * @since 1.0 + */ + public function widget_init() { + + if (class_exists('qTranslateWidget')) { + unregister_widget('qTranslateWidget'); + } + if (class_exists('mqTranslateWidget')) { + unregister_widget('mqTranslateWidget'); + } + if (class_exists('ppqTranslateWidget')) { + unregister_widget('ppqTranslateWidget'); + } + + //if (class_exists('qTranslateXWidget')) {//it has additional features some people use. + // unregister_widget('qTranslateXWidget'); + //} + + register_widget('QtranslateSlugWidget'); + } + + + + /** + * remove some default dashboard Widgets on Desktop + * + * @since 1.0 + * @deprecated + */ + function remove_dashboard_widgets() { + global $wp_meta_boxes; + unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_quick_press']); + } + + + + /** + * adds support for qtranslate nav menus + * + * @since 1.0 + */ + public function fix_nav_menu() { + global $pagenow; + + if( $pagenow != 'nav-menus.php' ) { + return; + } + //FIXME: fix the nav menu box + // wp_enqueue_script( 'nav-menu-query', plugins_url( 'assets/js/qts-nav-menu-min.js' , dirname(__FILE__ ) ), 'nav-menu', '1.0' ); + // add_meta_box( 'qt-languages', __('Languages', 'qts'), array(&$this, 'nav_menu_meta_box'), 'nav-menus', 'side', 'default' ); + } + + + + /** + * draws meta box for select language + * + * @since 1.0 + */ + public function nav_menu_meta_box() { + global $q_config; + echo '

'; + foreach($q_config['enabled_languages'] as $id => $language) { + $checked = ($language == $q_config['language']) ? ' checked="checked"' : ''; + echo '

'; + echo '

'; + } + echo '

'; + echo '

'; + echo '

'; + } + + + + /** + * Language select function for templating + * + * @param $type (string) choose the type of menu: 'text', 'image', 'both', 'dropdown' + * @param $args (array) some args for draw the menu: array( 'id', 'class', 'short' ); + * + * @since 1.0 + */ + public function language_menu( $type = "text", $args = array() ) { + global $q_config; + + + // default arguments + $defaults = array( + 'id' => "qts-lang-menu", + 'class' => "qts-lang-menu", + 'short' => false + ); + $args = wp_parse_args( $args, $defaults ); + + $languages = call_user_func($this->get_plugin_prefix() . 'getSortedLanguages'); + + // every type + switch ( $type ) { + + case 'image': + case 'text': + case 'both': + + $baseurl = dirname(plugins_url()); + $num_languages = count($languages); + echo "". PHP_EOL; + + break; + + case 'dropdown': + + echo "". PHP_EOL; + + break; + } + + } +} diff --git a/modules/slugs/includes/qtranslate-slug-settings-options.php b/modules/slugs/includes/qtranslate-slug-settings-options.php new file mode 100644 index 00000000..7a33c1e7 --- /dev/null +++ b/modules/slugs/includes/qtranslate-slug-settings-options.php @@ -0,0 +1,179 @@ + $lang) { + $label = sprintf( __('Slug (%s)', 'qts'), $q_config['language_name'][$lang] ); + $choices[] = "$label|$lang"; // prints: 'Slug (English)|en' ( $name = books ) + } + + return $choices; +} + + + +/** + * Define our form fields (settings) for displaying the default styles + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.1.7 + * + * @return array + */ +function qts_options_page_styles() { + + + $options[] = array( + "section" => "styles", + "id" => QTS_PREFIX . "styles", + "title" => __('Change styles type', 'qts'), + "desc" => array( + __("adds a file (qts-default.css) to the theme's header.", "qts"), + __("adds a minified ( slighlty faster) file (qts-default.min.css) to the theme's header.", "qts"), + __("prints the styles directly into the theme's header.", "qts"), + __("neither include not print the default style.", "qts") + ), + "type" => "multi-radio", + 'class' => 'qts-style', + "choices" => array( + __("file", "qts"), + __("minified", "qts"), + __("inline", "qts"), + __("none", "qts") + ), + "std" => "file" + ); + + return $options; +} + + + +/** + * Define our form fields (settings) + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + * @return array + */ +function qts_options_page_fields() { + + $post_types = get_post_types( array('_builtin' => false, 'public' => true ), 'objects'); + + // each post type + foreach ($post_types as $post_type): + + $options[] = array( + "section" => "post_types", + "id" => QTS_PREFIX . "post_type_" . $post_type->name, + "title" => $post_type->labels->singular_name, + "desc" => sprintf( __( 'http://example.org/%s/some-%s/', 'qts' ), $post_type->name, $post_type->name), + 'class' => 'qts-slug', + "type" => "multi-text", + "choices" => get_multi_txt_choices( $post_type->name), + "std" => "" + ); + + endforeach; + // end each post type + + $options[] = array( + "section" => "taxonomies", + "id" => QTS_PREFIX . "taxonomy_category", + "title" => __( 'Categories', 'qts' ), + "desc" => __( 'http://example.org/category/some-category/', 'qts' ), + "type" => "multi-text", + 'class' => 'qts-slug', + "choices" => get_multi_txt_choices('category'), + "std" => "" + ); + + $options[] = array( + "section" => "taxonomies", + "id" => QTS_PREFIX . "taxonomy_post_tag", + "title" => __( 'Tags', 'qts' ), + "desc" => __( 'http://example.org/tag/some-tag/', 'qts' ), + "type" => "multi-text", + 'class' => 'qts-slug', + "choices" => get_multi_txt_choices('post_tag'), + "std" => "" + ); + + + $taxonomies = get_taxonomies( array( 'public' => true, 'show_ui' => true, '_builtin' => false ), 'object' ); + + // each extra taxonomy + foreach ($taxonomies as $taxonomy): + + $options[] = array( + "section" => "taxonomies", + "id" => QTS_PREFIX . "taxonomy_" . $taxonomy->name, + "title" => $taxonomy->labels->singular_name, + "desc" => sprintf( __( 'http://example.org/%s/some-%s/', 'qts' ), $taxonomy->name, $taxonomy->name ), + "type" => "multi-text", + 'class' => 'qts-slug', + "choices" => get_multi_txt_choices( $taxonomy->name), + "std" => "" + ); + + endforeach; + // end each extra taxonomy + + + return $options; +} + + + +/** + * Contextual Help + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + */ +function qts_options_page_contextual_help() { + + + $text = "

" . __('Qtranslate Settings - Contextual Help','qts') . "

"; + $text .= "

" . __('Contextual help goes here. You may want to use different html elements to format your text as you want.','qts') . "

"; + + return $text; +} \ No newline at end of file diff --git a/modules/slugs/includes/qtranslate-slug-settings.php b/modules/slugs/includes/qtranslate-slug-settings.php new file mode 100644 index 00000000..dbcc2d10 --- /dev/null +++ b/modules/slugs/includes/qtranslate-slug-settings.php @@ -0,0 +1,815 @@ + 'default_field', // the ID of the setting in our options array, and the ID of the HTML form element + 'title' => 'Default Field', // the label for the HTML form element + 'desc' => 'This is a default description.', // the description displayed under the HTML form element + 'std' => '', // the default value for this setting + 'type' => 'text', // the HTML form element to use + 'section' => 'main_section', // the section this setting belongs to must match the array key of a section in qts_options_page_sections() + 'choices' => array(), // (optional): the values in radio buttons or a drop-down menu + 'class' => '' // the HTML form element class. Is used for validation purposes and may be also use for styling if needed. + ); + + // "extract" to be able to use the array keys as variables in our function output below + extract( wp_parse_args( $args, $defaults ) ); + + // additional arguments for use in form field output in the function qts_show_form_field! + $field_args = array( + 'type' => $type, + 'id' => $id, + 'desc' => $desc, + 'std' => $std, + 'choices' => $choices, + 'label_for' => $id, + 'class' => $class + ); + + + + add_settings_field( $id, $title, 'qts_show_form_field', __FILE__, $section, $field_args ); + +} + + + +/** + * Register our setting, settings sections and settings fields + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + */ +function qts_register_settings(){ + + // get the settings sections array + $settings_output = qts_get_settings(); + $qts_option_name = $settings_output['qts_option_name']; + + //setting + register_setting($qts_option_name, $qts_option_name, 'qts_validate_options' ); + + //sections + if(!empty($settings_output['qts_page_sections'])){ + // call the "add_settings_section" for each! + foreach ( $settings_output['qts_page_sections'] as $id => $title ) { + add_settings_section( $id, $title, 'qts_section_fn', __FILE__); + } + } + + //fields + if(!empty($settings_output['qts_page_fields'])){ + // call the "add_settings_field" for each! + foreach ($settings_output['qts_page_fields'] as $option) { + qts_create_settings_field($option); + } + } + //style + if(!empty($settings_output['qts_page_styles'])){ + // call the "add_settings_field" for each + foreach ($settings_output['qts_page_styles'] as $styleoption) { + qts_create_settings_field($styleoption); + } + } +} +add_action( 'admin_init', 'qts_register_settings' ); + + + +/** + * Group scripts (js & css) + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + */ +function qts_settings_scripts() { + global $qtranslate_slug; + + wp_enqueue_style('qts_theme_settings_css', plugins_url( 'assets/css/qts-settings.css' , dirname(__FILE__) ) ); + wp_enqueue_script( 'qts_theme_settings_js', plugins_url( 'assets/js/qts-settings.js' , dirname(__FILE__) ), array('jquery')); + + /** + * @deprecated + */ + if ($qtranslate_slug->check_old_data()) { + wp_enqueue_script('qts_theme_settings_upgrade_js', plugins_url( 'assets/js/qts-settings-upgrade.js' , dirname(__FILE__) ), array('jquery') ); + } +} + +add_action( 'admin_head', 'qts_settings_scripts' ); + +/** + * The Admin menu page + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + */ +function qts_add_menu() { + global $current_screen; + + $settings_output = qts_get_settings(); + // collect our contextual help text + $qts_contextual_help = $settings_output['qts_contextual_help']; + + // Display Settings Page link under the "Appearance" Admin Menu + $qts_settings_page = add_options_page(__('Qtranslate Slug options', 'qts'), __('Slug options', 'qts'), 'manage_options', QTS_PAGE_BASENAME, 'qts_show_settings_page'); +} +add_action( 'admin_menu', 'qts_add_menu' ); + + + +//////////////////////////////////////////////////////////////////////////////////////// + +// Callback functions + + + +/** + * Section HTML, displayed before the first option + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + * @return echoes output + */ +function qts_section_fn($page_section = false) { + + if ( !$page_section || !isset($page_section['id']) ) return; + + switch ($page_section['id']) { + case 'post_types': + + echo "

" . __('For example, the post_type books, in Spanish would be displayed as http://example.org/es/libros/post-type-name/. If you leave this blank will use the default option when you registered the post_type.', 'qts') . "

"; + break; + + case 'taxonomies': + + echo "

" . __('For example, the taxonomy category, in Spanish would be displayed as http://example.org/es/categoria/taxonomy-name/. If you leave this blank will use the default option when you registered the taxonomy (if you previously setup a base permastruct for categories or tags in permalinks page, these bases will be overwritten by the translated ones).', 'qts') . "

"; + break; + case 'styles': + + echo "

" . __('The default styles are very minimal, and you can include them or not.', 'qts') . "

\n"; + break; + } +} + + + +/** + * Form Fields HTML: all form field types share the same function + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + * @return echoes output + */ +function qts_show_form_field($args = array()) { + global $qtranslate_slug; + + extract( $args ); + + // get the settings sections array + $settings_output = qts_get_settings(); + $options = $qtranslate_slug->get_options(); + + // pass the standard value if the option is not yet set in the database + if ( !isset( $options[$id] ) && 'type' != 'checkbox' ) { + $options[$id] = $std; + } + + // additional field class. output only if the class is defined in the create_setting arguments + $field_class = ($class != '') ? ' ' . $class : ''; + + // switch html display based on the setting type. + switch ( $type ) { + case 'text': + $options[$id] = stripslashes($options[$id]); + $options[$id] = esc_attr( $options[$id]); + echo ""; + echo ($desc != '') ? "
$desc" : ""; + break; + + case "multi-text": + foreach($choices as $item) { + + $item = explode("|",$item); // cat_name|cat_slug + $item[0] = esc_html__($item[0], 'qts'); + + if (!empty($options[$id])) { + foreach ($options[$id] as $option_key => $option_val){ + if ($item[1] == $option_key) { + $value = $option_val; + } + } + } else { + $value = ''; + } + echo "" . $item[0] . ": " . + "
"; + //echo "$item[0]:
"; + } + echo ($desc != '') ? "$desc" : ""; + break; + + case 'textarea': + $options[$id] = stripslashes($options[$id]); + $options[$id] = esc_html( $options[$id]); + echo ""; + echo ($desc != '') ? "
$desc" : ""; + break; + + case 'select': + echo ""; + echo ($desc != '') ? "
$desc" : ""; + break; + + case 'select2': + echo ""; + echo ($desc != '') ? "
$desc" : ""; + break; + + case 'checkbox': + echo ""; + echo ($desc != '') ? "
$desc" : ""; + break; + + case "multi-checkbox": + foreach($choices as $item) { + + $item = explode("|",$item); + $item[0] = esc_html($item[0], 'qts'); + + $checked = ''; + + if ( isset($options[$id][$item[1]]) ) { + if ( $options[$id][$item[1]] == 'true') { + $checked = 'checked="checked"'; + } + } + + echo " $item[0]
"; + } + echo ($desc != '') ? "
$desc" : ""; + break; + + case "multi-radio": + foreach($choices as $index => $item) { + + $item = explode("|",$item); + $item_key = (count($item) > 1) ? esc_html($item[0], 'qts') : esc_html(end($item), 'qts'); + $item_value = (count($item) > 1) ? esc_html($item[1], 'qts') : esc_html(end($item), 'qts'); + + $checked = ''; + + if ( isset($options[$id]) && $options[$id] === $item_value) { + $checked = 'checked="checked"'; + } + + echo ""; + } + echo (!is_array($desc) && $desc != '') ? "
$desc" : ""; + break; + } +} + + + +/** + * Validates base slugs per 'type' (post_type | taxonomy) and 'language' + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + */ +function qts_sanitize_bases($base_slugs = false) { + + if ( !$base_slugs || empty($base_slugs) ) return; + + $base_slugs_processed = array(); + $base_founded = array(); + + // changing array structure + foreach ($base_slugs as $type => $base) { + foreach ($base as $lang => $value) { + if ($value != ""): + $base_value = $value; + $count = 2; + while (in_array($value, $base_founded)) { + $value = "$base_value-$count"; + $count++; + } + $base_founded[] = $base_slugs[$type][$lang] = $value; + endif; + } + } + + return $base_slugs; +} + + + +/** + * Admin Settings Page HTML + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + * @return echoes output + */ +function qts_show_settings_page() { + // get the settings sections array + $settings_output = qts_get_settings(); +?> +
+
+

+ +

pretty permalinks, in this section you can translate the URLs bases for public post_types, categories, tags and taxonomies.', 'qts'); ?>

+ +
+ + +

+ ; +

+ +

+ +
+
+ array('href' => array (),'title' => array ()), + 'b' => array(), + 'em' => array (), + 'i' => array (), + 'strong' => array() + ); + // trim whitespace + $input[$option['id']] = trim($input[$option['id']]); + // find incorrectly nested or missing closing tags and fix markup + $input[$option['id']] = force_balance_tags($input[$option['id']]); + // need to add slashes still before sending to the database + $input[$option['id']] = wp_kses( $input[$option['id']], $allowed_html); + + $valid_input[$option['id']] = addslashes($input[$option['id']]); + break; + } + break; + + case "multi-text": + // this will hold the text values as an array of 'key' => 'value' + unset($textarray); + + $text_values = array(); + foreach ($option['choices'] as $k => $v ) { + // explode the connective + $pieces = explode("|", $v); + + $text_values[] = $pieces[1]; + } + + foreach ($text_values as $v ) { + + // Check that the option isn't empty + if (!empty($input[$option['id'] . '|' . $v])) { + // If it's not null, make sure it's sanitized, add it to an array + switch ($option['class']) { + // different sanitation actions based on the class create you own cases as you need them + + //for numeric input + case 'numeric': + //accept the input only if is numberic! + $input[$option['id'] . '|' . $v]= trim($input[$option['id'] . '|' . $v]); // trim whitespace + $input[$option['id'] . '|' . $v]= (is_numeric($input[$option['id'] . '|' . $v])) ? $input[$option['id'] . '|' . $v] : ''; + break; + + case 'qts-slug': + // strip all html tags and white-space. + $exploded_types = explode('_', $option['id']); + $type_ = end($exploded_types ); + $input[$option['id'] . '|' . $v]= sanitize_title( sanitize_text_field( $input[$option['id'] . '|' . $v] ) ); + $input[$option['id'] . '|' . $v]= addslashes($input[$option['id'] . '|' . $v]); + break; + + // a "cover-all" fall-back when the class argument is not set + default: + // strip all html tags and white-space. + $input[$option['id'] . '|' . $v]= sanitize_text_field($input[$option['id'] . '|' . $v]); // need to add slashes still before sending to the database + $input[$option['id'] . '|' . $v]= addslashes($input[$option['id'] . '|' . $v]); + break; + } + // pass the sanitized user input to our $textarray array + $textarray[$v] = $input[$option['id'] . '|' . $v]; + + } else { + $textarray[$v] = ''; + } + } + // pass the non-empty $textarray to our $valid_input array + if (!empty($textarray)) { + $valid_input[$option['id']] = $textarray; + } + break; + + case 'textarea': + //switch validation based on the class! + switch ( $option['class'] ) { + //for only inline html + case 'inlinehtml': + // accept only inline html + // trim whitespace + $input[$option['id']] = trim($input[$option['id']]); + // find incorrectly nested or missing closing tags and fix markup + $input[$option['id']] = force_balance_tags($input[$option['id']]); + //wp_filter_kses expects content to be escaped! + $input[$option['id']] = addslashes($input[$option['id']]); + //calls stripslashes then addslashes + $valid_input[$option['id']] = wp_filter_kses($input[$option['id']]); + break; + + //for no html + case 'nohtml': + //accept the input only after stripping out all html, extra white space etc! + // need to add slashes still before sending to the database + $input[$option['id']] = sanitize_text_field($input[$option['id']]); + $valid_input[$option['id']] = addslashes($input[$option['id']]); + break; + + //for allowlinebreaks + case 'allowlinebreaks': + //accept the input only after stripping out all html, extra white space etc! + // need to add slashes still before sending to the database + $input[$option['id']] = wp_strip_all_tags($input[$option['id']]); + $valid_input[$option['id']] = addslashes($input[$option['id']]); + break; + + // a "cover-all" fall-back when the class argument is not set + default: + // accept only limited html + //my allowed html + $allowed_html = array( + 'a' => array('href' => array (),'title' => array ()), + 'b' => array(), + 'blockquote' => array('cite' => array ()), + 'br' => array(), + 'dd' => array(), + 'dl' => array(), + 'dt' => array(), + 'em' => array (), + 'i' => array (), + 'li' => array(), + 'ol' => array(), + 'p' => array(), + 'q' => array('cite' => array ()), + 'strong' => array(), + 'ul' => array(), + 'h1' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()), + 'h2' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()), + 'h3' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()), + 'h4' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()), + 'h5' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()), + 'h6' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()) + ); + + $input[$option['id']] = trim($input[$option['id']]); // trim whitespace + $input[$option['id']] = force_balance_tags($input[$option['id']]); // find incorrectly nested or missing closing tags and fix markup + $input[$option['id']] = wp_kses( $input[$option['id']], $allowed_html); // need to add slashes still before sending to the database + $valid_input[$option['id']] = addslashes($input[$option['id']]); + break; + } + break; + + case 'select': + // check to see if the selected value is in our approved array of values! + $valid_input[$option['id']] = (in_array( $input[$option['id']], $option['choices']) ? $input[$option['id']] : '' ); + break; + + case 'select2': + // process $select_values + $select_values = array(); + foreach ($option['choices'] as $k => $v) { + // explode the connective + $pieces = explode("|", $v); + + $select_values[] = $pieces[1]; + } + // check to see if selected value is in our approved array of values! + $valid_input[$option['id']] = (in_array( $input[$option['id']], $select_values) ? $input[$option['id']] : '' ); + break; + + case 'checkbox': + // if it's not set, default to null! + if (!isset($input[$option['id']])) { + $input[$option['id']] = null; + } + // Our checkbox value is either 0 or 1 + $valid_input[$option['id']] = ( $input[$option['id']] == 1 ? 1 : 0 ); + break; + + case 'multi-checkbox': + unset($checkboxarray); + $check_values = array(); + foreach ($option['choices'] as $k => $v ) { + // explode the connective + $pieces = explode("|", $v); + + $check_values[] = $pieces[1]; + } + + foreach ($check_values as $v ) { + + // Check that the option isn't null + if (!empty($input[$option['id'] . '|' . $v])) { + // If it's not null, make sure it's true, add it to an array + $checkboxarray[$v] = 'true'; + } + else { + $checkboxarray[$v] = 'false'; + } + } + // Take all the items that were checked, and set them as the main option + if (!empty($checkboxarray)) { + $valid_input[$option['id']] = $checkboxarray; + } + break; + + case 'multi-radio': + $valid_input[$option['id']] = (empty($input) || !isset($input[$option['id']])) ? $option['std'] : $input[$option['id']]; + break; + + endswitch; + + if (!empty($valid_input) && $valid_input[$option['id']] === "qts-slug" ) { + $valid_input = qts_sanitize_bases($valid_input); + } else { + $valid_input= $valid_input; + } + + endforeach; + + return $valid_input; +} + + + +/** + * Helper function for creating admin messages + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + * src: http://www.wprecipes.com/how-to-show-an-urgent-message-in-the-wordpress-admin-area + * + * @param (string) $message The message to echo + * @param (string) $msgclass The message class + * @return echoes the message + */ +function qts_show_msg($message, $msgclass = 'info') { + echo "
$message
"; +} + + + +/** + * Callback function for displaying admin messages + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + * @return calls qts_show_msg() + */ +function qts_admin_msgs() { + global $current_screen; + + // check for our settings page - need this in conditional further down + $qts_settings_pg = isset($_GET['page']) ? strpos($_GET['page'], QTS_PAGE_BASENAME) : ''; + // collect setting errors/notices: + // http://codex.wordpress.org/Function_Reference/get_settings_errors + $set_errors = get_settings_errors(); + + // display admin message only for the admin to see, only on our settings page + // and only when setting errors/notices are returned! + if(current_user_can ('manage_options') && $qts_settings_pg !== false && !empty($set_errors)){ + + // have our settings succesfully been updated? + if($set_errors[0]['code'] == 'settings_updated' && isset($_GET['settings-updated'])){ + qts_show_msg("

" . $set_errors[0]['message'] . "

", 'updated'); + + // have errors been found? + }else{ + // there maybe more than one so run a foreach loop. + foreach($set_errors as $set_error){ + // set the title attribute to match the error "setting title" - need this in js file + qts_show_msg("

" . $set_error['message'] . "

", 'error'); + } + } + } +} +add_action('admin_notices', 'qts_admin_msgs'); diff --git a/modules/slugs/includes/termmeta-core.php b/modules/slugs/includes/termmeta-core.php new file mode 100644 index 00000000..a0716df1 --- /dev/null +++ b/modules/slugs/includes/termmeta-core.php @@ -0,0 +1,226 @@ +supports_collation())//deprecated, was a reason for activation admin notice + if($wpdb->has_cap( 'collation' )) { + if(!empty($wpdb->charset)) $collate = "DEFAULT CHARACTER SET $wpdb->charset"; + if(!empty($wpdb->collate)) $collate .= " COLLATE $wpdb->collate"; + } + + $sql = "CREATE TABLE IF NOT EXISTS ". $wpdb->prefix . "termmeta" ." ( + `meta_id` bigint(20) NOT NULL AUTO_INCREMENT, + `term_id` bigint(20) NOT NULL DEFAULT '0', + `meta_key` varchar(255) NULL, + `meta_value` longtext NULL, + PRIMARY KEY id (`meta_id`), + KEY term_id (term_id), + KEY meta_key (meta_key($max_index_length)) + ) $collate;"; + $wpdb->query($sql); +} +endif; + + + +function simple_post_meta_define_table() { + global $wpdb; + $wpdb->termmeta = $wpdb->prefix . 'termmeta'; +} +add_action( 'init', 'simple_post_meta_define_table' ); + + + +/** + * Updates metadata cache for list of term IDs. + * + * Performs SQL query to retrieve the metadata for the term IDs and updates the + * metadata cache for the terms. Therefore, the functions, which call this + * function, do not need to perform SQL queries on their own. + * + * @param array $term_ids List of post IDs. + * @return bool|array Returns false if there is nothing to update or an array of metadata. + */ +if ( !function_exists('update_termmeta_cache') ): + function update_termmeta_cache($term_ids) { + return update_meta_cache('term', $term_ids); + } +endif; + + + +/** + * Add meta data field to a term. + * + * @param int $term_id Term ID. + * @param string $key Metadata name. + * @param mixed $value Metadata value. + * @param bool $unique Optional, default is false. Whether the same key should not be added. + * @return bool False for failure. True for success. + */ +if ( !function_exists('add_term_meta') ): + function add_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) { + return add_metadata('term', $term_id, $meta_key, $meta_value, $unique); + } +endif; + + + +/** + * Remove metadata matching criteria from a term. + * + * You can match based on the key, or key and value. Removing based on key and + * value, will keep from removing duplicate metadata with the same key. It also + * allows removing all metadata matching key, if needed. + * + * @param int $term_id Term ID + * @param string $meta_key Metadata name. + * @param mixed $meta_value Optional. Metadata value. + * @return bool False for failure. True for success. + */ +if ( !function_exists('delete_term_meta') ): + function delete_term_meta( $term_id, $meta_key, $meta_value = '' ) { + return delete_metadata('term', $term_id, $meta_key, $meta_value); + } +endif; + + + +/** + * Retrieve term meta field for a term. + * + * @param int $term_id Term ID. + * @param string $key The meta key to retrieve. + * @param bool $single Whether to return a single value. + * @return mixed Will be an array if $single is false. Will be value of meta data field if $single + * is true. + */ +if ( !function_exists('get_term_meta') ): + function get_term_meta( $term_id, $key, $single = false ) { + return get_metadata('term', $term_id, $key, $single); + } +endif; + + + +/** + * Update term meta field based on term ID. + * + * Use the $prev_value parameter to differentiate between meta fields with the + * same key and term ID. + * + * If the meta field for the term does not exist, it will be added. + * + * @param int $term_id Term ID. + * @param string $key Metadata key. + * @param mixed $value Metadata value. + * @param mixed $prev_value Optional. Previous value to check before removing. + * @return bool False on failure, true if success. + */ +if ( !function_exists('update_term_meta') ): + function update_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) { + return update_metadata('term', $term_id, $meta_key, $meta_value, $prev_value); + } +endif; + + + +/** + * Delete everything from term meta matching meta key. + * + * @param string $term_meta_key Key to search for when deleting. + * @return bool Whether the term meta key was deleted from the database + */ +if ( !function_exists('delete_term_meta_by_key') ): + function delete_term_meta_by_key($term_meta_key) { + if ( !$term_meta_key ) + return false; + + global $wpdb; + $term_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT term_id FROM $wpdb->termmeta WHERE meta_key = %s", $term_meta_key)); + if ( $term_ids ) { + $termmetaids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->termmeta WHERE meta_key = %s", $term_meta_key ) ); + $in = implode( ',', array_fill(1, count($termmetaids), '%d')); + do_action( 'delete_termmeta', $termmetaids ); + $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->termmeta WHERE meta_id IN($in)", $termmetaids )); + do_action( 'deleted_termmeta', $termmetaids ); + foreach ( $term_ids as $term_id ) + wp_cache_delete($term_id, 'term_meta'); + return true; + } + return false; + } +endif; + + + +/** + * Retrieve term meta fields, based on term ID. + * + * The term meta fields are retrieved from the cache, so the function is + * optimized to be called more than once. It also applies to the functions, that + * use this function. + * + * @param int $term_id term ID + * @return array + */ +if ( !function_exists('add_term_meta') ): + function get_term_custom( $term_id ) { + $term_id = (int) $term_id; + + if ( ! wp_cache_get($term_id, 'term_meta') ) + update_termmeta_cache($term_id); + + return wp_cache_get($term_id, 'term_meta'); + } +endif; + + + +/** + * Retrieve meta field names for a term. + * + * If there are no meta fields, then nothing (null) will be returned. + * + * @param int $term_id term ID + * @return array|null Either array of the keys, or null if keys could not be retrieved. + */ +if ( !function_exists('get_term_custom_keys') ): + function get_term_custom_keys( $term_id ) { + $custom = get_term_custom( $term_id ); + + if ( !is_array($custom) ) + return; + + if ( $keys = array_keys($custom) ) + return $keys; + } +endif; + + + +/** + * Retrieve values for a custom term field. + * + * The parameters must not be considered optional. All of the term meta fields + * will be retrieved and only the meta field key values returned. + * + * @param string $key Meta field key. + * @param int $term_id Term ID + * @return array Meta field values. + */ +if ( !function_exists('get_term_custom_values') ): + function get_term_custom_values( $key = '', $term_id ) { + if ( !$key ) + return null; + + $custom = get_term_custom($term_id); + + return isset($custom[$key]) ? $custom[$key] : null; + } +endif; \ No newline at end of file diff --git a/modules/slugs/languages/qts-es_ES.mo b/modules/slugs/languages/qts-es_ES.mo new file mode 100644 index 0000000000000000000000000000000000000000..e702170fb22cb368758195da542b3bbd2b088a70 GIT binary patch literal 5991 zcmd6r&5s;M8O93|KH@+i0m4TDls5#~%FfJsjpJlkkK%0BiNzW_-gP2~gsGXXooTzL ztKHST>&X>?#05COi39QhiA4B-IDm2;E{Gc!Zb(Q7!T|~R0}#Krx_f5U_Budv$Y^(- z>F%kjx89HEeQN&r(7iuWybkmKDF0u0k5V0Q`MtdHdJ|j){|5HJNAFSUOW-Tu%is?{ z4ZaDU2JgF9sV{m@IIw1_}dRC^5M{1tGW>k-JG`Z;gk0DlE0;KTPT z^*s13@crQLK(XidAb;x5ynP#c{{bH7dKaUg1z!iB0sjtu9c(|K)Fa?`LAn1^Q2g{4 z@CERZk6d!WSgPoRu@8Yh1Yd=|u1 z^%97=;U#v;TH=4g7@mvo*=q0^pgu2e^-JO`zWr={t-(*#p9RF;=0$p_d+H0^q(03* zO9z{R-F(Ic;U)Rdyu?~%BF65Dq9u(MY7 z9`|dVve)r$Y+H}}&RQpY_pU<*rm#boPv!%gJO9=2!VKplxtI^iv@a%!J+(A&iOajW zjh1@bquA>#DTi^Yb9=3fbL;iB?cAh3!46$G-M2bUePNQsM%twO4~lq~hf#a2ll9bk zZSS&XHSKaeD1G6^TwQmm8&A}_ONY5BN+yh5>X-GzmAQ^gVf4s&=C`RXGrkhpC_L0A zx7?A%`Ic>~jq90Z(R8Sd{%Se4c|6d&CMoSNTfGxsU;Ns@jmJiNn;90y>~wLE z-#_XMCf8A83nQyD=Znk5B(r+$YCr1rox4gD<>NA*&|8^FV?WY+u1q5FP89nrF%$8Q z*9Rtp^_?W{=gxOz{+7(&O3m0d@oDR`JK`D5hIVnh1g4*u^s3&AlSG$nQjCl2jwzEu zyG)#^_eMBRMy=t@-0qxOs`F6t?0S38)a1vc{%6daQYY}OrNW0Yfqit2^<*e-W!d4_D z-_n}g7R996sMr{c3Z)d1+)HVb%96zclj@lP!JIYI@8`OR3n4D7ganf5YmmsLG{$&u z5`EEn2xVaPro(eCU+P`DxG9S;vZvSZEd+y05qs5W7V-qK8)1r|>vGrLWHi+Ew!X@TQME?vGZVX2V^cPjCn=R@*#h<&nuUo6?_1jU6^M3LXh%P`N#y zXfrev5}lfQXshk2R}l!cJ%SoT2NHLBe2%{(DyA6enIG!SH{GZ1UX`LvDc>DM)e8Ko8pXc5@vf4h;eo9c&Qn#lrF%PE z2+4V@y>jTH&4_O6oFB$f>segf+IC%Cx2^pROXSP7S=O{POk z9*j(muTEXsKGS+?{ym{Xx@Bu4rKJ+lu70W?7nsqy2%*b1_gV2|>)1)Xa=d%|IJ}I<0i6iJYdOgDT}?=uS`vao#6TV^b^CMww1;8g<4()^UXNgrken3(XN7 z8YO%rbC!_utE{lB4WwkW^~LlC?49U{@olw5A$j_((Pb)pDpgpHr>`MV9mU1vj@flN z4FH;&-W*!OF&|V9p(D=*$>JhgBg~*s7&kTtP9*c&Dqzd-o7k5u=-1l>tfqr*_{>ay z;S$;87;?@Hb{Sd6kyZyBW!_r7ZpCQRD=1(*wPh4Xt?5Ez+|V+=f|AAEvHE=GW=X39J(RZ^LQxN@)b) zEeck@3;foYcDvieH#QvO;G82qUMwy$Cf$jLWpJ_tH^|w@@-ZZVC|VwJ!M(YvCD#xn zWlt0D1yzfWnIfCs;3P^InoKxA;Mz1X&_SgsQz>=Pdz{ZmJ{GJ*uD4{J9BYLH4Mofo zsVK3JtdB}5d=a>WKn|jJVh}A{{r_8&27{=9L7n$5!lv2sl`Tz2zeSJnsOywhXcR;%9XxNxnUzQ(yA<2M3?vFJ(if$-DS8;9;wz63rnG3#+4Ao%bSnHKSj zM;#pIv6V@?(;G-}*jCb{C3Yki{D;Nb;eK z>+E*7Yvc0}qa3$ns=2b$TcUfPFHIg9I)NGYW9QYminKL9uJn)yto24)uvE0`=ABT+mhk*4US&5I~y6T-Js0#ICAZIC!?NFEyK_W=LO60E-!5# zhG(yO*SkI_FMi59T*C(L^1omY1g?SJfd9BB0;uh6)Sc#yJf+@12q@{&&&(Q&c g>CMIV|34+&_Vgw{mbtDv-N=u*GEwubR)R$R2gwhetpET3 literal 0 HcmV?d00001 diff --git a/modules/slugs/languages/qts-es_ES.po b/modules/slugs/languages/qts-es_ES.po new file mode 100644 index 00000000..3372765f --- /dev/null +++ b/modules/slugs/languages/qts-es_ES.po @@ -0,0 +1,142 @@ +# Copyright (C) 2012 qTranslate slug +# This file is distributed under the same license as the qTranslate slug package. +msgid "" +msgstr "" +"Project-Id-Version: qTranslate slug 1.0\n" +"Report-Msgid-Bugs-To: http://wordpress.org/tag/qtranslate-slug\n" +"POT-Creation-Date: 2012-05-27 20:27:55+00:00\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2012-06-17 03:37+0100\n" +"Last-Translator: Carlos Sanz \n" +"Language-Team: Carlos Sanz Garcia \n" + +# qtranslate-slug.php +msgid "Language selector" +msgstr "Selector de idioma" + +# qtranslate-slug.php +msgid "Title:" +msgstr "Título:" + +# qtranslate-slug.php +msgid "

This plugin requires qTranslate to be installed and activated.

" +msgstr "

Este plugin necesita qTranslate instalado y activado previamente.

" + +# qtranslate-slug.php +msgid "Slug" +msgstr "Enlace permanente" + +# qtranslate-slug.php +msgid "Show short name (en):" +msgstr "Mostrar nombre corto (en):" + +# qtranslate-slug-settings-options.php +msgid "Post types" +msgstr "Post types" + +# qtranslate-slug-settings-options.php +msgid "Taxonomies" +msgstr "Taxonomias" + +# qtranslate-slug-settings-options.php +msgid "Slug (%s)" +msgstr "URL (%s)" + +# qtranslate-slug-settings-options.php +msgid "http://example.org/%s/some-%s/" +msgstr "http://ejemplo.org/%s/algun-%s/" + +# qtranslate-slug-settings-options.php +msgid "http://example.org/category/some-category/" +msgstr "http://ejemplo.org/categoria/alguna-categoria/" + +# qtranslate-slug-settings-options.php +msgid "http://example.org/tag/some-tag/" +msgstr "http://ejemplo.org/etiqueta/alguna-etiqueta/" + +# qtranslate-slug-settings.php +msgid "Qtranslate Slug options" +msgstr "Opciones de Qtranslate Slug" + +# qtranslate-slug-settings.php +msgid "Slug options" +msgstr "Opciones de URL" + +# qtranslate-slug-settings.php +msgid "Save Changes" +msgstr "Guardar cambios" + +# qtranslate-slug-settings.php +msgid "Expecting a Numeric value! Please fix." +msgstr "Se espera un valor numérico! Por favor, corrígelo." + +# qtranslate-slug-settings.php +msgid "Expecting comma separated numeric values! Please fix." +msgstr "Se esperan valores numéricos separados por coma! Por favor, corrígelo." + +# qtranslate-slug-settings.php +msgid "Invalid email" +msgstr "E-mail incorrecto" + +# qtranslate-slug-settings.php +msgid "This setting field cannot be empty! Please enter a valid email address." +msgstr "Este campo no puede estar vacío! Por favor introduce una dirección de e-mail válida." + +# qtranslate-slug-settings.php +msgid "Please enter a valid email address." +msgstr "Por favor introduce una dirección de e-mail válida." + +# qtranslate-slug-settings.php +msgid "upgrade now" +msgstr "actualizar ahora" + +# qtranslate-slug.php +msgid "Please update your old data to the new system." +msgstr "Por favor actualiza tu antiguo sistema de datos al nuevo." + +# qtranslate-slug-settings.php +msgid "Upgrade your data" +msgstr "Actualiza tus datos" + +# qtranslate-slug-settings.php +msgid "There are slugs stored with old data system. Please upgrade your data pressing upgrade button:" +msgstr "Hay slugs almacenados en el antiguo sistema. Por favor actualiza tus datos aprentando el botón actualizar:" + +# qtranslate-slug-settings.php +msgid "Sorry, some error happened. Refresh this page and try again please." +msgstr "Lo sentimos, algún tipo de error ha ocurrido. Por favor recarga esta página y prueba otra vez." + +# qtranslate-slug-settings.php +msgid "Congratulations, your data has been upgraded, you are up to date." +msgstr "Felicidades, tus datos se han actualizado, ahora estás al día." + +# qtranslate-slug-settings.php +msgid "One step more, select what type of slug is this: %s" +msgstr "Un paso más, selecction qué tipo de slug es este: %s" + +# qtranslate-slug-settings.php +msgid "Post, Page or Custom post type" +msgstr "Entrada, Página o Custom post type" + +# qtranslate-slug-settings.php +msgid "Category, tag or custom taxonomy" +msgstr "Categoria, tag o taxonomía" + +# qtranslate-slug.php +msgid "This plugin requires at least Wordpress 3.3 and Qtranslate(2.5.8 or newer)" +msgstr "Este plugin requiere al menos Wordpress 3.3 y Qtranslate(2.5.8 o mayor)" + +# qtranslate-slug-settings.php +msgid "If you activated previously the pretty permalinks, in this section you can translate the URLs bases for public post_types, categories, tags and taxonomies." +msgstr "Si has activado previamente los enlaces permanentes, en esta sección podrás traducir las bases de las URLs para post_types, categorías, etiquetas y taxonomias públicas." + +# qtranslate-slug-settings.php +msgid "For example, the post_type books, in Spanish would be displayed as http://example.org/es/libros/post-type-name/. If you leave this blank will use the default option when you registered the post_type." +msgstr "Por ejemplo, para el post_type books en Español se mostraría como http://example.org/es/libros/post-type-name/. Si dejas esto en blanco se usará la opción predeterminada cuando registraste el post_type." + +# qtranslate-slug-settings.php +msgid "For example, the taxonomy category, in Spanish would be displayed as http://example.org/es/categoria/taxonomy-name/. If you leave this blank will use the default option when you registered the taxonomy (if you previously setup a base permastruct for categories or tags in permalinks page, these bases will be overwritten by the translated ones)." +msgstr "Por ejemplo, la taxonomia category, en Español se mostraría como http://example.org/es/categoria/taxonomy-name/. Si dejas esto en blanco se usará la opción predeterminada cuando registraste la texonomia (si previamente configuraste la base de las estructuraas de categorías o tags en la página enlaces permanentes, estas bases serán reemplazadas por las traducidas)." + diff --git a/modules/slugs/languages/qts-pt_PT.mo b/modules/slugs/languages/qts-pt_PT.mo new file mode 100644 index 0000000000000000000000000000000000000000..64c0c003a45b3f35332dfbc0f68d40afaf90872d GIT binary patch literal 8618 zcmd6sU5q5xRmX3P0cS!0Cni7$D^@49`DRr4hoEJciri( zbyeNkx>YmNmXL@b4=9AZkO#yAtU$6h(jt*44}3@<^$QP(hbR(6QSy=~C`b|H4R{H^ zbE~SmXFN8J;)j&B=3iBPKh8bp-2XY}?zi6Y@D~)niMTmnB0YVZ%icYqJT3*bM3Bk-Z0Rq7G&4)}AR2c_Td zf*$}s3$B1)0-prG0e0V_)T4Cz0r>P=m3kZB&+^Ce-Uns;zhp2O=ewZD^#f4m`62iy z_y`~As@@I03w%E)OI!ypgHMC+13v?H!TX?$_ix~DfZqmLx_ap6l{yJN0{$}C1(`x! z1!cZ1@Rz_(fiivp%DnrawEHx83H&1vm8h?R((db^%=ayjf9iYuk$(RTUI8Ea1*Lu) zyasN7uYk{h-vMQu)nBaFc@BJx_bZ^-={Lb`@bjR|^Bqvye-9LS{|j6N|EKx=11L+r ze+WDWJ^_lp$Kb!>8zuN*-fu98=fU=&CgI(}8DE{^P;3vR) zU|^(jqWs5@=ipcBb${;NO5NrApMfIJ zqfCa$)HWz`4M1792gNU625~L*IglaL7eLX^Ux8P_FN5Ou{|k!WcYeJdCjr-Z{~b{J zKLBODUjcs&{5FUx)DJ?TR<5@^X)CwgSS1i-oGHoI#kFW#k;%w$cJ&6CfX)88Z5J|_T}ktDqPK04sw)S%9hPx6LO;(|sV(B6-ZM#MPw36W z8s^@O54sD@hAvHw_BJG~G=U&3? zh>HQd26HAD2k=->_Qfilr`St!7bBoG1Fn?ip&o4I{M>fVmci$CJURdwL z2D(~hsM}>bw`{QJ(5@AB6#LQ^JF`VE_uFqa+E_FF!z$^jSE;LY)>>Qb=6X{U)(jS# zwRV!9B$c%?9jmeSN4*l)X2lG9v8#MC!GTNmqtOF#@tmDtd|6b(QnQ~lEY~jE2DTGk z;3EuCzv6;3W7l5bJ7JI{&R*)~<9xY4d!+{!%%P~@+Ds>N`r4&%UAJe8{UR<)yl5~9 zrY;MUdB_EKcA533y6RdSS-l;XiS4PzM-6_o7uqZ=OWgDSm8`HO+yAhDVOs@<_reFb zwRrT6g;&0hC_?4Snl7xbwjj3 z&%WM3&(LQ-C}Cr*d8^g_X6>K%T_{G-5)6qQszDMDYa6trg1B@02IBYHWKqlcgoSRa zWe?X5#SqIGrdXz<%O|06!v@&12@MVLdMlh+Vy6_FW58shu4iy+9BG@HI8kjJnmyo+ zGK(u_U%a~M2pMr!)4SNi3|v*JXQ3Zdd!H8foZDOxl|% zU1E2man;Z}TCxQjVL?D`q9_nn+osATYKcb_+CjJ>(h-`(+cLYa{RC;!uG&PwK>{Bh zSM_GlK%pK2%tl>&c^6HLgBrsg zuKlFI1x5xIATMGwchy$N4%9XT!Jm*hNOG|q0y3Tze4%~~4zaxuMq2m5-t3@>PU9?2 zO|lxMYIk9r4U-BEK;@~hQRd37ViY<_ZXxFO_yqnC!7Sx?Zl}gLZ8&f8lG>QTkRdop z2GIUAsLIl1J%-1Daz(?DrL{M=?K(MMES!Ip3 zT5F0r@*!8sL)LI^NepI>@h5fW%NIOVXZ+kx34w}cZcSk>rv+g zcp66O>ATx)pa~ANbj#-Ko6b!?ilfd&JgT$pdZe783^<&}NE&{3wtYL|e@mOsZFepe zHYCNJ%P>YypFMr%$z4ZlL{6E2ArV zdecUQ(>HAvxorB1(Hl9NbYwiq=+h(N)-LI3f2k$d&bBq_kKC)L^Kxf%d+Fx&n^)$# zI@3M96qqSPBofD-mTY^C>^jcYsWD7}v!B1ceYNw{yq&0*G_P|dBNt?g_4HGNxLkU% z^9=Mt{v6iiY!sLJO!p(*b4!~^RhXnhf|o+u8Jmw+fBx*c>_Z;UuVnhfd41;8I)iM6 zo}H}_Z6QLDpr>mQX1{*IPQ-Hl203O=@9eDa*!7(qDjE`wgK~W*TX@^aoXh#t-~o@} zZr<&|y7j{yQP`FHh75tC|CPgE-7@QD;hdnsTj3+X?-M`)x~(}+ZhsHCU&VP$itiVO)9pEB4HpLpFhd#;eQuPEX> zrmJ3%Mu<0SCi)TKL>JJf-kUxk`%JLN7E>h8S1k#RpiC{fl>%v{V zB_%P+E=V}B2XhV}zM+%MG+5W;aM<7F!3sf3E{)MV`k7TLZ&uOFTp`=fj_OD9(*^aJ zg{=_|8D{(Y%~9TLxViqC#L)bNsIIM#+v0hqxkc5iNPR4IGs!d?SGMnNJgN$)rKz4H z3Lo+%gK@vY#t3y~CT)3^O}kJ{8yvIh3oY@nWvTjG20=~lk!sSRtpi`9v_5_^F*?-e zOT?)wZ1Fxk%)3EBViSJIEgMrx+NgRtMsP~&D==#Y4e4_FfFnIeu>ku@agCUZE2ra+ zBN>G}=Yv$&?Ix(HuaSikjNzNw>_}}a3O-zSr{sLp-Cz6>>h53)*}+h`)C|HH^D@{l z(##%E`YdWJtog^?pogmR>EB9OF8*Nplur_RngF+q?~JRoF12HRXre=iP7)XD7**50 zxS1HQr!G*jp(iS*k>yxZl0lRtv@Mmjsskny)rGd`ppLlBFBIH{YNsi<8&?jVqn?HS z)NP2=c<(rxjnP$zDMRvCtBLY6BIck&LLDNKAGX#!RCKoyMUwWy;e|#bPgsMUzETI_ zAp73*9w!E_Can;JW?`3zdnhQAAz;jAw-IsN-Ygc?9Mu zNqzN7UQ)=TVY%xvesL1{;YQ#njs=pMtH`Ic3ocLvEmPb}&d~&QYFa7o#eQLHwhFCfI8pdOgUMQ z_-ay3A9P5+gda1S$gz7!tTc=B;_$OXiw<={R@;7YRc&(iDldU)_Bg5&iws;TBD75< zU1Et4{k+(R5Q(6TkmMRC>r5{c_*Gr!3)KCF{0|Y1Cu4@ih(5`LB+pt%WZt;XZ?{x@ zp~*ClEJjhnQq4E1bM3asm)1uBv24t+uXf|%*v6EMuRaSfo-@gqZAY>|0xM?$ z$Mg;-G9lePJWzWEuqyG7d72O@6ro9ca`rE$ILA-ail&g7LxQmhrvz!3g>wR7cpM^@ z@*jRUhzC64Wx)}lqTooJ5d^MOI7~e$2`!8$ZYN!W*6J>pJscM_B4XNOSKlV~Y)(ny G)&Bu@ilBJ_ literal 0 HcmV?d00001 diff --git a/modules/slugs/languages/qts-pt_PT.po b/modules/slugs/languages/qts-pt_PT.po new file mode 100644 index 00000000..246d4264 --- /dev/null +++ b/modules/slugs/languages/qts-pt_PT.po @@ -0,0 +1,343 @@ +# Copyright (C) 2012 qTranslate slug +# This file is distributed under the same license as the qTranslate slug package. +msgid "" +msgstr "" +"Project-Id-Version: qTranslate slug\n" +"Report-Msgid-Bugs-To: http://wordpress.org/tag/qtranslate-slug\n" +"POT-Creation-Date: 2015-01-23 14:23-0000\n" +"PO-Revision-Date: 2015-01-23 15:26-0000\n" +"Last-Translator: Pedro Mendonça \n" +"Language-Team: Pedro Mendonça \n" +"Language: pt_PT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.7.3\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-KeywordsList: __;_e;__ngettext;_n;__ngettext_noop;_n_noop;_x;_nx;" +"_nx_noop;_ex;esc_attr__;esc_attr_e;esc_attr_x;esc_html__;esc_html_e;esc_html_x;" +"_c;_nc\n" +"X-Poedit-Basepath: .\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-SearchPath-1: ..\n" + +#: ../includes/class-qtranslate-slug-widget.php:11 +msgid "Allows your visitors to choose a Language." +msgstr "Permite aos visitantes escolher o seu Idioma." + +#: ../includes/class-qtranslate-slug-widget.php:12 +msgid "Language selector" +msgstr "Selector de idioma" + +#: ../includes/class-qtranslate-slug-widget.php:19 +msgid "Language" +msgstr "Idioma" + +#: ../includes/class-qtranslate-slug-widget.php:51 +msgid "Title:" +msgstr "Título:" + +#: ../includes/class-qtranslate-slug-widget.php:52 +msgid "Hide Title:" +msgstr "Esconder título:" + +#: ../includes/class-qtranslate-slug-widget.php:53 +msgid "Display:" +msgstr "Mostrar:" + +#: ../includes/class-qtranslate-slug-widget.php:54 +msgid "Text only" +msgstr "Apenas texto" + +#: ../includes/class-qtranslate-slug-widget.php:55 +msgid "Image only" +msgstr "Apenas imagem" + +#: ../includes/class-qtranslate-slug-widget.php:56 +msgid "Text and Image" +msgstr "Texto e imagem" + +#: ../includes/class-qtranslate-slug-widget.php:57 +msgid "Dropdown Box" +msgstr "Caixa de selecção" + +#: ../includes/class-qtranslate-slug-widget.php:58 +msgid "Show short name (en):" +msgstr "Mostrar abreviatura (pt):" + +#: ../includes/class-qtranslate-slug.php:413 +msgid "Please update your old data to the new system." +msgstr "Por favor actualize os seus dados antigos para o novo sistema." + +#: ../includes/class-qtranslate-slug.php:413 +#: ../includes/qtranslate-slug-settings.php:29 +msgid "upgrade now" +msgstr "actualizar agora" + +#: ../includes/class-qtranslate-slug.php:427 +msgid "or newer" +msgstr "ou mais recente" + +#: ../includes/class-qtranslate-slug.php:432 +msgid "This plugin requires at least %s and either %s, or %s, or %s" +msgstr "Este plugin requer no mínimo o %s e o %s, ou %s, ou %s" + +#: ../includes/class-qtranslate-slug.php:432 +msgid "More information about" +msgstr "Mais informações sobre" + +#: ../includes/class-qtranslate-slug.php:1612 +msgid "View all posts in %s" +msgstr "Ver todos os artigos em %s" + +#: ../includes/class-qtranslate-slug.php:1739 +msgid "Empty Term" +msgstr "Termo vazio" + +#: ../includes/class-qtranslate-slug.php:1999 +#: ../includes/class-qtranslate-slug.php:2000 +#: ../includes/class-qtranslate-slug.php:2003 +#: ../includes/class-qtranslate-slug.php:2541 +msgid "Slug" +msgstr "URL" + +#: ../includes/class-qtranslate-slug.php:2214 +#: ../includes/class-qtranslate-slug.php:2233 +#: ../includes/qtranslate-slug-settings-options.php:39 +msgid "Slug (%s)" +msgstr "URL (%s)" + +#: ../includes/class-qtranslate-slug.php:2400 +#: ../includes/class-qtranslate-slug.php:2404 +msgid "Name" +msgstr "Nome" + +#: ../includes/class-qtranslate-slug.php:2542 +msgid "Posts" +msgstr "Artigos" + +#: ../includes/class-qtranslate-slug.php:2634 +msgid "Languages" +msgstr "Idiomas" + +#: ../includes/class-qtranslate-slug.php:2657 +msgid "All languages" +msgstr "Todos os idiomas" + +#: ../includes/qtranslate-slug-settings-options.php:14 +msgid "Post types" +msgstr "Tipos de artigos" + +#: ../includes/qtranslate-slug-settings-options.php:15 +msgid "Taxonomies" +msgstr "Taxonomias" + +#: ../includes/qtranslate-slug-settings-options.php:16 +msgid "Styles" +msgstr "Estilos" + +#: ../includes/qtranslate-slug-settings-options.php:63 +msgid "Change styles type" +msgstr "Alterar o tipo de estilos" + +#: ../includes/qtranslate-slug-settings-options.php:65 +msgid "adds a file (qts-default.css) to the theme's header." +msgstr "adiciona um ficheiro (qts-default.css) ao cabeçalho do tema." + +#: ../includes/qtranslate-slug-settings-options.php:66 +msgid "" +"adds a minified ( slighlty faster) file (qts-default.min.css) to the theme's " +"header." +msgstr "" +"adiciona um ficheiro minimizado (qts-default.min.css), ligeiramente mais " +"rápido, ao cabeçalho do tema." + +#: ../includes/qtranslate-slug-settings-options.php:67 +msgid "prints the styles directly into the theme's header." +msgstr "exibe os estilos directamente no cabeçalho do tema." + +#: ../includes/qtranslate-slug-settings-options.php:68 +msgid "neither include not print the default style." +msgstr "nem incluir nem exibir o estilo padrão." + +#: ../includes/qtranslate-slug-settings-options.php:73 +msgid "file" +msgstr "ficheiro" + +#: ../includes/qtranslate-slug-settings-options.php:74 +msgid "minified" +msgstr "minimizado" + +#: ../includes/qtranslate-slug-settings-options.php:75 +msgid "inline" +msgstr "em linha" + +#: ../includes/qtranslate-slug-settings-options.php:76 +msgid "none" +msgstr "nenhum" + +#: ../includes/qtranslate-slug-settings-options.php:106 +#: ../includes/qtranslate-slug-settings-options.php:148 +msgid "http://example.org/%s/some-%s/" +msgstr "http://exemplo.org/%s/qualquer-%s/" + +#: ../includes/qtranslate-slug-settings-options.php:119 +msgid "Categories" +msgstr "Categorias" + +#: ../includes/qtranslate-slug-settings-options.php:120 +msgid "http://example.org/category/some-category/" +msgstr "http://exemplo.org/categoria/qualquer-categoria/" + +#: ../includes/qtranslate-slug-settings-options.php:130 +msgid "Tags" +msgstr "Etiquetas" + +#: ../includes/qtranslate-slug-settings-options.php:131 +msgid "http://example.org/tag/some-tag/" +msgstr "http://exemplo.org/etiqueta/qualquer-etiqueta/" + +#: ../includes/qtranslate-slug-settings-options.php:175 +msgid "Qtranslate Settings - Contextual Help" +msgstr "Definições do Qtranslate - Ajuda contextual" + +#: ../includes/qtranslate-slug-settings-options.php:176 +msgid "" +"Contextual help goes here. You may want to use different html elements to " +"format your text as you want." +msgstr "" +"Isto é a ajuda contextual. Poderá utilizar diferentes elementos html para " +"formatar o seu texto como desejar." + +#: ../includes/qtranslate-slug-settings.php:23 +msgid "Upgrade your data" +msgstr "Actualize os seus dados" + +#: ../includes/qtranslate-slug-settings.php:24 +msgid "" +"There are slugs stored with old data system. Please upgrade your data pressing " +"upgrade button:" +msgstr "" +"Existem URLs com sistema de dados antigo. Por favor actualize os seus dados " +"através do botão actualizar:" + +#: ../includes/qtranslate-slug-settings.php:77 +msgid "Sorry, some error happened. Refresh this page and try again please." +msgstr "" +"Lamentavelmente mas ocorreu um erro. Por favor refresque esta página e tente " +"novamente." + +#: ../includes/qtranslate-slug-settings.php:84 +msgid "Congratulations, your data has been upgraded, you are up to date." +msgstr "" +"Parabéns, os seus dados foram actualizados e o sistema está agora actual." + +#: ../includes/qtranslate-slug-settings.php:90 +msgid "One step more, select what type of slug is this: %s" +msgstr "Um passo mais, seleccione que tipo de URL é este: %s" + +#: ../includes/qtranslate-slug-settings.php:91 +msgid "Post, Page or Custom post type" +msgstr "Artigo, página ou tipo de artigo personalizado" + +#: ../includes/qtranslate-slug-settings.php:91 +msgid "Category, tag or custom taxonomy" +msgstr "Categoria, etiqueta ou taxonomia personalizada" + +#: ../includes/qtranslate-slug-settings.php:182 +#: ../includes/qtranslate-slug-settings.php:322 +msgid "Qtranslate Slug options" +msgstr "Opções do Qtranslate Slug" + +#: ../includes/qtranslate-slug-settings.php:322 +msgid "Slug options" +msgstr "Opções do URL" + +#: ../includes/qtranslate-slug-settings.php:359 +msgid "" +"For example, the post_type books, in Spanish would be displayed as " +"http://example.org/es/libros/post-type-name/. If you leave this " +"blank will use the default option when you registered the post_type." +msgstr "" +"Por exemplo, o tipo de artigo livros, em português seria mostrado " +"como http://exemplo.org/pt/livros/nome-de-tipo-de-artigo/. Se " +"deixar isto em branco, será usada a opção por omissão registada no tipo de " +"artigo." + +#: ../includes/qtranslate-slug-settings.php:364 +msgid "" +"For example, the taxonomy category, in Spanish would be displayed " +"as http://example.org/es/categoria/taxonomy-name/. If you leave " +"this blank will use the default option when you registered the " +"taxonomy (if you previously setup a base permastruct for categories or " +"tags in permalinks page, these " +"bases will be overwritten by the translated ones)." +msgstr "" +"Por exemplo, a taxonomia categoria, em português seria mostrado " +"como http://exemplo.org/pt/categoria/nome-de-taxonomia/. Se " +"deixar isto em branco, será usada a opção por omissão registada na " +"taxonomia (se previamente configurou a base das ligações permanentes para " +"categorias ou etiquetas na página ligações permanentes, estas bases serão sobrepostas pelas traduzidas)." + +#: ../includes/qtranslate-slug-settings.php:368 +msgid "The default styles are very minimal, and you can include them or not." +msgstr "Os estilos padrão são mínimos, pode incluí-los ou não." + +#: ../includes/qtranslate-slug-settings.php:567 +msgid "" +"If you activated previously the pretty " +"permalinks, in this section you can translate the URLs bases for public post_types, categories, tags and taxonomies." +msgstr "" +"Se activou previamente as ligações " +"permanentes, nesta secção poderá traduzir as bases das " +"URLs para tipos " +"de artigo, categorias, etiquetas e taxonomias públicas." + +#: ../includes/qtranslate-slug-settings.php:586 +msgid "If you selected \"none\", copy and use these styles as you see fit:" +msgstr "Se escolher \"nenhum\", copie e utilize estes estilos como entender:" + +#: ../includes/qtranslate-slug-settings.php:589 +msgid "Save Changes" +msgstr "Guardar alterações" + +#: ../includes/qtranslate-slug-settings.php:642 +msgid "Expecting a Numeric value! Please fix." +msgstr "É necessário um valor numérico! Por favor, corrija." + +#: ../includes/qtranslate-slug-settings.php:655 +msgid "Expecting comma separated numeric values" +msgstr "Valores numéricos separados por vírgulas" + +#: ../includes/qtranslate-slug-settings.php:665 +msgid "Expecting comma separated numeric values! Please fix." +msgstr "" +"São necessários valores numéricos separados por vírgulas! Por favor, corrija." + +#: ../includes/qtranslate-slug-settings.php:690 +msgid "Invalid email" +msgstr "Email incorrecto" + +#: ../includes/qtranslate-slug-settings.php:692 +msgid "This setting field cannot be empty! Please enter a valid email address." +msgstr "" +"Este campo não pode estar vazio! Por favor introduza um endereço de email " +"válido." + +#: ../includes/qtranslate-slug-settings.php:700 +msgid "Please enter a valid email address." +msgstr "Por favor introduza um endereço de email válido." + +#: ../qtranslate-slug.php:150 +msgid "Settings" +msgstr "Definições" diff --git a/modules/slugs/languages/qts.pot b/modules/slugs/languages/qts.pot new file mode 100644 index 00000000..cedf142d --- /dev/null +++ b/modules/slugs/languages/qts.pot @@ -0,0 +1,313 @@ +# Copyright (C) 2012 qTranslate slug +# This file is distributed under the same license as the qTranslate slug package. +msgid "" +msgstr "" +"Project-Id-Version: qTranslate slug 1.0\n" +"Report-Msgid-Bugs-To: http://wordpress.org/tag/qtranslate-slug\n" +"POT-Creation-Date: 2015-01-23 14:23-0000\n" +"PO-Revision-Date: 2015-01-23 14:23-0000\n" +"Last-Translator: Pedro Mendonça \n" +"Language-Team: Carlos Sanz Garcia \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.7.3\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-KeywordsList: __;_e;__ngettext;_n;__ngettext_noop;_n_noop;_x;_nx;" +"_nx_noop;_ex;esc_attr__;esc_attr_e;esc_attr_x;esc_html__;esc_html_e;" +"esc_html_x\n" +"X-Poedit-Basepath: .\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-SearchPath-1: ..\n" + +#: ../includes/class-qtranslate-slug-widget.php:11 +msgid "Allows your visitors to choose a Language." +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:12 +msgid "Language selector" +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:19 +msgid "Language" +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:51 +msgid "Title:" +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:52 +msgid "Hide Title:" +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:53 +msgid "Display:" +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:54 +msgid "Text only" +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:55 +msgid "Image only" +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:56 +msgid "Text and Image" +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:57 +msgid "Dropdown Box" +msgstr "" + +#: ../includes/class-qtranslate-slug-widget.php:58 +msgid "Show short name (en):" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:413 +msgid "Please update your old data to the new system." +msgstr "" + +#: ../includes/class-qtranslate-slug.php:413 +#: ../includes/qtranslate-slug-settings.php:29 +msgid "upgrade now" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:427 +msgid "or newer" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:432 +msgid "This plugin requires at least %s and either %s, or %s, or %s" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:432 +msgid "More information about" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:1612 +msgid "View all posts in %s" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:1739 +msgid "Empty Term" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:1999 +#: ../includes/class-qtranslate-slug.php:2000 +#: ../includes/class-qtranslate-slug.php:2003 +#: ../includes/class-qtranslate-slug.php:2541 +msgid "Slug" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:2214 +#: ../includes/class-qtranslate-slug.php:2233 +#: ../includes/qtranslate-slug-settings-options.php:39 +msgid "Slug (%s)" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:2400 +#: ../includes/class-qtranslate-slug.php:2404 +msgid "Name" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:2542 +msgid "Posts" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:2634 +msgid "Languages" +msgstr "" + +#: ../includes/class-qtranslate-slug.php:2657 +msgid "All languages" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:14 +msgid "Post types" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:15 +msgid "Taxonomies" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:16 +msgid "Styles" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:63 +msgid "Change styles type" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:65 +msgid "adds a file (qts-default.css) to the theme's header." +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:66 +msgid "" +"adds a minified ( slighlty faster) file (qts-default.min.css) to the theme's " +"header." +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:67 +msgid "prints the styles directly into the theme's header." +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:68 +msgid "neither include not print the default style." +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:73 +msgid "file" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:74 +msgid "minified" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:75 +msgid "inline" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:76 +msgid "none" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:106 +#: ../includes/qtranslate-slug-settings-options.php:148 +msgid "http://example.org/%s/some-%s/" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:119 +msgid "Categories" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:120 +msgid "http://example.org/category/some-category/" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:130 +msgid "Tags" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:131 +msgid "http://example.org/tag/some-tag/" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:175 +msgid "Qtranslate Settings - Contextual Help" +msgstr "" + +#: ../includes/qtranslate-slug-settings-options.php:176 +msgid "" +"Contextual help goes here. You may want to use different html elements to " +"format your text as you want." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:23 +msgid "Upgrade your data" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:24 +msgid "" +"There are slugs stored with old data system. Please upgrade your data pressing " +"upgrade button:" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:77 +msgid "Sorry, some error happened. Refresh this page and try again please." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:84 +msgid "Congratulations, your data has been upgraded, you are up to date." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:90 +msgid "One step more, select what type of slug is this: %s" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:91 +msgid "Post, Page or Custom post type" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:91 +msgid "Category, tag or custom taxonomy" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:182 +#: ../includes/qtranslate-slug-settings.php:322 +msgid "Qtranslate Slug options" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:322 +msgid "Slug options" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:359 +msgid "" +"For example, the post_type books, in Spanish would be displayed as " +"http://example.org/es/libros/post-type-name/. If you leave this " +"blank will use the default option when you registered the post_type." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:364 +msgid "" +"For example, the taxonomy category, in Spanish would be displayed " +"as http://example.org/es/categoria/taxonomy-name/. If you leave " +"this blank will use the default option when you registered the " +"taxonomy (if you previously setup a base permastruct for categories or " +"tags in permalinks page, these " +"bases will be overwritten by the translated ones)." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:368 +msgid "The default styles are very minimal, and you can include them or not." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:567 +msgid "" +"If you activated previously the pretty " +"permalinks, in this section you can translate the URLs bases for public post_types, categories, tags and taxonomies." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:586 +msgid "If you selected \"none\", copy and use these styles as you see fit:" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:589 +msgid "Save Changes" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:642 +msgid "Expecting a Numeric value! Please fix." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:655 +msgid "Expecting comma separated numeric values" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:665 +msgid "Expecting comma separated numeric values! Please fix." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:690 +msgid "Invalid email" +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:692 +msgid "This setting field cannot be empty! Please enter a valid email address." +msgstr "" + +#: ../includes/qtranslate-slug-settings.php:700 +msgid "Please enter a valid email address." +msgstr "" + +#: ../qtranslate-slug.php:150 +msgid "Settings" +msgstr "" diff --git a/modules/slugs/readme.txt b/modules/slugs/readme.txt new file mode 100644 index 00000000..cbf1b227 --- /dev/null +++ b/modules/slugs/readme.txt @@ -0,0 +1,296 @@ +=== Qtranslate Slug === +Contributors: carlos_a_sanz, pedroghandi +Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=GYS2L7627B4F8&lc=GB&item_name=Qtranslate%2dSlug%20Improvement%20Fund&item_number=qts%2dpaypal¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted +Tags: qtranslate, slug, multilanguage, widget +Requires at least: 4.0 +Tested up to: 4.5 +Stable tag: 1.1.18 +License: GPLv2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +Adds support for permalink translations to QTranslate-X + +== Description == + +[Qtranslate-X](http://wordpress.org/plugins/qtranslate-x/) is a nice plugin for Multilingual Websites. **Qtranslate Slug** is an addon to QTranslate, which adds support for permalinks translations. + + + + + +1.1.17 fixes a dangerous Security Exploit. Please update right now! + += Requirements: = + +* Wordpress 4.0 (PHP 5.4 and MySQL 5) +* mQtranslate 2.6.2.4 or Qtranslate 2.5.8 or qtranslate-x ( 2.9.1 ) + += New in 1.1.18 = + +* works with upcomming wp 4.5! thats new for a change! +* widget is now compatible with wp 4.3. thanks to @adnanoner ( #111) and @gitmad (#112) +* saving taxonomies wont print warning. thanks to @jmarceli ( #113) +* saving post quick edit wont print warnings. thanks again to jmarceli ( #114 ) +* Code from wp.org is now been merged with the github account +* Some notices are fixed. Thanks to @rafa-aguilar ( #89 ) +* custom post types are fixed! thanks to @MicheleBertoli ( #102 ) +* slug box now shows the utf8 chars instead of the enconded ones. +* you can now toggle the default slug box, in case you want to edit it. +* edit term has been re-worked, so no more errors and notices! ( hopefully!) +* couple of other stuff has been fixed by me thanks to your awesome bug reports! + += New in 1.1.17 = +* Hability to filter the position of the Metabox +* Fixed dangerous security exploit! + += New in 1.1.16 = +Minor fix for the language menu using qtranslate's function + += New in 1.1.15 = +* Fixes the duplicated hreflang links in + += New in 1.1.14 = + +The menu widget didn't allow the visitors to change to the default language if qtranslate-x was being used. So, adjusted the Language Menu widget to play nice with qtranslate-x. +Hope to bring some nice changes that were made in the github repository in the next version. For now, enjoy. + += New in 1.1.13 = +== Thanks to returning @pedro-mendonca for these commits: == +* Cleaned duplicated label in widget +* Bug fix in "Slug (%s)" string translation +* Changed text strings with no text-domain and with text-domain 'qtranlate' to text-domain 'qts' +* pot catalog updated with current strings, including last found is "More information about". +== Thanks to @johnclause for these : == +* Convenience links in notice_dependences +* Menu compatibility with qTranslate-X +* Fixed extra characters in widget +### Thanks to vbkun for casting the much wanted function to get a slug based on an id and language +* Added a global qts_get_slug( $id, $lang) +### and sadly: +* removed the menu admin box until better implementation + + +See you next Version! + + +**Advice: If you're using a multisite installation, you will must activate qtranslate plugins by separately on each site.** + +You can also check the [project website](http://not-only-code.github.com/qtranslate-slug/) hosted on [GitHub](http://not-only-code.github.com). +Thanks for use this plugin! + += Contributors = + +* [Pedro de Carvalho](https://github.com/LC43/) +* [Risto Niinemets](https://github.com/RistoNiinemets) +* [Pedro Mendonça](https://github.com/pedro-mendonca) +* [codep0et](https://github.com/codep0et) +* [Giraldi Maggio](https://github.com/bedex78) +* [jinoOM](https://github.com/jinoOM) +* [Juanfran](https://github.com/juanfran-granados) +* [Arild](https://github.com/arildm) +* [Rafa Aguilar](https://github.com/rafitaFCB) +* [Bastian Heist](https://github.com/beheist) +* [John Clause](https://github.com/johnclause) + + +== Installation == +**This plugins requires [Qtranslate](http://wordpress.org/extend/plugins/qtranslate/) or [mqTranslate](https://wordpress.org/plugins/mqtranslate/) installed previously, if not, it will not activate.** + +1. Upload `qtranslate-slug` to the `/wp-content/plugins/` directory. +1. Activate the plugin through the 'Plugins' menu in WordPress. +1. That's all! + += Changing base permastructs = + +1. In admin: navigate to *Settings/Slug options*. +1. Set the base permastructs for **post types** and **taxonomies** (If you setup a base permastruct for *categories* or *tags* in *Settings/Permalinks*, these will be overwritten by the translated ones). +1. Save settings and that's all! + +== Frequently Asked Questions == + += It works with posts and pages, but with other content type? = + +This plugin allows to translate slugs of: posts, pages, custom post types, categories, tags and custom taxonomies. + += Do I have to configure anything? = + +If you want to translate also the base permastructs (ex. *category*, *tag*, etc). Visit the plugin settings page in the admin *Settings/Slug options* + += How can i insert a language selector in my theme ? = + +You can choose to: +* use **Qtranslate Slug Widget** in your sidebar. +* place in your template ``. Options are: `dropdown`, `text`, `image`, and `both`. + += Appears an error 404, what can i do? = + +In the admin go to *Settings/Permalinks* or *Settings/Slug options* and save. + += I can't manage translations in Nav Menus. = + +That's because language selector metabox is hidden, if you are in admin *nav menus* screen, press the button **Screen options** (on top and right) and after, check the option *Languages*. It will appear a **Language** meta box on top of the left sidebar. + += How to get the current url in a specific language? = + +You can use `qts_get_url()` or the awkwardly named `qTranslateSlug_getSelfUrl()` which is an alias for the first one. + + +== Screenshots == + +1. Edit page for: post / page / post_type, you can see the meta box for translated slugs on top and right. +2. Add new taxonomy page +3. Edit taxonomy page +4. Qtranslate Slug options page for translate base permastructs of post_types and taxonomies. + +== Changelog == + + += New in Versions 1.1.12 = + +* fixed warnings in settings +* replace qtranslate with our own for taxonomies + += New in Versions 1.1.10 and 1.1.11 = + +* Fixing wrong commit to wp.org +* Clean deleted files += New in Version 1.1.9 = + +Lots of bug fixes! Thanks again to everyone that contributed to this project, with commits, bug reports and suggestions. + +* Compatibility with qtranslate-X! ( thanks @beheist, pull #85, fixing most of #80 ) +* More updates to the portuguese translation ( thanks pedro-mendonca, pull #86) +* Corrected the link to language files ( thanks pedro-mendonca ) +* Added translation for some hardcoded texts ( thanks pedro-mendonca ) +* Corrected a link from 'qtranslate' to 'qts' language files ( thanks pedro-mendonca ) +* Fixed taxonomies slugs ( thanks to [eirikv's bug report](https://wordpress.org/support/topic/categories-slug-dont-work) ) +* Fixed many warnings ( thanks piffpaffpuff, issue #78 and to [pedrodu1](https://wordpress.org/support/topic/warnings-qtranslate-slugphp) ) +* Changed the behaviour of "Quick Edit", from the wp forums [1](https://wordpress.org/support/topic/categories-tags-and-quick-edit-dont-show-in-admin) [2](https://wordpress.org/support/topic/quick-edit-inhibited-by-qtranslate-slug-with-wp-41-mqtranslate) ( thanks everyone!! ) +* Fixed the menus! Now you can properly use one menu for every language. Use the dropdown section "Languages", and for each item, change the "Navigation Label" and "Title Attribute". Select "All languages", to make sure everything is awesome! All these features were a consequence of fixing all the warnings based on [Gery's bug report](https://wordpress.org/support/topic/qtranslate-slug-conflicting-with-ubermenu). +* Minor fixes, etc. + + += New in Version 1.1.9 = + +Lots of bug fixes! Thanks again to everyone that contributed to this project, with commits, bug reports and suggestions. + +* Compatibility with qtranslate-X! ( thanks @beheist, pull #85, fixing most of #80 ) +* More updates to the portuguese translation ( thanks pedro-mendonca, pull #86) +* Corrected the link to language files ( thanks pedro-mendonca ) +* Added translation for some hardcoded texts ( thanks pedro-mendonca ) +* Corrected a link from 'qtranslate' to 'qts' language files ( thanks pedro-mendonca ) +* Fixed taxonomies slugs ( thanks to [eirikv's bug report](https://wordpress.org/support/topic/categories-slug-dont-work) +* Fixed many warnings ( thanks piffpaffpuff, issue #78 and to [pedrodu1](https://wordpress.org/support/topic/warnings-qtranslate-slugphp) ) +* Changed the behaviour of "Quick Edit", from the wp forums [1](https://wordpress.org/support/topic/categories-tags-and-quick-edit-dont-show-in-admin) [2](https://wordpress.org/support/topic/quick-edit-inhibited-by-qtranslate-slug-with-wp-41-mqtranslate) ( thanks everyone!! ) +* Fixed the menus! Now you can properly use one menu for every language. Use the dropdown section "Languages", and for each item, change the "Navigation Label" and "Title Attribute". Select "All languages", to make sure everything is awesome! All these features were a consequence of fixing all the warnings based on [Gery's bug report)[https://wordpress.org/support/topic/qtranslate-slug-conflicting-with-ubermenu). +* Minor fixes, etc. + +See you next Version! + + += 1.1.8 = + +Many thanks to everyone that contributed to this update, for their commits, bug reports and for simply using it + +* Portuguese translation and fixed some translation bugs ( thanks pedro-mendonca ) +* removed mqtranslate switcher widget hook +* Updated the plugin structure and coding style +* solve some conflicts with search and pagination queries +* Settings php errors, syntax indent and fixed settings assets url +* Change titles when there is a click on pagination on show all pages tab ( thanks juanfran-granados ) +* Formatted dependency notice message ( thanks arildm ) +* Updated the deprecated jquery 'live' function and solve php strict standards error ( thanks rafitaFCB ) +* Fixed error showing if PHP was newer than 5.3 ( thanks rafitaFCB ) +* Strict standard advise prevented ( thanks rafitaFCB ) +* php notices are prevented in post edit, when using adding new translated tags ( thanks rafitaFCB ) +* fixed the hreflang issue! 'bout time! +* As discussed in issue #25, the flags are now img tags, intead of background-url. +* Added another option to include the css style in a minified file. ( and also showing in the option screen the styles we would use.) + += 1.1.7 = +* removed styles from html elements and added options to use .css file or print inline styles +* fixed tag creation on post edit. +* fixed earlier bad post slug introduced in 1.1.6 + += 1.1.6 = +* compatible with mqtranslate +* php5.4+ compatible + += 1.1.5 = +* bugfixes + += 1.1 = +* added multisite support +* fixed some parse url bugs +* fixed slug bases validation + += 1.0 = +* **works** with any permalink combination and qtranslate mode. +* new branch, the plugin has been rewritten: now the code is commented and wrapped inside a class, much code has change and the performance has been increased (use caches). +* data system changed, no ID for slug type, then it don't needs install `qtrasnlate_slug` table. That means slugs now are stored on meta tables and installation creates a termmeta table with some new *core functions* to access/save data, based on [simple term meta](http://wordpress.org/extend/plugins/simple-term-meta/). Upgrade process when the plugin updates from older versions. +* the plugin generates translated slug automatically from title in empty cases. +* the plugin checks if the slug already exists (per each language and `post_type`/`taxonomy`), and adds a progressive number in this case. Works on ajax requests for example when new taxonomies are created in edit post page. +* possibility to translate the base of permastructs for *post_types* and *taxonomies*, uses [$wp_rewrite](http://codex.wordpress.org/Class_Reference/WP_Rewrite). New admin options page for save the base permastructs. +* added some filters, see in [other notes](http://wordpress.org/extend/plugins/qtranslate-slug/other_notes/). +* added plugin language textdomain (.pot file). +* updated **Language selector Widget**, and some new conventions like accessible functions for templating. +* some bug fixes. +* some Qtranslate patches. + += 0.9 = +* some wordpress qTranslate bug fixes +* adds a javascript solution for qTranslate Nav Menus + += 0.8 = +* added support por Categories +* added support por Tags +* added support por Taxonomies +* added support por Custom Post Types + += 0.7 = [Zapo](http://www.qianqin.de/qtranslate/forum/viewtopic.php?f=4&t=1049&start=50#p7499) +* added suport for qTranslate TLD domain mode (en: domain.com | fr: domain.fr) visit + += 0.5 and 0.6 enhanched by Marco Del Percio = + +== Upgrade Notice == + += 1.0 = +Major version, the plugin has been rewritten. Better performance, and some enhancements. + += 0.9 = +This version fix some bugs and allow multilanguage in nav-menus. + += 0.8 = +A lot of slugs content allowed + += 0.7 = +This version allows TLD domain option for a different Qtranslate fork maded by Zappo + + +== Other notes == + +Plugin filters reference: + += qts_validate_post_slug = +filter to process the post slug before is saved on the database. +`args: $post (object), $slug (string), $lang (string)` + += qts_validate_term_slug = +filter to process the term slug before is saved on the database. +`args: $term (object), $slug (string), $lang (string)` + += qts_url_args = +filter to process the entire url after it has been generated. +`args: $url (string), $lang (string)` + += qts_permastruct = +filter to process the permastruct, used for change the base. +`args: $permastruct (string), $name (string)` + + += Todo = + +* detect Slug for each language and redirect accordingly in parse_query. +* expand qtranslate for translate attachment names and descriptions ( useful for galleries ) +* translate other slugs like attachments. +* qtranslate integration with other plugins like Jigoshop, e-commerce, etc. Addapt **$wp_rewrite**. diff --git a/modules/slugs/slugs.php b/modules/slugs/slugs.php new file mode 100644 index 00000000..927fa43a --- /dev/null +++ b/modules/slugs/slugs.php @@ -0,0 +1,182 @@ +language_menu($type, $args); +} + +/** + * Finds the translated slug of the given post by calling get_slug + * @param int $id the post id + * @param string $lang which language to look for + * @since 1.1.13 + */ + +function qts_get_slug( $id, $lang ) { + global $qtranslate_slug; + return $qtranslate_slug->get_slug($id, $lang); +} + + +/** + * Adds support for old plugin function + * + * @package Qtranslate Slug + * @subpackage Core + * @since 1.1.5 + */ +function qTranslateSlug_getSelfUrl ($lang = false) { // bad naming, I'll keep just in case + return qts_get_url($lang); +} + +function qts_get_url($lang = false) { + global $qtranslate_slug; + + return $qtranslate_slug->get_current_url($lang); +} + + + +/** + * Add a "Settings" link to the plugins.php page for Qtranslate Slug + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + * @return calls qts_show_msg() + */ +function qts_add_settings_link( $links, $file ) { + + if (QtranslateSlug::block_activate()) return $links; + + $this_plugin = plugin_basename( __FILE__ ); + if( $file == $this_plugin ) { + $settings_link = "" . __( 'Settings', 'qts' ) . ''; + array_unshift($links, $settings_link); + } + return $links; +} +add_filter( 'plugin_action_links', 'qts_add_settings_link', 10, 2 ); + + + +/** + * Delete plugin stored data ( options, termmeta table and postmeta data ) + * + * @package Qtranslate Slug + * @subpackage Settings + * @version 1.0 + * + */ +function qts_uninstall() { + global $q_config, $wpdb, $wp_version; + + // options + delete_option(QTS_OPTIONS_NAME); + delete_option('qts_version'); + + // don't delete termmeta table as it will be used by wp beginning 4.4 + if( version_compare($wp_version, "4.4", "<" ) ) { + $wpdb->query("DROP TABLE IF EXISTS $wpdb->termmeta"); + } + + // delete postmeta data + $meta_keys = array(); + foreach ($q_config['enabled_languages'] as $lang) $meta_keys[] = sprintf("_qts_slug_%s", $lang); + $meta_keys = "'". implode( "','", $meta_keys ) . "'"; + $wpdb->query("DELETE from $wpdb->postmeta WHERE meta_key IN ($meta_keys)"); +} diff --git a/modules/slugs/version.txt b/modules/slugs/version.txt new file mode 100644 index 00000000..cddff47e --- /dev/null +++ b/modules/slugs/version.txt @@ -0,0 +1,162 @@ += New in 1.1.18 = + +Let's start with what has been fixed: + + +* widget is now compatible with wp 4.3. thanks to @adnanoner ( #111) and @gitmad (#112) +* saving taxonomies wont print warning. thanks to @jmarceli ( #113) +* saving post quick edit wont print warnings. thanks again to jmarceli ( #114 ) +* Code from wp.org is now been merged with the github account +* Some notices are fixed. Thanks to @rafa-aguilar ( #89 ) +* custom post types are fixed! thanks to @MicheleBertoli ( #102 ) +* lots of other stuff has been fixed by me thanks to your awesome bug reports! + + + +and now, what isn't working: +In QTS slug options you can change the bases for taxonomies and custom post types. + +So, for example, you can change /category/ for /category/ for english and /categoria/ for spanish version. +But these won't work: +* slug with UTF8 charactes in taxonomies bases: example: /類別/.. instead of /category/.. + utf8 in taxonomies works just fine: /category_zh/魚/ +* slug with UTF8 charactes in custom post type bases : example: /圖書/.. instead of /books/.. + utf8 in custom post slugs works just fine: /tushu/彩繪中國經典名著/ +* translating custom post types archives with custom base name /tushu/ isnt working. but using utf8 in the the default slug, as expected : /中國/ + + + + + + +Thanks for using, enjoy 1.1.18. + +If anything breaks, let me know! + += New in 1.1.17 = +* Fixed dangerous security exploit! +* Hability to filter the position of the Metabox + += New in 1.1.16 = +Minor fix for the language menu using qtranslate's function + += New in 1.1.15 = +* Fixes the duplicated hreflang links in + += New in 1.1.14 = + +The menu widget didn't allow the visitors to change to the default language if qtranslate-x was being used. So, adjusted the Language Menu widget to play nice with qtranslate-x. +Hope to bring some nice changes that were made in the github repository in the next version. For now, enjoy. + += 1.1.13 = +== Thanks to returning @pedro-mendonca for these commits: == +* Cleaned duplicated label in widget +* Bug fix in "Slug (%s)" string translation +* Changed text strings with no text-domain and with text-domain 'qtranlate' to text-domain 'qts' +* pot catalog updated with current strings, including last found is "More information about". +== Thanks to @johnclause for these : == +* Convenience links in notice_dependences +* Menu compatibility with qTranslate-X +* Fixed extra characters in widget +== Thanks to vbkun for casting this much wanted function == +* Added a global qts_get_slug( $id, $lang) +== and sadly: == +* removed the menu admin box until better implementation + += 1.1.12 = + +* fixed warnings in settings +* replace qtranslate with our own for taxonomies + += 1.1.10 and 1.1.11 = +* Fixing wrong commit to wp.org +* Clean deleted files + += 1.1.9 = + +Lots of bug fixes! Thanks again to everyone that contributed to this project, with commits, bug reports and suggestions. + +* Compatibility with qtranslate-X! ( thanks @beheist, pull #85, fixing most of #80 ) +* More updates to the portuguese translation ( thanks pedro-mendonca, pull #86) +* Corrected the link to language files ( thanks pedro-mendonca ) +* Added translation for some hardcoded texts ( thanks pedro-mendonca ) +* Corrected a link from 'qtranslate' to 'qts' language files ( thanks pedro-mendonca ) +* Fixed taxonomies slugs ( thanks to [eirikv's bug report](https://wordpress.org/support/topic/categories-slug-dont-work) ) +* Fixed many warnings ( thanks piffpaffpuff, issue #78 and to [pedrodu1](https://wordpress.org/support/topic/warnings-qtranslate-slugphp) ) +* Changed the behaviour of "Quick Edit", from the wp forums [1](https://wordpress.org/support/topic/categories-tags-and-quick-edit-dont-show-in-admin) [2](https://wordpress.org/support/topic/quick-edit-inhibited-by-qtranslate-slug-with-wp-41-mqtranslate) ( thanks everyone!! ) +* Fixed the menus! Now you can properly use one menu for every language. Use the dropdown section "Languages", and for each item, change the "Navigation Label" and "Title Attribute". Select "All languages", to make sure everything is awesome! All these features were a consequence of fixing all the warnings based on [Gery's bug report](https://wordpress.org/support/topic/qtranslate-slug-conflicting-with-ubermenu). +* Minor fixes, etc. + +See you next Version! + += 1.1.8 = + +Many thanks to everyone that contributed to this update, both for their commits and bug reports ) + +* Portuguese translation and fixed some translation bugs ( thanks pedro-mendonca ) +* removed mqtranslate switcher widget hook +* Updated the plugin structure and coding style +* solve some conflicts with search and pagination queries +* Settings php errors, syntax indent and fixed settings assets url +* Change titles when there is a click on pagination on show all pages tab ( thanks juanfran-granados ) +* Formatted dependency notice message ( thanks arildm ) +* Updated the deprecated jquery 'live' function and solve php strict standards error ( thanks rafitaFCB ) +* Fixed error showing if PHP was newer than 5.3 ( thanks rafitaFCB ) +* Strict standard advise prevented ( thanks rafitaFCB ) +* php notices are prevented in post edit, when using adding new translated tags ( thanks rafitaFCB ) +* fixed the hreflang issue! 'bout time! +* As discussed in issue #25, the flags are now img tags, intead of background-url. +* Added another option to include the css style in a minified file. ( and also showing in the option screen the styles we would use.) + += 1.1.7 = +* removed styles from html elements and added options to use .css file or print inline styles +* fixed tag creation on post edit. +* fixed earlier bad post slug introduced in 1.1.6 + += 1.1.6 = +* compatible with mqtranslate +* php5.4+ compatible + += 1.1.5 = +* bugfixes + += 1.1 = +* added multisite support +* fixed some parse url bugs +* fixed slug bases validation + += 1.0 = +* new branch, the plugin has been rewrited: now the code is commented and wrapped inside a class, also all code has change and the performance has been increased. +* structural changes: + * no ID for slug type, then don't install qtrasnlate_slug table. + * slugs now are stored on meta tables, installation creates a termmeta table with some new 'core functions' to access/save data, based on [simple term meta](http://wordpress.org/extend/plugins/simple-term-meta/). +* some automation: + * the plugin generates translated slug automatically from title in empty cases (like wordpress). + * the plugin checks if the slug already exists (per each language and type / taxonomy), and adds a progressive number in this case (like wordpress). + * works on ajax requests like creatig new taxonomies on edit post page. +* possibility to translate the base of permastructs for 'post_types' and 'taxonomies' (uses $wp_rewrite). +* added some filters: + * 'qts_validate_post_slug' : args( $post (object), $slug (string), $lang (string) ) / filter to process the post slug before is saved on the database. + * 'qts_validate_term_slug' : args( $term (object), $slug (string), $lang (string) ) / filter to process the term slug before is saved on the database. + * 'qts_current_url' : args ( $url (string), $lang (string) ) / filter to process the entire url after it has been generated. + * 'qts_permastruct' : args ( $permastruct (string), $name (string) ) / filter to process the permastruct, used for change the base. +* added plugin language textdomain (.pot file) +* new admin options page for save the base permastructs. +* import process when the plugin updates older versions. +* some bug fixes. +* some Qtranslate patches. + += 0.9 = +* some wordpress qTranslate bug fixes +* adds a javascript solution for qTranslate Nav Menus + += 0.8 = +* added support por Categories +* added support por Tags +* added support por Taxonomies +* added support por Custom Post Types + += 0.7 ( enhanced by Zapo (http://www.qianqin.de/qtranslate/forum/viewtopic.php?f=4&t=1049&start=50#p7499) ) = +* added suport for qTranslate TLD domain mode (en: domain.com | fr: domain.fr) visit + += 0.5 and 0.6 enhanched by Marco Del Percio = \ No newline at end of file diff --git a/qtranslate_core.php b/qtranslate_core.php index 30a235df..9359ce53 100644 --- a/qtranslate_core.php +++ b/qtranslate_core.php @@ -61,11 +61,6 @@ function qtranxf_init_language() { } } - // TODO fix qtranslate-slug still using 'original_url' field and remove it from here, this has no sense! - if ( defined( 'QTS_VERSION' ) ) { - $url_info['original_url'] = $_SERVER['REQUEST_URI']; - } - $url_info['language'] = qtranxf_detect_language( $url_info ); $q_config['language'] = apply_filters( 'qtranslate_language', $url_info['language'], $url_info ); diff --git a/qtranslate_options.php b/qtranslate_options.php index 1342903b..dfb3f03d 100644 --- a/qtranslate_options.php +++ b/qtranslate_options.php @@ -86,6 +86,7 @@ function qtranxf_set_default_options( &$ops ) { 'hide_default_language' => true, // hide language tag for default language in urls 'use_secure_cookie' => false, 'header_css_on' => true, + 'slugs_enabled' => false, ); // single line options