Manual de WordPress: Internacionalizar un plugin

Dado que WordPress se usa a escala internacional es altamente recomendable internacionalizar nuestro plugin, es decir, prepararlo para que los textos se muestren en diferentes idiomas.

Recursos

Previamente tendremos que establecer las locale editando wp-config.php:

define ('WPLANG', 'es_ES');

WordPress usa para i18n (internationalization, 18 letras entre la i y la n) la librería gettext (GNU internationalization utilities). Lo más práctico es hacer el plugin en inglés y prepararlo para su traducción utilizando las funciones __() y _e(), añadiendo como argumento el text domain, el identificador que permite a WordPress distinguir qué traducción utilizar de las disponibles. Lo más recomendable es utilizar como text domain el nombre del directorio del plugin, en nuestro caso helloworld. Marcaremos en nuestro código las cadenas traducibles de esta manera:

  • función __(): en las cadenas, en vez de…
    <?php
    echo "<h2>Blog Options</h2>";
    ?>

    … usaremos:

    <?php
    echo "<h2>".__('Blog Options', 'helloworld')."</h2>";
    ?>
  • función _e(): si usamos echo, en vez de…
    <?php
    echo "We deleted spams";
    ?>

    … usaremos:

    <?php
    _e("We deleted spams", "helloworld");
    ?>

Vamos a añadir soporte para idiomas en el plugin "Hello World 1.0" obteniendo de esa manera la versión "Hello World 2.0". A los dos archivos que formaban el plugin:
helloworld.php
readme.txt
ubicados en el directorio:
wp-content/plugins/helloworld/
añadiremos tres más:
helloworld.pot
helloworld-es_ES.po
helloworld-es_ES.mo
ubicados en este caso en el directorio:
wp-content/plugins/helloworld/lang/

Comenzaremos editando el archivo helloworld.php de "Hello World 1.0" y marcando con __() o _e() las cadenas traducibles…

<?php
// registrar la funcion que se ejecuta al activar el plugin
register_activation_hook(__FILE__, 'helloworld_activate');
// funcion que se ejecuta al activar el plugin
function helloworld_activate() {
    // crear la tabla del plugin e insertar dos registros
    global $wpdb;
    $table_name= $wpdb->prefix."helloworld";
 
       $sql = "CREATE TABLE $table_name (
        `id` mediumint( 9 ) NOT NULL auto_increment,
        `type` tinytext NOT NULL,
        `saludo` tinytext NOT NULL,
        PRIMARY KEY  (`id`)
        )";
    $wpdb->query($sql);
 
    $sql = "INSERT INTO $table_name (`id`, `type`, `saludo`)
        VALUES (1, 'default', 'Hello World')";
    $wpdb->query($sql);
 
    $sql = "INSERT INTO $table_name (`id`, `type`, `saludo`)
        VALUES (2, 'custom', 'Hola Mundo')";
    $wpdb->query($sql);
 
    // añadir la option del plugin
    add_option('helloworld_saludo_type', 'default');
}
 
// registrar la funcion que se ejecuta al desactivar el plugin
register_deactivation_hook(__FILE__, 'helloworld_deactivate');
// funcion que se ejecuta al desactivar el plugin
function helloworld_deactivate() {
    // borrar la tabla del plugin
    global $wpdb;
    $table_name = $wpdb->prefix."helloworld";
 
    $sql = "DROP TABLE $table_name";
    $wpdb->query($sql);
 
    // borrar la option del plugin
    delete_option('helloworld_saludo_type');
}
 
// crear un item en el panel de administracion
add_action('admin_menu', 'helloworld_menu');
// crear la pagina de opciones del plugin
function helloworld_menu() {
    add_options_page('Hello World plugin options', 'Hello World', 8,
        basename(__FILE__), 'helloworld_options');
}
// funcion que muestra la pagina de opciones del plugin
function helloworld_options() {
    // comprobar si la peticion procede del form
    global $wpdb;
    $table_name = $wpdb->prefix."helloworld";
    if (isset($_POST['saludo_custom_new'])
        && !empty($_POST['saludo_custom_new'])) {
        $sql = "UPDATE $table_name
            SET saludo ='{$_POST['saludo_custom_new']}'
            WHERE type='custom'";
        $wpdb->query($sql);
    }
    if (isset($_POST['saludo_type'])) {
        update_option('helloworld_saludo_type', $_POST['saludo_type']);
    }
 
    // mostrar la pagina de opciones
    $saludo_default = $wpdb->get_var("SELECT saludo
        FROM $table_name
        WHERE type='default'" );
    $saludo_custom = $wpdb->get_var("SELECT saludo
        FROM $table_name
        WHERE type='custom'" );
    $saludo_type = get_option('helloworld_saludo_type');
    if ($saludo_type == "default") {
        $checked_default = "checked";
        $checked_custom = "";
    } else {
        $checked_default = "";
        $checked_custom = "checked";
    }
    echo "<div class='wrap'>n";
    echo "<h2>Hello World plugin options</h2>n";
    echo "<form method='post' action=''>n";
    echo "Display:<br />n";
    echo "<input type='radio' name='saludo_type' value='default'
        ".$checked_default." /> Message default
        (<b>".$saludo_default."</b>)<br />n";
    echo "<input type='radio' name='saludo_type' value='custom'
        ".$checked_custom." /> Message custom
        (<b>".$saludo_custom."</b>)<br />n";
    echo "New Message custom: <input type='text'
        name='saludo_custom_new' /><br />n";
    echo "<input type='submit' name='update' value='Update' />n";
    echo "</form>n";
    echo "</div>n";
}
 
// funcion del plugin para usar en PHP, devuelve un string
function helloworld() {
    // recuperar el saludo
    global $wpdb;
    $table_name = $wpdb->prefix."helloworld";
    $saludo_type = get_option('helloworld_saludo_type');
    $saludo = $wpdb->get_var("SELECT saludo
        FROM $table_name
        WHERE type='$saludo_type'" );
    // output del plugin
    return "<p>".$saludo."</p>n";
}
 
// registrar la funcion que se ejecuta al llamar al shortcode
add_shortcode('helloworld', 'helloworld_shortcode');
// shortcode del plugin para usar en los post
function helloworld_shortcode($atts) {
    // el valor devuelto por return se inserta en el post en lugar
    // del shortcode. No se debe usar echo sino return
    return helloworld();
}
?>

… obteniendo:

<?php
// registrar la funcion que se ejecuta al activar el plugin
register_activation_hook(__FILE__, 'helloworld_activate');
// funcion que se ejecuta al activar el plugin
function helloworld_activate() {
    // crear la tabla del plugin e insertar dos registros
    global $wpdb;
    $table_name= $wpdb->prefix."helloworld";
 
       $sql = "CREATE TABLE $table_name (
        `id` mediumint( 9 ) NOT NULL auto_increment,
        `type` tinytext NOT NULL,
        `saludo` tinytext NOT NULL,
        PRIMARY KEY  (`id`)
        )";
    $wpdb->query($sql);
 
    $sql = "INSERT INTO $table_name (`id`, `type`, `saludo`)
        VALUES (1, 'default', 'Hello World')";
    $wpdb->query($sql);
 
    $sql = "INSERT INTO $table_name (`id`, `type`, `saludo`)
        VALUES (2, 'custom', 'Hola Mundo')";
    $wpdb->query($sql);
 
    // añadir la option del plugin
    add_option('helloworld_saludo_type', 'default');
}
 
// registrar la funcion que se ejecuta al desactivar el plugin
register_deactivation_hook(__FILE__, 'helloworld_deactivate');
// funcion que se ejecuta al desactivar el plugin
function helloworld_deactivate() {
    // borrar la tabla del plugin
    global $wpdb;
    $table_name = $wpdb->prefix."helloworld";
 
    $sql = "DROP TABLE $table_name";
    $wpdb->query($sql);
 
    // borrar la option del plugin
    delete_option('helloworld_saludo_type');
}
 
// crear un item en el panel de administracion
add_action('admin_menu', 'helloworld_menu');
// crear la pagina de opciones del plugin
function helloworld_menu() {
    add_options_page(__('Hello World plugin options', 'helloworld'),
        'Hello World', 8, basename(__FILE__), 'helloworld_options');
}
// funcion que muestra la pagina de opciones del plugin
function helloworld_options() {
    // comprobar si la peticion procede del form
    global $wpdb;
    $table_name = $wpdb->prefix."helloworld";
    if (isset($_POST['saludo_custom_new'])
        && !empty($_POST['saludo_custom_new'])) {
        $sql = "UPDATE $table_name
            SET saludo ='{$_POST['saludo_custom_new']}'
            WHERE type='custom'";
        $wpdb->query($sql);
    }
    if (isset($_POST['saludo_type'])) {
        update_option('helloworld_saludo_type', $_POST['saludo_type']);
    }
 
    // mostrar la pagina de opciones
    $saludo_default = $wpdb->get_var("SELECT saludo
        FROM $table_name
        WHERE type='default'" );
    $saludo_custom = $wpdb->get_var("SELECT saludo
        FROM $table_name
        WHERE type='custom'" );
    $saludo_type = get_option('helloworld_saludo_type');
    if ($saludo_type == "default") {
        $checked_default = "checked";
        $checked_custom = "";
    } else {
        $checked_default = "";
        $checked_custom = "checked";
    }
    echo "<div class='wrap'>n";
    echo "<h2>".__('Hello World plugin options', 'helloworld')."</h2>n";
    echo "<form method='post' action=''>n";
    echo __('Display', 'helloworld').":<br />n";
    echo "<input type='radio' name='saludo_type' value='default'
        ".$checked_default." /> ".__('Message default', 'helloworld')."
        (<b>".$saludo_default."</b>)<br />n";
    echo "<input type='radio' name='saludo_type' value='custom'
        ".$checked_custom." /> ".__('Message custom', 'helloworld')."
        (<b>".$saludo_custom."</b>)<br />n";
    echo __('New', 'helloworld')." ".__('Message custom', 'helloworld').":
        <input type='text' name='saludo_custom_new' /><br />n";
    echo "<input type='submit' name='update'
        value='".__('Update', 'helloworld')."' />n";
    echo "</form>n";
    echo "</div>n";
}
 
// funcion del plugin para usar en PHP, devuelve un string
function helloworld() {
    // recuperar el saludo
    global $wpdb;
    $table_name = $wpdb->prefix."helloworld";
    $saludo_type = get_option('helloworld_saludo_type');
    $saludo = $wpdb->get_var("SELECT saludo
        FROM $table_name
        WHERE type='$saludo_type'" );
    // output del plugin
    return "<p>".$saludo."</p>n";
}
 
// registrar la funcion que se ejecuta al llamar al shortcode
add_shortcode('helloworld', 'helloworld_shortcode');
// shortcode del plugin para usar en los post
function helloworld_shortcode($atts) {
    // el valor devuelto por return se inserta en el post en lugar
    // del shortcode. No se debe usar echo sino return
    return helloworld();
}
?>

Además, añadiremos en helloworld.php una sección en la que se carga el idioma i18n:

  • Cargar el idioma i18n
    <?php
    // ejecutar una funcion una vez que WordPress ha cargado
    add_action('init', 'helloworld_textdomain');
     
    // funcion para cargar el idioma i18n
    function helloworld_textdomain() {
        $dir = basename(dirname(__FILE__))."/lang";
        load_plugin_textdomain( 'helloworld', 'wp-content/plugins/'.$dir, $dir);
    }
    ?>

Una vez que hayamos marcado en nuestro código fuente con __() o _e() las cadenas traducibles utilizaremos el comando xgettext (una herramienta de la librería gettext) para extraer las cadenas originales y generar el archivo POT (PO Template, extensión .pot), la plantilla de traducción. Para generar el archivo POT (helloworld.pot) haremos:

$ xgettext --keyword=__ --keyword=_e --language=PHP --from-code=UTF-8
  --output=helloworld.pot helloworld.php

El contenido de helloworld.pot será:

msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSIONn"
"Report-Msgid-Bugs-To: n"
"POT-Creation-Date: 2009-09-01 20:05+0200n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONEn"
"Last-Translator: FULL NAME <email@ADDRESS>n"
"Language-Team: LANGUAGE <[email protected]>n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=CHARSETn"
"Content-Transfer-Encoding: 8bitn"
 
#: helloworld.php:74 helloworld.php:101
msgid "Hello World plugin options"
msgstr ""
 
#: helloworld.php:103
msgid "Display"
msgstr ""
 
#: helloworld.php:104
msgid "Message default"
msgstr ""
 
#: helloworld.php:105 helloworld.php:106
msgid "Message custom"
msgstr ""
 
#: helloworld.php:106
msgid "New"
msgstr ""
 
#: helloworld.php:107
msgid "Update"
msgstr ""

El charset lo tenemos que establecer manualmente. Para ello reemplazaremos la línea…

"Content-Type: text/plain; charset=CHARSETn"

… por:

"Content-Type: text/plain; charset=UTF-8n"

Cada traductor se encargará de editar la plantilla POT (helloworld.pot) y traducir las secciones msgstr a su idioma, obteniendo el archivo PO (Portable Object, extensión .po), en este caso traducido al español (helloworld-es_ES.po):

msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSIONn"
"Report-Msgid-Bugs-To: n"
"POT-Creation-Date: 2009-08-31 07:02+0200n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONEn"
"Last-Translator: FULL NAME <email@ADDRESS>n"
"Language-Team: LANGUAGE <[email protected]>n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=UTF-8n"
"Content-Transfer-Encoding: 8bitn"
 
#: helloworld.php:74 helloworld.php:101
msgid "Hello World plugin options"
msgstr "Opciones del plugin Hello World"
 
#: helloworld.php:103
msgid "Display"
msgstr "Mostrar"
 
#: helloworld.php:104
msgid "Message default"
msgstr "Saludo por defecto"
 
#: helloworld.php:105 helloworld.php:106
msgid "Message custom"
msgstr "Saludo personalizado"
 
#: helloworld.php:106
msgid "New"
msgstr "Nuevo"
 
#: helloworld.php:107
msgid "Update"
msgstr "Guardar"

Una vez que disponemos del archivo PO tenemos que generar el archivo MO (Machine Object, extensión .mo), la traducción en formato binario, un formato más adecuado para una rápida extracción de las cadenas traducidas. Para generar el archivo MO (helloworld-es_ES.mo) haremos:

$ msgfmt helloworld-es_ES.po -o helloworld-es_ES.mo

Para cargar la traducción incluiremos en nuestro código lo siguiente:

<?php
$dir = basename(dirname(__FILE__))."/lang";
load_plugin_textdomain( 'helloworld', 'wp-content/plugins/'.$dir, $dir);
?>

Ésta será la página de opciones del plugin en inglés (en_US)…

WordPress helloworld screenshot 1

… y ésta traducida al español (es_ES):

WordPress helloworld screenshot 2

Artículos en la categoría "Manual de WordPress"

  1. Manual de WordPress: Links
  2. Manual de WordPress: Fotos
  3. Manual de WordPress: Vídeos
  4. Manual de WordPress: Música
  5. Manual de WordPress: Crear un plugin
  6. Manual de WordPress: Internacionalizar un plugin
  7. Manual de WordPress: Crear un widget
  8. Manual de WordPress: Plugins imprescindibles
  9. Manual de WordPress: Plugin All in One SEO Pack
  10. Manual de WordPress: Plugin WP-Amazon
  11. Manual de WordPress: Plugin Simple Tags