diff --git a/README.md b/README.md index 418b6e2..27a9ace 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,14 @@ Integrates the **Ultimate Member** plugin with the **Polylang** plugin. Makes Ul ## Key features -- Localized permalinks for the Account and User (profile) pages. -- Ability to duplicate Ultimate Member forms for all languages in one click. +- Language switcher shortcode. Display the Polylang language switcher where you need it. +- Localize permalinks for the Account and User (profile) pages. - Ability to duplicate Ultimate Member pages for all languages in one click. +- Ability to duplicate Ultimate Member forms for all languages in one click. - Ability to translate email templates. - Ability to translate bio (description) field in profile. +- Integration with the [Account tabs](https://github.com/umdevelopera/um-account-tabs) extension. Makes custom account tabs translatable. +- Integration with the [Profile tabs](https://ultimatemember.com/extensions/profile-tabs/) extension. Makes custom profile tabs translatable. ## Installation @@ -24,18 +27,42 @@ Once the plugin is cloned, enter your site admin dashboard and go to _wp-admin > ### How to install from ZIP archive -You can install this plugin from the [ZIP archive](https://drive.google.com/file/d/17n3Kr05_B_edsGY7An7xu85TZ7H5gbOT/view?usp=sharing) as any other plugin. Follow [this instruction](https://wordpress.org/support/article/managing-plugins/#upload-via-wordpress-admin). +You can install this plugin from the [ZIP archive](https://drive.google.com/file/d/1rj0W6639PMrFQqLfeCZXhoYgRcnCac8d/view?usp=sharing) as any other plugin. Follow [this instruction](https://wordpress.org/support/article/managing-plugins/#upload-via-wordpress-admin). ## How to use +### How to display language switcher + +Add the **[um_pll_switcher]** shortcode to the place you need. + +Shortcode attributes: +- int `dropdown` Displays languages into a dropdown if set to 1. Defaults to 0. +- int `show_flags` Displays flags if set to 1. Defaults to 1. +- int `show_names` Shows language names if set to 1. Defaults to 1. +- string `display_names_as` Whether to display the language name or its slug. Accepts 'slug' and 'name'. Defaults to 'name'. +- string `item_display` Whether to display languages as a list or inline. Accepts 'list-item' and 'inline'. Defaults to 'inline'. +- string `item_spacing` Whether to preserve or discard whitespace between list items. Accepts 'preserve' and 'discard'. Defaults to 'preserve'. +- int `hide_current` Hides the current language if set to 1. Defaults to 0. +- int `hide_if_no_translation` Hides the link if there is no translation if set to 1. Defaults to 0. + +See also [Options](https://polylang.pro/doc/the-language-switcher/#options) + +**Screenshots** + +Image - Language switcher shortcode in the header template. +![Language switcher shortcode in the header template](https://github.com/user-attachments/assets/b0fa465c-52fc-4eb8-a19d-c330f397da61) + +Image - Language switcher in the page header. +![Language switcher in the page header](https://github.com/user-attachments/assets/a39efdb2-183e-44ba-bc1d-3f39892d5004) + ### How to translate pages Go to *wp-admin > Pages* to translate Ultimate Member pages. Click the **Create Pages** button in the notice to duplicate Ultimate Member pages for all languages. Or click the "+" icon unter the flag to duplicate each page manually. Image - Translate pages. -![Pages](https://github.com/umdevelopera/um-polylang/assets/113178913/40543c1b-d428-4832-9090-d2cc9166b616) +![WP Pages cr](https://github.com/user-attachments/assets/ef991008-2d5f-4dd7-9514-a5fd0d256dc0) -Go to *wp-admin > Settings > Permalinks* and click the **Save Changes** button if you need to update rewrite rules for the Account and User page permalinks. +Go to *wp-admin > Settings > Permalinks* if you need to update rewrite rules for the Account and User page permalinks. Don't change settings on this page, just visit it. WordPress will update rewrite rules. Note: The "Post name" permalink structure is recommended. Image - Permalink settings. @@ -46,12 +73,12 @@ Image - Permalink settings. Go to *wp-admin > Ultimate Member > Forms* to translate Ultimate Member forms. Click the **Create Forms** button in the notice to duplicate Ultimate Member forms for all languages. Or click the "+" icon unter the flag to duplicate each form manually. Image - Translate forms. -![Forms](https://github.com/umdevelopera/um-polylang/assets/113178913/76763122-a774-4778-ab2c-748b3e983779) +![UM Forms cr](https://github.com/user-attachments/assets/a6057994-ffd9-41d4-ac47-2436550732ff) Once forms for languages are created you can open these forms and translate fields. You have to translate a **Label** for custom fields. You also can translate **Placeholder** and **Help Text** if needed. -**Choices** are not translatable, this is necessary for the directory search to work correctly. Don't try to translate choices in the field settings! You can use custom functions to translate choices. -See examples: +__Note:__ Choices in the Checkbox, Radio, Dropdown and Multi-Select fields are not translatable. This is necessary for the directory filters to work correctly. Don't try to translate choices in the field settings! +You can use custom functions to translate choices. See examples here: - [How to translate choices of the Checkbox field](https://gist.github.com/umdevelopera/f7b0e07d5db870c9ce9fc1e513224e45) - [How to translate choices of the Dropdown field](https://gist.github.com/umdevelopera/bcc8c882ead5914845b489ece73b612d) @@ -62,7 +89,25 @@ See examples: Go to *wp-admin > Ultimate Member > Settings > Email* to translate email templates. Click the "+" icon unter the flag to translate a template for the language. The plugin saves translated email templates to locale subfolders in the theme, see [Email Templates](https://docs.ultimatemember.com/article/1335-email-templates). Image - Translate emails. -![Email](https://github.com/umdevelopera/um-polylang/assets/113178913/17167ba5-8564-4fe9-ba33-ef69bfb67f57) +![UM Settings, Email cr](https://github.com/user-attachments/assets/47901a64-ea93-4bdd-b70c-47f0dd3fea08) + +### How to translate custom account tabs + +This feature is available if you use the [Account tabs](https://github.com/umdevelopera/um-account-tabs) extension. + +Go to *wp-admin > Ultimate Member > Account Tabs*. Click the **Create Tabs** button in the notice to duplicate tabs for all languages. Once the tabs are duplicated for each language, you can manually edit the tab title. + +Image - Translate account tabs. +![WP, Ultimate Member, Account Tabs (Create Tabs) cr](https://github.com/user-attachments/assets/bd7e22ae-ca3a-4cd4-96d8-6a9e339b1a33) + +### How to translate custom profile tabs + +This feature is available if you use the [Profile tabs](https://ultimatemember.com/extensions/profile-tabs/) extension. + +Go to *wp-admin > Ultimate Member > Profile Tabs*. Click the **Create Tabs** button in the notice to duplicate tabs for all languages. Once the tabs are duplicated for each language, you can manually edit the tab title. + +Image - Translate profile tabs. +![WP, Ultimate Member, ProfileTabs (Create Tabs) cr](https://github.com/user-attachments/assets/5db162cd-9c53-4d7f-8081-63f8e31d8105) ## Support @@ -75,6 +120,6 @@ Ultimate Member home page: https://ultimatemember.com/ Ultimate Member documentation: https://docs.ultimatemember.com/ -Ultimate Member on wordpress.org: https://wordpress.org/plugins/ultimate-member/ +Ultimate Member download: https://wordpress.org/plugins/ultimate-member/ -Article: [How to translate plugin](https://docs.ultimatemember.com/article/1449-how-to-translate-plugin#switch). +Articles: [How to translate plugin](https://docs.ultimatemember.com/article/1449-how-to-translate-plugin#switch), [The language switcher](https://polylang.pro/doc/the-language-switcher/) diff --git a/includes/admin/class-admin.php b/includes/admin/class-admin.php index 9803a46..78903a0 100644 --- a/includes/admin/class-admin.php +++ b/includes/admin/class-admin.php @@ -21,6 +21,18 @@ */ class Admin { + const NOTICES = array( + 'um_pll_create_forms', + 'um_pll_create_pages', + 'um_pll_create_account_tabs', + 'um_pll_create_profile_tabs', + ); + + const POST_TYPES = array( + 'um_form' => 'um_form', + 'um_account_tabs' => 'um_account_tabs', + 'um_profile_tabs' => 'um_profile_tabs', + ); /** * Admin constructor. @@ -110,8 +122,11 @@ public function notice_create_forms() { } $need_translations = array(); - foreach ( $posts as $post => $post_id ) { - if ( $def_lang !== pll_get_post_language( $post_id ) ) { + foreach ( $posts as $post_id ) { + $cur_lang = pll_get_post_language( $post_id ); + if ( false === $cur_lang ) { + pll_set_post_language( $post_id, PLL()->pref_lang ); + } elseif ( $def_lang !== $cur_lang ) { continue; } $post_translations = pll_get_post_translations( $post_id ); @@ -121,43 +136,41 @@ public function notice_create_forms() { } if ( $need_translations ) { - $url_params = array( - 'um_adm_action' => 'um_pll_create_forms', - '_wpnonce' => wp_create_nonce( 'um_pll_create_forms' ), - ); - - $url = add_query_arg( $url_params ); - - ob_start(); - ?> + $url_params = array( + 'um_adm_action' => 'um_pll_create_forms', + '_wpnonce' => wp_create_nonce( 'um_pll_create_forms' ), + ); -

- -

-

- - -

+ $url = add_query_arg( $url_params ); + ob_start(); + ?> +

'notice-warning', - 'message' => $message, - 'dismissible' => true, + // translators: %1$s - plugin name, %2$s - a list of forms. + echo esc_html( + sprintf( + __( '%1$s needs to create required forms for every language to function correctly. Forms that need translation: %2$s', 'um-polylang' ), + UM_PLUGIN_NAME, + implode( ', ', $need_translations ) + ) ); + ?> +

+

+ + +

+ admin()->notices()->add_notice( 'um_pll_create_forms', $notice_data, 20 ); + $notice_data = array( + 'class' => 'notice-warning', + 'message' => $message, + 'dismissible' => true, + ); + + UM()->admin()->notices()->add_notice( 'um_pll_create_forms', $notice_data, 20 ); } } @@ -205,7 +218,6 @@ public function notice_create_pages() { ob_start(); ?> -

" class="button button-primary">

- flush_rewrite_rules(); + $this->reset_admin_notices(); } } diff --git a/includes/core/class-shortcodes.php b/includes/core/class-shortcodes.php new file mode 100644 index 0000000..fffdd06 --- /dev/null +++ b/includes/core/class-shortcodes.php @@ -0,0 +1,86 @@ + 0, // Display as list and not as dropdown. + 'show_flags' => 1, // Don't show flags. + 'show_names' => 1, // Show language names. + 'display_names_as' => 'name', // Display the language name. + 'item_display' => 'inline', // CSS "display" property for list items. + 'item_spacing' => 'preserve', // Preserve whitespace between list items. + 'force_home' => 0, // Tries to find a translation. + 'hide_current' => 0, // Don't hide the current language. + 'hide_if_no_translation' => 0, // Don't hide the link if there is no translation. + 'admin_render' => 0, // Make the switcher in a frontend context. + 'echo' => 0, // Echoes the list. + 'raw' => 0, // Build the language switcher. + ); + + /** + * Class constructor. + */ + public function __construct() { + add_shortcode( 'um_pll_switcher', array( $this, 'um_pll_switcher' ) ); + } + + /** + * Displays a language switcher. + * + * Shortcode: [um_pll_switcher] + * + * @param array $atts { + * Optional array of arguments. + * + * @type int $dropdown The list is displayed as dropdown if set, defaults to 0. + * @type int $show_flags Displays flags if set to 1, defaults to 1. + * @type int $show_names Shows language names if set to 1, defaults to 1. + * @type string $display_names_as Whether to display the language name or its slug, valid options are 'slug' and 'name', defaults to 'name'. + * @type string $item_display Optional CSS "display" property for list items. Valid options are 'list-item' and 'inline', defaults to 'inline'. + * @type string $item_spacing Whether to preserve or discard whitespace between list items, valid options are 'preserve' and 'discard', defaults to 'preserve'. + * @type int $hide_current Hides the current language if set to 1, defaults to 0. + * @type int $hide_if_no_translation Hides the link if there is no translation if set to 1, defaults to 0. + * } + * @return string|array either the html markup of the switcher or the raw elements to build a custom language switcher + */ + function um_pll_switcher( $atts ) { + $args = shortcode_atts( self::DEFAULTS, $atts ); + + $output = $this->the_languages( PLL()->links, $args ); + if ( empty( $args['dropdown'] ) ) { + if ( ! empty( $args['item_display'] ) ) { + $search = ''; + } else { + if ( ! empty( $args['show_flags'] ) ) { + $lang = UM()->Polylang()->get_current(); + $language = PLL()->model->get_language( $lang ); + if ( is_object( $language ) ) { + $output = $language->flag . ' ' . $output; + } + } + $output = '
' . $output . '
'; + } + + return $output; + } + +} diff --git a/includes/core/class-um-polylang.php b/includes/core/class-um-polylang.php index 39e6537..a20cdb1 100644 --- a/includes/core/class-um-polylang.php +++ b/includes/core/class-um-polylang.php @@ -12,6 +12,8 @@ /** * The "Ultimate Member - Polylang" extension initialization. * + * How to call: UM()->Polylang() + * * @package um_ext\um_polylang\core */ class UM_Polylang { @@ -53,9 +55,16 @@ public function __construct() { } elseif ( UM()->is_request( 'frontend' ) ) { $this->fields(); $this->form(); + $this->shortcodes(); } - add_action( 'plugins_loaded', array( $this, 'textdomain' ), 9 ); + // Extensions. + if ( defined( 'um_account_tabs_version' ) ) { + require_once um_polylang_path . 'includes/extensions/account-tabs.php'; + } + if ( defined( 'um_profile_tabs_version' ) ) { + require_once um_polylang_path . 'includes/extensions/profile-tabs.php'; + } } @@ -164,12 +173,18 @@ public function setup() { /** - * Loads a plugin's translated strings. + * Subclass that add shortcodes. + * + * @since 1.2.0 + * + * @return um_ext\um_polylang\core\Shortcodes() */ - public function textdomain() { - $locale = get_locale() ? get_locale() : 'en_US'; - load_textdomain( um_polylang_textdomain, WP_LANG_DIR . '/plugins/' . um_polylang_textdomain . '-' . $locale . '.mo' ); - load_plugin_textdomain( um_polylang_textdomain, false, dirname( um_polylang_plugin ) . '/languages/' ); + public function shortcodes() { + if ( empty( UM()->classes['um_polylang_shortcodes'] ) ) { + require_once um_polylang_path . 'includes/core/class-shortcodes.php'; + UM()->classes['um_polylang_shortcodes'] = new um_ext\um_polylang\core\Shortcodes(); + } + return UM()->classes['um_polylang_shortcodes']; } diff --git a/includes/extensions/account-tabs.php b/includes/extensions/account-tabs.php new file mode 100644 index 0000000..9db4fcf --- /dev/null +++ b/includes/extensions/account-tabs.php @@ -0,0 +1,180 @@ + 'ids', + 'nopaging' => true, + 'post_status' => 'publish', + 'post_type' => 'um_account_tabs', + ); + $posts = get_posts( $args ); + + UM()->Polylang()->posts()->create_posts( $posts, 'um_account_tabs' ); + + $url = add_query_arg( 'update', 'um_pll_create_account_tabs', admin_url( 'edit.php?post_type=um_account_tabs' ) ); + exit( wp_safe_redirect( $url ) ); +} +add_action( 'um_admin_do_action__um_pll_create_account_tabs', 'um_polylang_account_tabs_create' ); + + +/** + * Update the "Embed a profile form" setting in the translated tab. + * + * @see um_ext\um_polylang\core\Posts::create_posts() + * + * @param int $tr_id Translated post ID. + * @param int $post_id Original post ID. + * @param string $lang Translated language slug. + * @param string $post_type Post type. + */ +function um_polylang_account_tabs_create_posts( $tr_id, $post_id, $lang, $post_type ) { + if ( 'um_account_tabs' === $post_type ) { + $um_form = get_post_meta( $post_id, '_um_form', true ); + if ( ! empty( $um_form ) ) { + $tr_um_form = pll_get_post( $um_form, $lang ); + if ( ! empty( $tr_um_form ) ) { + update_post_meta( $tr_id, '_um_form', $tr_um_form ); + } + } + } +} +add_action( 'um_polylang_create_posts', 'um_polylang_account_tabs_create_posts', 10, 4 ); + + +/** + * Display a notice with the "Create Tabs" button. + * + * @return void + */ +function um_polylang_account_tabs_notice() { + $screen = get_current_screen(); + if ( ! is_object( $screen ) || 'edit-um_account_tabs' !== $screen->id ) { + return; + } + + $languages = pll_languages_list(); + if ( empty( $languages ) ) { + return; + } + $def_lang = pll_default_language(); + + $args = array( + 'fields' => 'ids', + 'nopaging' => true, + 'post_status' => 'publish', + 'post_type' => 'um_account_tabs', + ); + $posts = get_posts( $args ); + if ( empty( $posts ) ) { + return; + } + + $need_translations = array(); + foreach ( $posts as $post => $post_id ) { + $cur_lang = pll_get_post_language( $post_id ); + if ( false === $cur_lang ) { + pll_set_post_language( $post_id, PLL()->pref_lang ); + } elseif ( $def_lang !== $cur_lang ) { + continue; + } + $post_translations = pll_get_post_translations( $post_id ); + if ( array_diff( $languages, array_keys( $post_translations ) ) ) { + $need_translations[ $post_id ] = get_the_title( $post_id ); + } + } + + if ( $need_translations ) { + $url_params = array( + 'um_adm_action' => 'um_pll_create_account_tabs', + '_wpnonce' => wp_create_nonce( 'um_pll_create_account_tabs' ), + ); + + $url = add_query_arg( $url_params ); + + ob_start(); + ?> +

+ +

+

+ + +

+ 'notice-warning', + 'message' => $message, + 'dismissible' => true, + ); + + UM()->admin()->notices()->add_notice( 'um_pll_create_account_tabs', $notice_data, 20 ); + } +} +add_action( 'in_admin_header', 'um_polylang_account_tabs_notice' ); + + +/** + * Display a notice after um_adm_action. + * + * @param array $messages Admin notice messages. + * @param string $update Update action key. + * @return array + */ +function um_polylang_account_tabs_notice_update( $messages, $update ) { + if ( 'um_pll_create_account_tabs' === $update ) { + $messages[0]['content'] = __( 'Tabs have been duplicated successfully.', 'um-polylang' ); + } + return $messages; +} +add_filter( 'um_adm_action_custom_notice_update', 'um_polylang_account_tabs_notice_update', 10, 2 ); +add_filter( 'um_adm_action_custom_update_notice', 'um_polylang_account_tabs_notice_update', 10, 2 ); + + +/** + * Localize custom account tabs. + * + * @param array $tabs All custom account tabs like posts array. + * @return array Custom account tabs for the current language. Uses default language tab if no tab for the current. + */ +function um_polylang_account_tabs_get_tabs( $tabs ) { + if ( is_array( $tabs ) ) { + $current = UM()->Polylang()->get_current(); + $default = UM()->Polylang()->get_default(); + foreach( $tabs as $i => $tab ) { + $post_id = is_object( $tab ) ? $tab->ID : absint( $tab ); + $post_lang = pll_get_post_language( $post_id ); + if ( $post_lang === $current ) { + continue; + } + if ( $post_lang === $default && ! pll_get_post( $post_id, $current ) ) { + continue; + } + unset( $tabs[ $i ] ); + } + } + return $tabs; +} +add_filter( 'um_account_tabs_get_tabs', 'um_polylang_account_tabs_get_tabs', 10, 1 ); diff --git a/includes/extensions/profile-tabs.php b/includes/extensions/profile-tabs.php new file mode 100644 index 0000000..1f3edf3 --- /dev/null +++ b/includes/extensions/profile-tabs.php @@ -0,0 +1,287 @@ + 'ids', + 'nopaging' => true, + 'post_status' => 'publish', + 'post_type' => 'um_profile_tabs', + ); + $posts = get_posts( $args ); + + UM()->Polylang()->posts()->create_posts( $posts, 'um_profile_tabs' ); + + $url = add_query_arg( 'update', 'um_pll_create_profile_tabs', admin_url( 'edit.php?post_type=um_profile_tabs' ) ); + exit( wp_safe_redirect( $url ) ); +} +add_action( 'um_admin_do_action__um_pll_create_profile_tabs', 'um_polylang_profile_tabs_create' ); + + +/** + * Update the "Custom Profile Form" setting in the translated tab. + * + * @see um_ext\um_polylang\core\Posts::create_posts() + * + * @param int $tr_id Translated post ID. + * @param int $post_id Original post ID. + * @param string $lang Translated language slug. + * @param string $post_type Post type. + */ +function um_polylang_profile_tabs_create_posts( $tr_id, $post_id, $lang, $post_type ) { + if ( 'um_profile_tabs' === $post_type ) { + $um_form = get_post_meta( $post_id, 'um_form', true ); + if ( ! empty( $um_form ) ) { + $tr_um_form = pll_get_post( $um_form, $lang ); + if ( ! empty( $tr_um_form ) ) { + update_post_meta( $tr_id, 'um_form', $tr_um_form ); + } + } + } +} +add_action( 'um_polylang_create_posts', 'um_polylang_profile_tabs_create_posts', 10, 4 ); + + +/** + * Display a notice with the "Create Tabs" button. + * + * @return void + */ +function um_polylang_profile_tabs_notice() { + $screen = get_current_screen(); + if ( ! is_object( $screen ) || 'edit-um_profile_tabs' !== $screen->id ) { + return; + } + + $languages = pll_languages_list(); + if ( empty( $languages ) ) { + return; + } + $def_lang = pll_default_language(); + + $args = array( + 'fields' => 'ids', + 'nopaging' => true, + 'post_status' => 'publish', + 'post_type' => 'um_profile_tabs', + ); + $posts = get_posts( $args ); + if ( empty( $posts ) ) { + return; + } + + $need_translations = array(); + foreach ( $posts as $post_id ) { + $cur_lang = pll_get_post_language( $post_id ); + if ( false === $cur_lang ) { + pll_set_post_language( $post_id, PLL()->pref_lang ); + } elseif ( $def_lang !== $cur_lang ) { + continue; + } + $post_translations = pll_get_post_translations( $post_id ); + if ( array_diff( $languages, array_keys( $post_translations ) ) ) { + $need_translations[ $post_id ] = get_the_title( $post_id ); + } + } + + if ( $need_translations ) { + $url_params = array( + 'um_adm_action' => 'um_pll_create_profile_tabs', + '_wpnonce' => wp_create_nonce( 'um_pll_create_profile_tabs' ), + ); + + $url = add_query_arg( $url_params ); + + ob_start(); + ?> +

+ +

+

+ + +

+ 'notice-warning', + 'message' => $message, + 'dismissible' => true, + ); + + UM()->admin()->notices()->add_notice( 'um_pll_create_profile_tabs', $notice_data, 20 ); + } +} +add_action( 'in_admin_header', 'um_polylang_profile_tabs_notice' ); + + +/** + * Display a notice after um_adm_action. + * + * @param array $messages Admin notice messages. + * @param string $update Update action key. + * @return array + */ +function um_polylang_profile_tabs_notice_update( $messages, $update ) { + if ( 'um_pll_create_profile_tabs' === $update ) { + $messages[0]['content'] = __( 'Tabs have been duplicated successfully.', 'um-polylang' ); + } + return $messages; +} +add_filter( 'um_adm_action_custom_notice_update', 'um_polylang_profile_tabs_notice_update', 10, 2 ); +add_filter( 'um_adm_action_custom_update_notice', 'um_polylang_profile_tabs_notice_update', 10, 2 ); + + +/** + * Add custom profile tabs. + * + * @param array $tabs Profile tabs. + * @return array + */ +function um_polylang_profile_tabs_add_tabs( $tabs ) { + $custom_tabs = um_polylang_profile_tabs_get_tabs(); + if ( $custom_tabs ) { + foreach ( $custom_tabs as $tab ) { + $tabs[ $tab['tabid'] ] = array( + 'ID' => $tab['id'], + 'name' => $tab['title'], + 'icon' => $tab['icon'], + 'is_custom_added' => true, + ); + } + } + return $tabs; +} +add_filter( 'um_profile_tabs', 'um_polylang_profile_tabs_add_tabs', 9999, 1 ); +remove_filter( 'um_profile_tabs', array( UM()->Profile_Tabs()->profile(), 'add_tabs' ), 9999, 1 ); +remove_filter( 'um_profile_tabs', array( UM()->Profile_Tabs()->profile(), 'predefine_tabs' ), 1, 1 ); + + +/** + * Initialize custom profile tabs before adding them to the profile menu. + * + * @staticvar boolean $custom_tabs + * @return array Localized profile tabs array. + */ +function um_polylang_profile_tabs_get_tabs() { + static $custom_tabs = false; + + if ( false === $custom_tabs ) { + $custom_tabs = array(); + + $args = array( + 'numberposts' => -1, + 'post_status' => 'publish', + 'post_type' => 'um_profile_tabs', + ); + $tabs = get_posts( $args ); + + if ( $tabs && is_array( $tabs ) ) { + + // Localize custom profile tabs. + $current = UM()->Polylang()->get_current(); + $default = UM()->Polylang()->get_default(); + foreach( $tabs as $i => $tab ) { + $post_id = is_object( $tab ) ? $tab->ID : absint( $tab ); + $post_lang = pll_get_post_language( $post_id ); + if ( $post_lang === $current ) { + continue; + } + if ( $post_lang === $default && ! pll_get_post( $post_id, $current ) ) { + continue; + } + unset( $tabs[ $i ] ); + } + + // Build tabs. + foreach ( $tabs as $tab ) { + $slug = $tab->um_tab_slug ? $tab->um_tab_slug : $tab->post_name; + if ( isset( $custom_tabs[ $slug ] ) ) { + continue; + } + + $link_type = (int) $tab->um_link_type; + $tab_link = ! $link_type ? '' : $tab->um_tab_link; + + $tab = array( + 'tabid' => $slug, + 'id' => $tab->ID, + 'title' => $tab->post_title, + 'content' => $tab->post_content, + 'form' => $tab->um_form, + 'icon' => $tab->um_icon ? $tab->um_icon : 'fas fa-check', + 'link_type' => $link_type, + 'tab_link' => $tab_link, + ); + + $custom_tabs[ $slug ] = $tab; + + if ( empty( $tab_link ) ) { + // Show content. + add_action( + "um_profile_content_{$slug}", + function( $args ) use ( $tab ) { + $content = wpautop( $tab['content'] ); + $tab_content = um_convert_tags( $content, array(), false ); + + if ( ! empty( $tab['form'] ) ) { + add_filter( 'um_force_shortcode_render', array( UM()->Profile_Tabs()->profile(), 'force_break_form_shortcode' ) ); + } + if ( class_exists( '\Elementor\Plugin' ) ) { + \Elementor\Plugin::instance()->frontend->remove_content_filter(); + } + + echo apply_filters( 'the_content', $tab_content ); + + if ( class_exists( '\Elementor\Plugin' ) ) { + \Elementor\Plugin::instance()->frontend->add_content_filter(); + } + if ( ! empty( $tab['form'] ) ) { + remove_filter( 'um_force_shortcode_render', array( UM()->Profile_Tabs()->profile(), 'force_break_form_shortcode' ) ); + echo '
'; + echo UM()->Profile_Tabs()->profile()->um_custom_tab_form( $tab['tabid'], $tab['form'] ); + } + } + ); + } else { + // Show remote link. + add_filter( + "um_profile_menu_link_{$slug}", + function( $nav_link ) use ( $tab_link ) { + return $tab_link; + } + ); + add_filter( + "um_profile_menu_link_{$slug}_attrs", + function( $profile_nav_attrs ) { + return $profile_nav_attrs . ' target="_blank"'; + } + ); + } + } + } + } + + return $custom_tabs; +} diff --git a/languages/um-polylang-en_US.l10n.php b/languages/um-polylang-en_US.l10n.php new file mode 100644 index 0000000..2f5ba2b --- /dev/null +++ b/languages/um-polylang-en_US.l10n.php @@ -0,0 +1,2 @@ +'Ultimate Member - Polylang','report-msgid-bugs-to'=>'','pot-creation-date'=>'2023-12-03 23:01+0000','po-revision-date'=>'2024-11-10 20:47+0000','last-translator'=>'DeveloperA UltimateMember','language-team'=>'English (United States)','language'=>'en_US','plural-forms'=>'nplurals=2; plural=n != 1;','mime-version'=>'1.0','content-type'=>'text/plain; charset=UTF-8','content-transfer-encoding'=>'8bit','x-generator'=>'Loco https://localise.biz/','x-loco-version'=>'2.6.6; wp-6.4.1','x-domain'=>'um-polylang','messages'=>[]]; diff --git a/languages/um-polylang-en_US.mo b/languages/um-polylang-en_US.mo index 78bcd5c..b636fe5 100644 Binary files a/languages/um-polylang-en_US.mo and b/languages/um-polylang-en_US.mo differ diff --git a/languages/um-polylang-en_US.po b/languages/um-polylang-en_US.po index e0c58bd..608d805 100644 --- a/languages/um-polylang-en_US.po +++ b/languages/um-polylang-en_US.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: Ultimate Member - Polylang\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-12-03 23:01+0000\n" -"PO-Revision-Date: 2023-12-24 19:26+0000\n" +"PO-Revision-Date: 2024-11-10 20:47+0000\n" "Last-Translator: DeveloperA UltimateMember\n" "Language-Team: English (United States)\n" "Language: en_US\n" @@ -16,7 +16,7 @@ msgstr "" "X-Domain: um-polylang" #. %1$s - plugin name, %2$s - a list of forms. -#: includes/admin/class-admin.php:138 +#: includes/admin/class-admin.php:153 #, php-format msgid "" "%1$s needs to create required forms for every language to function correctly." @@ -24,22 +24,36 @@ msgid "" msgstr "" #. %1$s - plugin name, %2$s - a list of pages. -#: includes/admin/class-admin.php:213 +#: includes/admin/class-admin.php:226 #, php-format msgid "" "%1$s needs to create required pages for every language to function correctly." " Pages that need translation: %2$s" msgstr "" -#: includes/admin/class-admin.php:146 +#: includes/admin/class-admin.php:161 msgid "Create Forms" msgstr "" -#: includes/admin/class-admin.php:221 +#: includes/admin/class-admin.php:234 msgid "Create Pages" msgstr "" -#: includes/admin/class-admin.php:252 +#: includes/extensions/account-tabs.php:121 +#: includes/extensions/profile-tabs.php:121 +msgid "Create Tabs" +msgstr "" + +#. %1$s - a list of tabs. +#: includes/extensions/account-tabs.php:114 +#: includes/extensions/profile-tabs.php:114 +#, php-format +msgid "" +"Extension needs to create tabs for every language to function correctly. " +"Tabs that need translation: %1$s" +msgstr "" + +#: includes/admin/class-admin.php:264 msgid "Forms have been duplicated successfully." msgstr "" @@ -55,14 +69,21 @@ msgstr "" msgid "Integrates Ultimate Member with Polylang." msgstr "" -#: includes/admin/class-admin.php:147 includes/admin/class-admin.php:222 +#: includes/admin/class-admin.php:162 includes/admin/class-admin.php:235 +#: includes/extensions/account-tabs.php:122 +#: includes/extensions/profile-tabs.php:122 msgid "No thanks" msgstr "" -#: includes/admin/class-admin.php:256 +#: includes/admin/class-admin.php:268 msgid "Pages have been duplicated successfully." msgstr "" +#: includes/extensions/account-tabs.php:148 +#: includes/extensions/profile-tabs.php:148 +msgid "Tabs have been duplicated successfully." +msgstr "" + #. %s - plugin name. #: um-polylang.php:69 #, php-format diff --git a/languages/um-polylang.pot b/languages/um-polylang.pot index a9956ae..3d40963 100644 --- a/languages/um-polylang.pot +++ b/languages/um-polylang.pot @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: Ultimate Member - Polylang\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-12-24 19:26+0000\n" +"POT-Creation-Date: 2024-11-10 20:47+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: \n" @@ -17,7 +17,7 @@ msgstr "" "X-Domain: um-polylang" #. %1$s - plugin name, %2$s - a list of forms. -#: includes/admin/class-admin.php:138 +#: includes/admin/class-admin.php:153 #, php-format msgid "" "%1$s needs to create required forms for every language to function correctly." @@ -25,22 +25,36 @@ msgid "" msgstr "" #. %1$s - plugin name, %2$s - a list of pages. -#: includes/admin/class-admin.php:213 +#: includes/admin/class-admin.php:226 #, php-format msgid "" "%1$s needs to create required pages for every language to function correctly." " Pages that need translation: %2$s" msgstr "" -#: includes/admin/class-admin.php:146 +#: includes/admin/class-admin.php:161 msgid "Create Forms" msgstr "" -#: includes/admin/class-admin.php:221 +#: includes/admin/class-admin.php:234 msgid "Create Pages" msgstr "" -#: includes/admin/class-admin.php:252 +#: includes/extensions/account-tabs.php:121 +#: includes/extensions/profile-tabs.php:121 +msgid "Create Tabs" +msgstr "" + +#. %1$s - a list of tabs. +#: includes/extensions/account-tabs.php:114 +#: includes/extensions/profile-tabs.php:114 +#, php-format +msgid "" +"Extension needs to create tabs for every language to function correctly. " +"Tabs that need translation: %1$s" +msgstr "" + +#: includes/admin/class-admin.php:264 msgid "Forms have been duplicated successfully." msgstr "" @@ -56,14 +70,21 @@ msgstr "" msgid "Integrates Ultimate Member with Polylang." msgstr "" -#: includes/admin/class-admin.php:147 includes/admin/class-admin.php:222 +#: includes/admin/class-admin.php:162 includes/admin/class-admin.php:235 +#: includes/extensions/account-tabs.php:122 +#: includes/extensions/profile-tabs.php:122 msgid "No thanks" msgstr "" -#: includes/admin/class-admin.php:256 +#: includes/admin/class-admin.php:268 msgid "Pages have been duplicated successfully." msgstr "" +#: includes/extensions/account-tabs.php:148 +#: includes/extensions/profile-tabs.php:148 +msgid "Tabs have been duplicated successfully." +msgstr "" + #. %s - plugin name. #: um-polylang.php:69 #, php-format diff --git a/readme.txt b/readme.txt index 3da2948..3e1ba5b 100644 --- a/readme.txt +++ b/readme.txt @@ -4,11 +4,11 @@ Author: umdevelopera Author URI: https://github.com/umdevelopera Plugin URI: https://github.com/umdevelopera/um-polylang Tags: ultimate member, polylang, multilingual -Requires at least: 5.5 -Tested up to: 6.4.2 +Requires at least: 6.5 +Tested up to: 6.7 Requires UM core at least: 2.6.8 -Tested UM core up to: 2.8.1 -Stable tag: 1.1.1 +Tested UM core up to: 2.9.1 +Stable tag: 1.2.0 License: GNU Version 2 or Any Later Version License URI: http://www.gnu.org/licenses/gpl-3.0.txt @@ -18,11 +18,14 @@ Integrates the "Ultimate Member" plugin with the "Polylang" plugin. Makes UM mul = Key Features = +* Language switcher shortcode. Displays the Polylang language switcher where you need it. * Localized permalinks for the Account and User (profile) pages. -* Ability to duplicate Ultimate Member forms for all languages in one click. * Ability to duplicate Ultimate Member pages for all languages in one click. +* Ability to duplicate Ultimate Member forms for all languages in one click. * Ability to translate email templates. * Ability to translate bio (description) field in profile. +* Integration with the Account tabs extension. Makes custom account tabs translatable. +* Integration with the Profile tabs extension. Makes custom profile tabs translatable. = Documentation & Support = @@ -38,32 +41,40 @@ Download ZIP file from GitHub or Google Drive. You can find download links here: == Changelog == += 1.2.0: November 10, 2024 = + +* Enhancements: + + - Added: Language switcher shortcode [um_pll_switcher]. + - Added: Integration with the Account tabs extension. Custom account tabs are translatable now. + - Added: Integration with the Profile tabs extension. Custom profile tabs are translatable now. + = 1.1.1: December 24, 2023 = -* Tweak: Displays forms/posts that need translation in the notice. -* Tweak: Copy fields to the draft when translating a form manually. -* Tweak: Automatically flush rewrite rules after bulk pages creation. + - Tweak: Displays forms/posts that need translation in the notice. + - Tweak: Copy fields to the draft when translating a form manually. + - Tweak: Automatically flush rewrite rules after bulk pages creation. = 1.1.0: December 4, 2023 = -* Added: Polylang integration for Ultimate Member forms. -* Added: The "Create Forms" notice and button. -* Added: The "Create Pages" notice and button. -* Added: The `lang` parameter to the account activation link. -* Added: Translation template (.pot file). -* Fixed: Classes autoloader issue: Class "um_ext\um_polylang\core\Fields" not found. + - Added: Polylang integration for Ultimate Member forms. + - Added: The "Create Forms" notice and button. + - Added: The "Create Pages" notice and button. + - Added: The `lang` parameter to the account activation link. + - Added: Translation template (.pot file). + - Fixed: Classes autoloader issue: Class "um_ext\um_polylang\core\Fields" not found. = 1.0.2: July 20, 2023 = -* Fixed: Translated description field value + - Fixed: Translated description field value = 1.0.1: June 21, 2023 = -* Added: A notice that Polylang plugin is required. -* Tweak: Flush rewrite rules on activation. -* Fixed: Account and profile links in the language switcher. -* Fixed: Conflict with WooCommerce in Account. + - Added: A notice that Polylang plugin is required. + - Tweak: Flush rewrite rules on activation. + - Fixed: Account and profile links in the language switcher. + - Fixed: Conflict with WooCommerce in Account. = 1.0.0: June 14, 2023 = -* Initial release. \ No newline at end of file + - Initial release. \ No newline at end of file diff --git a/um-polylang.php b/um-polylang.php index 7213c81..bea0857 100644 --- a/um-polylang.php +++ b/um-polylang.php @@ -8,12 +8,12 @@ * Text Domain: um-polylang * Domain Path: /languages * - * Version: 1.1.1 - * UM version: 2.7.0 - * Requires at least: 5.5 - * Requires PHP: 5.6 + * Requires at least: 6.5 + * Requires PHP: 7.4 + * UM version: 2.8.9 + * Version: 1.2.0 * - * @package UM Tools + * @package um_ext\um_polylang */ if ( ! defined( 'ABSPATH' ) ) { @@ -22,7 +22,7 @@ require_once ABSPATH . 'wp-admin/includes/plugin.php'; -$plugin_data = get_plugin_data( __FILE__ ); +$plugin_data = get_plugin_data( __FILE__, true, false ); define( 'um_polylang_url', plugin_dir_url( __FILE__ ) ); define( 'um_polylang_path', plugin_dir_path( __FILE__ ) ); @@ -30,13 +30,13 @@ define( 'um_polylang_extension', $plugin_data['Name'] ); define( 'um_polylang_version', $plugin_data['Version'] ); define( 'um_polylang_textdomain', 'um-polylang' ); -define( 'um_polylang_requires', '2.7.0' ); // Activation script. if ( ! function_exists( 'um_polylang_activation_hook' ) ) { function um_polylang_activation_hook() { if ( function_exists( 'UM' ) && function_exists( 'pll_languages_list' ) ) { + require_once 'includes/admin/class-admin.php'; require_once 'includes/core/class-setup.php'; if ( class_exists( 'um_ext\um_polylang\core\Setup' ) ) { $setup = new um_ext\um_polylang\core\Setup();