Localization of a custom website using WordPress

Localization of a custom website using WordPress

One of the latest projects I worked on for about a month was developing a social network. The site itself isn't very complex. But there was (and still is) one thing that bothers me — language support. In WordPress, this issue has long been well developed. And if you’re comfortable with using a computer and writing/editing text, translating a theme or plugin is not a big deal. But for a custom CMS, which I use in almost all of my projects, this becomes a problem — especially if language support wasn’t properly thought out from the start.

Naively, I decided to use the localization functionality provided by the Kohana framework (which my engine is based on). By default, phrases and translated words are stored in a standard PHP file as an array. Here’s an example of pagination translation:

return array(
    'First'     => 'First',
    'Last'      => 'Last',
    'Previous'  => '<',
    'Next'      => '>',
);

The main advantage of this method is performance. Any others? Seems like that’s it. But in high-load projects, it matters! Of course, this method only works well if you don’t plan to expand the site in the future. Or if there’s a tool (or one is developed) to extract `__()` strings into such an array — this approach could work too (I read about this idea on Habr).

But once I imagined how many edits would be required during refinements — and how much time I’d spend on these languages (there are five at the moment!) — I immediately decided to abandon this method.

After some thinking, I came to two conclusions:

  1. You can use the PHP extension "gettext".
  2. You can borrow the approach from existing CMSs (WP, Drupal, Joomla).

Started with the first one. Honestly — it wasn’t easy. Locale settings, strange file paths, encoding issues... nothing worked. Plus, the client’s server didn’t even have the gettext extension installed. So I had to drop that idea.
Still, I’ll need to learn gettext properly later.

Option two. Fortunately, I had some experience with WP. So I decided to dig deeper into it.
After analyzing how `load_theme_textdomain()` and `__()` work, I built a simple language-handling class. It was successfully integrated (but not yet fully tested).

How to Connect WordPress POMO to Your Custom Engine

From WordPress, we’ll need 5 files from `/wp-includes/pomo/`:
`entry.php`, `mo.php`, `po.php`, `streams.php`, `translations.php`.
Maybe not all of them are necessary, but since I didn’t study the class logic — I just took everything to be safe.

Below is a class that performs the same tasks as `load_theme_textdomain()` and `__()` in WP:

<?php 
class Lng
{
    private static $_lang_ar = array();

    public static function _($s, $l = 'default', $a = NULL)
    {
        $l = Lng::l().'-'.$l.'.mo';

        if (!isset(Lng::$_lang_ar[$l]))
        {
            Lng::$_lang_ar[$l] = new NOOP_Translations;
        }

        $s = Lng::$_lang_ar[$l]->translate($s);

        return empty($a) ? $s : strtr($s, $a);
    }

    public static function load($l, $p)
    {
        $l = Lng::l().'-'.$l.'.mo';

        if (!class_exists('MO', FALSE))
        {
            throw new Exception('The "MO" library does not included');
        }

        try {
            $MO = new MO();
            if (!$MO->import_from_file($p.$l)) {
                return FALSE;
            }

            if (isset(Lng::$_lang_ar[$l])) {
                $MO->merge_with(Lng::$_lang_ar[$l]);
            }

            Lng::$_lang_ar[$l] = &$MO;
        }
        catch (Exception $e)
        {
            throw new Exception('The language file "'.$l.'" does not exist');
        }

        return TRUE;
    }

    public static function l()
    {
        return 'ru';
    }
}

And here’s a usage example:

<?php
header('Content-Type: text/html; charset=utf-8');

try {
    require_once('vendor/pomo/mo.php');
    require_once('library/lng.php');

    Lng::load('first','languages/');
    Lng::load('second','languages/');
}
catch(Exception $e) {
    echo $e->getMessage();
}

$name_first = 'Andriy';
$name_second = 'Alexei';
?>

<p><?php echo Lng::_('Hello {name}, how are you?','first',array('{name}' => $name_first))?></p>
<p><?php echo Lng::_('I am fine, thx {name}. And you?','second',array('{name}' => $name_second))?></p>

I don't think this code needs much explanation — the comments speak for themselves. Just keep in mind that your language files should be located in the `languages` folder and named `first` and `second`.

Expected output:

Hello Andriy, how are you?
I am fine, thx Alexei. And you?

Good luck with your translations!

Posts on similar topics

Are you having problems with your WordPress site? Do you need additional functionality? A custom plugin or a new page?
Then write to me via the feedback form, and I will try to help you.

Write a comment

Your email address will not be published. Required fields are marked *