Because WPML creates posts and pages for each language, comments from one do not appear on the other.

This plugin merges comments from all WPML translations of the posts and pages so that they all are displayed on each other.

Comments are internally still attached to the post or page they were made on.

It uses the get_comments() API call, which in some circumstances might not return all posts.

This is a fixed version of the no longer maintained WPML Comment Merging plugin:
https://wordpress.org/extend/plugins/wpml-comment-merging/

Thanks to Simon Wheatley for contributing the fix.

Forked from: https://github.com/jgalea/wpml-comments-merging

Recently I was working on a new client's website using the Divi theme and they wanted a nice visual video background as the homepage hero, so to clean up the visual appeal of the site I wanted to set the Divi header background to transparent, and on scroll bring the background back in.

Below is my quick and not-so-dirty CSS to remove the Divi header background colour until scroll

body.home #page-container {
    padding-top: 0 !important;
}
body.home #main-header {
    background-color: transparent !important;
    box-shadow: none;
}
body.home header#main-header.et-fixed-header {
    background: #fff !important;
}

Please note that the code above is meant only for the homepage, if you remove the body.home it'll reflect on the entire site

Leave a comment below if you have a better way to achieve this or if this piece of CSS worked for you! Until next time.

If you have been looking to translate the group name and description with WPML on BuddyPress and/or BuddyBoss platform and you found yourself on the WPML support forums with answers like "Unfortunately it is not possible to translate e group names and descriptions yet." or "Actually I am not sure if this is possible...".

Well, you're in luck!

Because I spent countless minutes (mostly because I forgot to turn on my time tracker) trying to figure out how to resolve this naggin' issue with the simplistic grace of translating using WPML.

Before diving deep into the code and breaking your frontal lobe on why it isn't working only to figure out you're missing an ; or forgetting to close something, let's all take a step back and return to elementary school with the good ol' paper and pencil.

But since the invention of the internet and the modern-day phone, we'll settle for notepad or a plain-text text editor.

What do I want to use?

  • WPML
  • BuddyPress/Boss
  • ACF Pro specifically the Options Page

What do I need to make this work?

There are always going to be things you are not going to think about before you achieve your end goal but knowing what your end goal is and planning steps on how you can get to that goal is half the battle. I find thinking (mostly drawing doodles) helps me a lot more than 10 thousand open tabs.

 

How do I determine the current language on WPML?

Having to work on past jobs and projects using WPML, I know exactly what to search for.

So with that, I'm one step closer to my master plan.. to resolve translating BuddyPress's group name and description.

 

Where can I find the template file for the BuddyPress Group Name and Description?

This step may be easy for me to figure out but you really need to know and learn about WordPress Child Themes, if you're not using Child Themes on your client's site you are in for a future headache, so save yourself some stress and some unread ATTN: important emails, and learn about child themes and templates.

If you know about child themes and overriding the parent theme template, my trick is copying and searching the class name in the template file to see if I'm on the right track. And if I do find the class name I simply add a class name of test afterward (with a space of course) and then saving the file, pressing F12, and right-clicking on the refresh button, and selecting Clear Cache and Hard Reload. Sometime's it takes a minute before it shows usually it is because of a caching plugin or because of server cache / CDN.

For the BuddyPress group name and description its in the cover-image-header.php file in /buddypress/members/single/ with the class name of .bb-bp-group-title for the name and .group-description for the description.

Now that we know where the name and description are pulling from and we also know that we can override the theme template file within our child theme, we're like 2 steps in achieving our end goal. *high-five*

Next step: Apply the WPML if statement and see if the name and description change when I click on the WPML language switcher. For this, you'll need to know the WPML language code for your 2nd language, for moi - it's french, for obvious reasons because I'm from Canada.

Inside the cover-image-header.php file on Line 95 you'll find the group title and on Line 104 you'll find the group description

The following echo statements show how the group's name and description are being called, so taking that we can add our WPML if language statement.

<?php echo esc_attr( bp_get_group_name() ); ?>
<?php echo bp_nouveau_group_meta()->description; ?>

Be sure to comment out the original code so there it doesn't show doubles and/or confuse you later on.

So, we end up with the following - it's static for now, nothing fancy we just want to make sure it works.

<?php
if(ICL_LANGUAGE_CODE=='fr') {
    echo 'Bonjour le monde!';
} else {
    echo esc_attr( bp_get_group_name() );
}
?>

Ok, now let's repeat that for the description also.

<?php
if(ICL_LANGUAGE_CODE=='fr') {
    echo 'Bonjour le monde!';
} else {
    echo bp_nouveau_group_meta()->description;
}
?>

 

How can I determine the BuddyPress group and sync it with ACF on the options page?

Step 3a - Get the Options Page (You'll need ACF Pro, worth every penny - save yourself trouble and buy back some time)

if( function_exists('acf_add_options_page') ) {
    acf_add_options_page();
}

Step 3b - Setup the Options Page Field Group

By default, ACF is not translatable in WPML; usually, you'll need to check the theme or plugin in the Theme and plugins localization panel but we'll just create a dummy ACF field group. The name doesn't matter just need to create an initial field group.

Once that group is created; scroll down to the bottom and look for the Multilingual Content Setup meta box and select Make 'Field Groups' translatable and click Apply

Multilingual Content Setup

This should create a tab for the 2nd language on the ACF field group page, so delete the original dummy ACF field group and click on that 2nd language to create the ACF field group you will be working with.

WPML ACF Setup

Step 3c - Setup the Repeater Field

Now, you may ask how I ended up deciding to use the repeater field rather than creating a text field for the name and description for the group's translation. There is really no way to determine how many groups there would be in the future so by using the repeater field we are able to future-proof this bootlegged setup for as long as possible until WPML or BuddyPress decides to support the translation of the name and description of the groups.

Give this repeater field a label and copy the label name to a text editor to be used later.

Create 3 repeater sub-fields: slug, name, and description

ACF Sub Fields

Basically, the idea is to determine the group's slug and if the slug is X then pull the 2nd language's name and description. Sounds simple but just you wait.

First, we need to find the groups slug - you'll most likely end up finding bp_is_groups_component() first but this function isn't it. The bp_is_groups_component() function will only return true if its a group's component so every group would return true so it won't be able to separate each group; which is what we need to make this work.

The function you will need is bp_get_current_group_slug(), this built-in function returns the group's slug - how I knew to use the slug at the start you may ask? I didn't - I was guestimating what I could use based on my history of working with WordPress, slugs, ids whatever. Sometimes plugins don't have such built-in functions it's just the nature of the game.

Next you'll need the ACF repeater fields to pull in the data of each row on that field group from the options page

if ( bp_get_current_group_slug() == get_sub_field('group_slug') ) {
    echo get_sub_field('group_description');
}

"Amaaaaazzzing...I got this solved.." is something you might be saying right now because that was what I was thinking when I got here - but you also might be thinking that really don't need the rest of the post and you might be right; right after you enter your email and the 3 digits on the back of your credit card.

Even if you get the repeater (sub)fields working and you think it's done and send that (regrettable) email to your client saying it's done without doing QA; you'll probably miss some view/page that no one really goes to but the client/customer.

So back to the problem at hand.

There are some realizations you might have landed on at this step of the progress, such as...

  1. What if the group name and description don't have a translation on the options page?
  2. Will the original language name and description show?

This was the step that took me the most time and almost broke my brain in an endless if-else hell but the solution to the problem was so simple.

You'll probably think you'll need to count how many rows there are on the options page and display the original name and description after the loop is finished with an else statement, but you don't need to.

What you need to do is when the group's slug if statement fails display the name and description once with the count function.

You'll end up with something like this for the group name:

<?php
if(ICL_LANGUAGE_CODE=='fr') {
	if( have_rows('group_french_translation', 'option') ) {
		$count = 0;
		while( have_rows('group_french_translation', 'option') ) {
			$count ++;
			the_row();
			if ( bp_get_current_group_slug() == get_sub_field('group_slug') ) {
				echo get_sub_field('group_title');
			} else if ( $count <= 1 ) {
				echo esc_attr( bp_get_group_name() );
			}
		}
	} else {
		echo esc_attr( bp_get_group_name() );
	}
} else {
	echo esc_attr( bp_get_group_name() );
}
?>

and this for the group description:

<?php
if(ICL_LANGUAGE_CODE=='fr') {
    if( have_rows('group_french_translation', 'option') ) {
        $count = 0;
        while( have_rows('group_french_translation', 'option') ) {
            $count ++;
            the_row();
            if ( bp_get_current_group_slug() == get_sub_field('group_slug') ) {
                echo get_sub_field('group_description');
            } else if ( $count <= 1 ) {
                echo bp_nouveau_group_meta()->description;
            }
        }
    } else {
        echo bp_nouveau_group_meta()->description;
    }
} else {
    echo bp_nouveau_group_meta()->description;
}
?>

I've been told by my friends countless times that I don't explain my thought process and that I land on conclusions without properly explaining how I got there, so please leave a comment below if you think I've missed a step or if you have a better long term solution for this problem leave a comment below. Until next time.

Note: Ninja Forms version 3.4.31 and above no longer uses PikaDate it was updated to Flatpickr

While working on a recent project I needed to disable specific dates on the date picker within Ninja Forms.

I kept running into Uncaught SyntaxError: Invalid or unexpected token error when using the disableDayFn function while following the date picker documentation. After testing on my client's site for a few hours I had thought the documentation was outdated. It turns out I was wrong1.

Ninja Forms Setup

Finally I decided that maybe I should test on my local environment instead of a live website, so I spun up my local WordPress install, installed ninja forms, and imported a test form.

Then carefully coping over each piece of code from the documentation over one by one but this time instead I would not combine the two JS files but keep them separate. Not sure why but this seemed to have worked and resolved my SyntaxError for the disableDayFn.

So keep the scripts.js and customDatePicker.js separate.

After cleaning all the comments and removing the labels and enabled days functions I was left with this:

var customDatePickerStuff = Marionette.Object.extend( {
    initialize: function() {
        this.listenTo( Backbone.Radio.channel( 'pikaday' ), 'init', this.modifyDatepicker );	
    },
    modifyDatepicker: function( dateObject, fieldModel ) {
        dateObject.pikaday._o.disableDayFn = function( date ) {
            var disabledDays = ["2017-04-28", "2017-04-29", "2017-04-30"];
            if ( _.indexOf( disabledDays, moment( date ).format( "YYYY-MM-DD" ) ) !== –1 ) {
                return true;
            }
        }
    }
});
jQuery( document ).ready( function() {
	new customDatePickerStuff();
} );

1Update October 29th 2020:

Emailed Free Support and heres what they found

I figured out the syntax issue. It was missing a parenthesis around the 'if' statement. See the following code,

dateObject.pikaday._o.disableDayFn = function( date ) {
            var disabledDays = ["2020-10-29"];

            if ( (_.indexOf( disabledDays, moment( date ).format( "YYYY-MM-DD" ) ) ) !== -1 ) {
                return true;
            }
        }

Once you add the parenthesis it disables all days except for the 29th .... or whatever days you want disabled. Please let us know if you need anything else.

Step 1. Completed. ff..finally.

Setup ACF Options Page and repeater fields.

//ACF Options Page
if( function_exists('acf_add_options_page') ) {
	acf_add_options_page();
}

After updated the disabledDays array to more current/futures dates to test, the dates are disabled.

A good sign of progress.

During the ACF repeater field setup, you'll need to match the date format to the disabledDays array above. So in the date subfield select the return format to custom and enter

Y-m-d

One step forward another step back

While going down another Google rabbit hole and open tabs hell, I decided to just search the ACF support forums (because I'm definitely not the only one who had had this question of getting ACF repeater values into a JavaScript file) and BOOM found like 2 articles [1][2].

Question: How do I pass ACF field values into a JavaScript file?

Answer: wp_localize_script

/*
 * Plugin Name: Ninja Forms – Datepicker Customizations
 */
add_filter( 'ninja_forms_enqueue_scripts', 'nf_datepicker_options' );
function nf_datepicker_options() {
	wp_enqueue_script( 'nf_datepicker_options', plugin_dir_url( __FILE__ ) . 'script.js', array( 'jquery' ), false, true );

	wp_register_script( 'nf_datepicker_options-custom', plugin_dir_url( __FILE__ ) . 'customDatePicker.js' );
	wp_localize_script( 'nf_datepicker_options-custom', 'acf_dates', array(
        'block_dates' => get_field("block_dates", 'option')
    ) );
	wp_enqueue_script( 'nf_datepicker_options-custom' );
}

Sounds nice and easy right?

It is actually is pretty easy. Just pass in the field names into wp_localize_script

wp_localize_script( 'nf_datepicker_options-custom', 'acf_data', array(
    'field_name' => get_field("field_name"),
    'field_type' => get_field("field_type", 'option') // if youre using the options page
) );

Inside the JS file, call the data:

console.log ( acf_data.field_name );
console.log ( acf_data.field_type );

So close yet so far.

First, move the disabledDays array out of the modifyDatepicker function and after a lot of console.logging, hard refreshes, clearing the browser cache and 1 final 'quick' google search on "convert nested objects to an array, javascript" and landing on stack overflow one final time, thanks internet! You're really the one doing my job for me!

const array = acf_dates.block_dates;
var disabledDays = [].concat(...array.map(Object.values));
var customDatePickerStuff = Marionette.Object.extend( {
    initialize: function() {
        this.listenTo( Backbone.Radio.channel( 'pikaday' ), 'init', this.modifyDatepicker );	
    },
    modifyDatepicker: function( dateObject, fieldModel ) {
        dateObject.pikaday._o.disableDayFn = function( date ) {
            if ( _.indexOf( disabledDays, moment( date ).format( "YYYY-MM-DD" ) ) !== -1 ) {
                return true;
            }
        }
    }
});
jQuery( document ).ready( function() {
    new customDatePickerStuff();
} );

Hope this will help someone spend less time in front of the computer screen and more time outside maybe... leave a comment in the comments below.

Update November 24th 2020:

Recently updated Ninja Forms on the client's site and all the hard work above came crashing down below is what Ninja Form Free Support said in an email

In the Ninja Forms version 3.4.31 and above the library for the Date field was updated to use the Flatpickr library.

The developer documentation has not yet been updated for the Flatpickr at this time.

While custom code is outside the scope of support that we're able to help with, you can find documentation for Flatpickr here:
https://flatpickr.js.org/

Update February 7th 2021:

If you're looking to disable the past dates on the date picker; check out the updated code here

Recently when working on a client's website I needed to use the ACF repeater fields on a WordPress site that was built on Divi. After doing a quick google search and reading a few articles it seemed normal ACF fields on Divi's modules work flawlessly but when it comes to the repeater fields there seem to be technical issues and after a search on ACF support, it looks like I was not the only one with the same problem.

So I've created a custom page template for the custom post type because how else am I going to get the repeater fields showing up on the page, I completed the page and nonetheless the client ends up asking for the content to be put into tabs. I initially thought of adding bootstrap for it's tabbed featured and quickly remembered and realized that it may conflict with Divi and that Divi had its own built-in tab module.

Inserting Divi Modules into the templates

Instead of rebuilding the own page on a Divi, I decided to use the page template but somehow integrate the Divi tab module into my page template. So after a quick google search, I ended up on a post about how to integrate Divi section into a page template, so after skimming through the article I ended finding the piece of code I needed;

<?php echo do_shortcode('[et_pb_section global_module="198"][/et_pb_section]'); ?>

Using the Divi library you can create a section with any module and using the shortcode above you can insert into any page template you'll need the module on.

With that, I created the tab module with a few test tabs and sure enough the module loaded onto the page where I had inserted the line of code, now to get the ACF repeater field working on the module.

In comes ACF Repeater

I know I needed PHP for the ACF repeater fields to work properly so from my older work I've learned using shortcodes to run code is a neat little trick and works almost everywhere in WordPress and could get anything done and it's in the functions.php file so it can run PHP!

Using the WordPress shortcode API and ob_start(); I've created a simple solution to the problem with displaying ACF repeater fields in Divi modules.

Just place inside your functions.php file and add your ACF repeater fields coding inside, then add the shortcode (in this case [foobar]) to the Divi module

function foobar_func( $atts ){
ob_start();
//ACF fields here
return ob_get_clean();
}
add_shortcode( 'foobar', 'foobar_func' );

Let me know in the comments before if it works for you or if you have another way to add the ACF repeater fields to the Divi modules

Today I was trying to look for how to add an item count to the shopping cart on the Divi theme, I couldn't find exactly what I was looking for although I did manage to find a few examples on StackOverflow and other websites that work with woocommerce on other themes but on divi it did not work at all.

After searching the divi support forum and documentation I did manage to find a few articles that were exactly what I was looking for however the articles are for members only. Being a freelancer I may have to work with any themes or plugins my clients may have on their website as it was in this case.

So instead of contacting my client and going through email hell for my client and myself, I started taking a look into the header.php file in the Divi Theme - thankfully one of my first tasks when taking on the client was to create a child theme.

Searching for the Divi Item Count Solution

After looking for a minute I finally found what I was looking for and luckily it was a very simple change to display the item count on the shopping cart icon on the menu.

First, you'll need to copy the header.php file from the divi theme into your divi-child theme then on or around Line 285 you'll find an array with:

'no_text' => true,

You'll need to change the true to false

'no_text' => false,

Save the header.php file.

Making the change on the child theme is important so any future updates to the divi theme won't overwrite any changes previously made.

After this small change, you'll see the number of items next to the cart icon on the main navigation menu, you may have to style the icon and text a little bit, but for the most part its there.

Let me know if this worked out for you or you have another way around this in the comments below!

Recently I was trying to sort some products on WooCommerce for one of my clients and ended up doing a quick little Google search. I found all the top search results were pretty outdated, most of the posts were from 2015. WooCommerce has been through a few updates since then and the process to sort the products on the shop page is different.

In WooCommerce 3.7 to sort the products on the shop page is super simple you  just have to go to:

Products > All Products > Sorting

Then you can drag and drop how you want the products to display on the shop page.

And thats it.

Work Experience
Andar Software Ltd.
Front-End Web Developer
08 / 2022 - Present
08 / 2015 - 06 / 2019
9345-1961 Quebec Inc.
Wordpress Developer
09 / 2021 - 08 / 2022
Yellow Pages
Front-End Developer
06 / 2019 - 11 / 2020
perpetual media ltd.
Developer
2011 - 2022
iPosco Systems Inc.
Web & Graphic Designer
12 / 2011
Technology Stack
Adobe Creative Cloud
HTML 5
CSS 3
JS / jQuery
PHP
mySQL / msSQL
Wordpress / WooCommerce
Shopify
Bootstrap
React
Solidity
web3.js
Laravel
Tailwind
AplineJS
Livewire
© 2024 PERPETUAL MEDIA LTD
rickypoon.ca
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram