Accessing WordPress localization during plugin activation
September 7, 2015
Accessing WordPress translation capabilities out of the normal flow.
Translations please
I need some localized strings during the activation of a plugin.
Since the plugin is not activated yet the customary localization on the init
hook will not happen during the plugin activation request handling: any localization attempt will fail returning the original string.
In this specific case, in the User Groups Content Restriction plugin, I'm trying to insert some default terms
// in the main plugin class
public static function activate() {
ugcr_TermManager::instance()->remove_terms();
ugcr_TermManager::instance()->insert_terms();
}
The method of the code in charge of that
// in the ugcr_TermManager class
public function insert_terms() {
// Register taxonomies to avoid errors
register_taxonomy( ugcr_Plugin::$taxonomy_name, null );
register_taxonomy( ugcr_Plugin::$post_taxonomy_name, null );
// Get default terms with localized names...
$terms = $this->get_additional_terms();
// ...insert terms and so on...
}
is using an helper method to insert the default terms with localized names
public function get_additional_terms() {
return array(
array(
'slug' => 'logged-in',
'name' => __( 'Logged-in users', 'ugcr' )
),
array(
'slug' => 'visitor',
'name' => __( 'Visitors', 'ugcr' )
)
);
}
Manually loading a required text domain
Hacking the flow and manually loading the required localization file is not a big lift and WordPress will graciously lend itself to it.
Modifying the insert_terms
method will fix non working translations
public function insert_terms() {
// In need of translated strings now...
global $l10n;
$l10n = is_array($l10n) ? $l10n : array();
$languages_dir = dirname( dirname( __FILE__ ) ) . '/languages/';
$mo_file = 'ugcr-' . get_locale() . '.mo';
load_textdomain( 'ugcr', $dir . $file );
// Register taxonomies to avoid errors
register_taxonomy( ugcr_Plugin::$taxonomy_name, null );
register_taxonomy( ugcr_Plugin::$post_taxonomy_name, null );
$terms = $this->get_additional_terms();
// ...insert terms and so on...
}
WordPress will take care, under the hood, to handle non existing localization files or strings as usual.
Other ways?
Option
I think the above operation should happen during activation but another way would have been to hook the term insertion on the shutdown
method behind an option toggle like
// the main plugin class will register its hooks here
public function hooks() {
add_action( 'init', array( $this, 'localization_init' ) );
add_action( 'init', array( $this, 'register_taxonomy' ) );
add_action('init', array(ugcr_TermManager::instance(), 'insert_terms'));
}
// in the ugcr_TermManager class
public function insert_terms() {
$version = 1;
if(get_option('ugcr_did_insert_terms', 0) >= $version){
return;
}
// Get default terms with localized names...
$terms = $this->get_additional_terms();
// ...insert terms and so on...
// update the option
update_option('ugcr_did_insert_terms', $version);
}
What I do not like about this approach is that it does not feel less hacky to me and runs on each page load.
Cron
Another option is a cron job
// in the main plugin class
public static function activate() {
ugcr_TermManager::instance()->remove_terms();
ugcr_TermManager::instance()->insert_terms();
wp_schedule_single_event(time() + 10, 'ugcr_first_run');
}
// the main plugin class will register its hooks here
public function hooks() {
add_action( 'init', array( $this, 'localization_init' ) );
add_action( 'init', array( $this, 'register_taxonomy' ) );
add_action('ugcr_first_run', array(ugcr_TermManager::instance(), 'insert_terms'));
}
This is a more elegant solution but still I feel like an initialization task should not leave traces in the normal plugin flow.
Personal taste in the end.