Creating your own Stella Widget

Our multilingual localization plugin for WordPress, Stella, has been out for a while, and we received a lot of useful feedback from our customers. Quite a plenty of our tech support emails asked how to create a language dropdown select widget, so we decided to write a tutorial on creating your own custom widget for Stella. At the end, you can download the source code in a form of a plugin.

Stella is for WordPress, and WordPress is for … themes. :) Anyway, we usually want to customize the look and feel of our website. And Stella is no exception: it provides a lightweight widget to display a language switcher ( Appearance -> Widgets -> Stella language menu), that you may want to change.

This tutorial will show you how to do it. First, let’s make a plan: what do we need to achieve?

  1. Create a standard WordPress widget in a form of plugin.
  2. Obtain the language list from Stella.
  3. Show the language list in a different way than Stella does – with drop down.

 

WordPress widget

To create a widget for WordPress you need just to inherit WP_Widget class and override WP_Widget::widget() .

class Stella_Drop_Down_Widget extends WP_Widget {
       function widget($args, $instance) {
	extract( $args );
	$title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Language' ) : $instance['title'], $instance, $this->id_base);
	$before_widget .= '<div  class="cssmenu"><ul><li>';
	$after_widget = '</li></ul></div>' . $after_widget;

	echo $before_widget;

	if ( ! empty( $title ) ) {
	    if ( '<h3 class="widget-title">' == $before_title )
		$before_title = '<a href="javascript:;" ><span>';

	    if ( '</h3>' == $after_title )
	    	$after_title = '</span></a>';

	    echo $before_title . $title . $after_title;
	}

	echo $after_widget;
    }
}

In the code above, there is a little complex, but flexible output of the widget. If you want to manually call this widget, it will be possible to tell the widget to use custom $before_title, $after_title, $before_widget, $after_widget and even to hook ‘widget_title’! It’s cool, isn’t it?

The markup that we created in this step will be used later.
This:

<h3 class="widget-title">

is the default value for $before_title, so if it’s customized by user ( by passing explicit parameters ), then we will use user-defined value here.

Next, the widget should be registered in WordPress (that’s the reason why widgets appear in Appearance -> Widgets). So we need to add it into WordPress widget creation queue:

add_action( 'widgets_init', create_function( '', 'register_widget( "Stella_Drop_Down_Widget" );' ));

And, give it an unique name and description by calling parent constructor method:

parent::__construct(
            'drop_down_stella_widget', // Base ID
	    'Stella drop down', // Widget name
	    array( 'description' => 'Shows the language selection menu') // Widget description
        );

To use this widget as standalone plugin, we need to add plugin header:

/*
Plugin Name: Stella Drop Down
Plugin URI: http://theme.fm/?p=3581
Description: Creates drop down language switcher for Stella plugin.
Version: 1.0
Author: Artem Popov
Author URI: http://theme.com
License: GPL2
*/

Now the widget shows itself in Appearance -> Widgets and works properly.

<?php
/*
Plugin Name: Stella Drop Down
Plugin URI: http://theme.fm/?p=3581
Description: Creates drop down language switcher for Stella plugin.
Version: 1.0
Author: Artem Popov
Author URI: http://theme.com
License: GPL2
*/
class Drop_Down_Stella_Widget extends WP_Widget{
    function __construct() {
        parent::__construct(
            'drop_down_stella_widget', // Base ID
	    'Stella drop down', // Widget name
	    array( 'description' => 'Shows the language selection menu') // Widget description
        );
    }
    function widget($args, $instance) {
	extract( $args );
	$title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Language' ) : $instance['title'], $instance, $this->id_base);
	$before_widget .= '<div  class="cssmenu"><ul><li>';
	$after_widget = '</li></ul></div>' . $after_widget;

	echo $before_widget;

	if ( ! empty( $title ) ) {
	    if ( '<h3 class="widget-title">' == $before_title )
		$before_title = '<a href="javascript:;" ><span>';

	    if ( '</h3>' == $after_title )
	    	$after_title = '</span></a>';

	    echo $before_title . $title . $after_title;
	}
	echo $after_widget;
    }
}
add_action( 'widgets_init', create_function( '', 'register_widget( "Drop_Down_Stella_Widget" );' ));

Obtain Stella language list

There are 2 methods of obtaining registered languages in Stella. First method is to use the function:

stella_get_lang_list();

But I prefer the second method. Add this code into widget constuctor:

$this->lang_list = apply_filters( 'stella_get_lang_list', array() );

And this method for output language list:

private function __get_switcher_html( $id ) {
		$html = '';
		if( isset( $this->lang_list ) ){
			foreach ( $this->lang_list as $prefix=>$item ){
				$href = is_ssl() ? 'https://'.$item['href'] : 'http://'.$item['href'];
				$html.= '<li><a href="'.$href.'"><span>'.$item['title'].'</span></a></li>';
			}
		}

		return  '<ul>' . $html . '</ul>';
	}

Now, call it before ‘echo $after_widget’ in the widget() method:

echo $this->__get_switcher_html(  $args['widget_id'] );

Double underscores in function name say: ‘Do not call me outside the class, I’m a private method!’. Actially this is mainly for developer, PHP likes private keyword more.

<?php
/*
Plugin Name: Stella Drop Down
Plugin URI: http://theme.fm/?p=3581
Description: Creates drop down language switcher for Stella plugin.
Version: 1.0
Author: Artem Popov
Author URI: http://theme.com
License: GPL2
*/
class Stella_Drop_Down_Widget extends WP_Widget{
    function __construct() {
        parent::__construct(
            'drop_down_stella_widget', // Base ID
	    'Stella drop down', // Widget name
	    array( 'description' => 'Shows the language selection menu') // Widget description
        );
        $this->lang_list = apply_filters( 'stella_get_lang_list', array() );
    }
    function widget($args, $instance) {
	extract( $args );
	$title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Language' ) : $instance['title'], $instance, $this->id_base);
	$before_widget .= '<div  class="cssmenu"><ul><li>';
	$after_widget = '</li></ul></div>' . $after_widget;

	echo $before_widget;

	if ( ! empty( $title ) ) {
	    if ( '<h3 class="widget-title">' == $before_title )
		$before_title = '<a href="javascript:;" ><span>';

	    if ( '</h3>' == $after_title )
	    	$after_title = '</span></a>';

	    echo $before_title . $title . $after_title;
	}
        echo $this->__get_switcher_html( $args['widget_id'] );
	echo $after_widget;
    }
    private function __get_switcher_html( $id ) {
		$html = '';
		if( isset( $this->lang_list ) ){
			foreach ( $this->lang_list as $prefix=>$item ){
				$href = is_ssl() ? 'https://'.$item['href'] : 'http://'.$item['href'];
				$html.= '<li><a href="'.$href.'"><span>'.$item['title'].'</span></a></li>';
			}
		}

		return  '<ul>' . $html . '</ul>';
	}
}
add_action( 'widgets_init', create_function( '', 'register_widget( "Stella_Drop_Down_Widget" );' ));

Now, we have the widget that mostly recreates default Stella widget. Let’s make it drop down.

Make drop down

Surprisingly, but to make this language list drop down, we just need to add style file. Markup for them is already integrated into the code. Adding explicit styles into the theme:

class Stella_Drop_Down_Styles {
    function __construct() {
        add_action('wp_enqueue_scripts', array( $this, 'add_scripts' ) );

    }
    function add_scripts() {
        $path = trailingslashit( plugins_url( basename( dirname( __FILE__ ) ) ) );
        wp_enqueue_style( 'stella-drop-down', $path . "/css/stella-drop-down.css", null, '1.0'  );
    }
}
new Stella_Drop_Down_Styles();

I guess there is no need to describe these lines, may be it’s enough just to comment that this peace of code returns correct path even if there are symbolic links in this path:

$path = trailingslashit( plugins_url( basename( dirname( __FILE__ ) ) ) );

For the CSS file used in this example, please look at the zip file below, that contains this free widget. I’ve used these styles, but they can be changed a lot if you wish. That’s the result:

<?php
/*
Plugin Name: Stella Drop Down
Plugin URI: http://theme.fm/?p=3581
Description: Creates drop down language switcher for Stella plugin.
Version: 1.0
Author: Artem Popov
Author URI: http://theme.com
License: GPL2
*/
class Stella_Drop_Down_Widget extends WP_Widget{
    function __construct() {
        parent::__construct(
            'drop_down_stella_widget', // Base ID
	    'Stella drop down', // Widget name
	    array( 'description' => 'Shows the language selection menu') // Widget description
        );
        $this->lang_list = apply_filters( 'stella_get_lang_list', array() );
    }
    function widget($args, $instance) {
	extract( $args );
	$title = apply_filters('widget_title', empty( $instance['title'] ) ? __( 'Language' ) : $instance['title'], $instance, $this->id_base);
	$before_widget .= '<div  class="cssmenu"><ul><li>';
	$after_widget = '</li></ul></div>' . $after_widget;

	echo $before_widget;

	if ( ! empty( $title ) ) {
	    if ( '<h3 class="widget-title">' == $before_title )
		$before_title = '<a href="javascript:;" ><span>';

	    if ( '</h3>' == $after_title )
	    	$after_title = '</span></a>';

	    echo $before_title . $title . $after_title;
	}
        echo $this->__get_switcher_html( $args['widget_id'] );
	echo $after_widget;
    }
    private function __get_switcher_html( $id ) {
		$html = '';
		if( isset( $this->lang_list ) ){
			foreach ( $this->lang_list as $prefix=>$item ){
				$href = is_ssl() ? 'https://'.$item['href'] : 'http://'.$item['href'];
				$html.= '<li><a href="'.$href.'"><span>'.$item['title'].'</span></a></li>';
			}
		}

		return  '<ul>' . $html . '</ul>';
	}
}
add_action( 'widgets_init', create_function( '', 'register_widget( "Stella_Drop_Down_Widget" );' ));

class Stella_Drop_Down_Styles {
    function __construct() {
        add_action('wp_enqueue_scripts', array( $this, 'add_scripts' ) );

    }
    function add_scripts() {
        $path = trailingslashit( plugins_url( basename( dirname( __FILE__ ) ) ) );
        wp_enqueue_style( 'stella-drop-down', $path . "/css/stella-drop-down.css", null, '1.0'  );
    }
}
new Stella_Drop_Down_Styles();

Click here to download widget.
Visit Store