In Linux we trust!

Работа с картой переводов (PHP)

Расскажу, как организовать карту переводов для сайта и быстро ее наполнить первичными данными.

Итак, первым делом создайте карту переводов (lang.php):

<?php

return [

    'en-home-title' => 'My Homepage Title / My Blog',
    'ru-home-title' => 'Залоголок главной страницы / Мой блог',
    'de-home-title' => 'Meine Homepage Titel / Mein Blog',

    // -- AUTO -- //
];

Вывод любой константы из карты переводов осуществляется через такую функцию:

define('LANG', 'en');
define('LANG_FILE', __DIR__ . '/lang.php');

/*
 * @param string $var
 * @param string $lang (optional)
 *
 * @return string
 */
function _T(string $var, string $lang = ''): string
{
    $lang = $lang ?: LANG;
    static $map = [];
    if (!$map) {
        $map = require LANG_FILE;
    }
    $key = "{$lang}-{$var}";
    return $map[$key] ?? '';
}

В шаблоне все лингвистические строки предстоит заменить на вызовы этой функции, соответственно, с выносом константы в карту переводов. Примерно, так:

Карта переводов

1) Автоматизация заполнения карты переводов:

Будем автоматизировать вышеобозначенный процесс в редакторе Sublime 3. Открыв редактор, нажимаем Tools → Developer → New Plugin. в открывщемся окне набиваем скриптинг новой команды my_translate:

import sublime, sublime_plugin, os

class MyTranslateCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        v = self.view
        var = v.substr(v.sel()[0])
        result = os.popen("php mytranslate.php '" + var + "'").read()
        v.replace(edit, v.sel()[0], "<?=_T('" + result + "')?>")
        sublime.status_message("Done: " + result)

Внутри команды вызывается внешний PHP-скрипт (mytranslate.php), который и заносит переданную ему строку в карту переводов.

<?php

@ $word = $_SERVER['argv'][1];
if (!$word) {
    exit();
}
$_word = $word;
$_word = strip_tags($_word);
$_word = str_replace(['&amp;', '&lt;', '&gt;'], ' ', $_word);
$_word = preg_replace('~[^\w+0-9_]+~', '-', strtolower($_word));
$_word = trim($_word, '-');
// список языков
$langs = ['en', 'ru', 'de'];
// файл с картой переводов
$file = 'lang.php';
// маркер после которого добавлять
$marker = '// -- AUTO -- //';
// префикс всех добавляемых констант
$prefix = '';
$_word = $prefix . $_word;
$echo = "\n";
$content = file_get_contents($file);
$variants = range(0, 100);
foreach ($langs as $lang) {
    $one = "'{$lang}-{$_word}%s'";
    $two = "'{$word}'";
    foreach ($variants as $v) {
        $vv = sprintf($one, $v ? "-{$v}" : '');
        if (strpos($content, $vv) === false) {
            $echo .= "\n    {$vv} => {$two},";
            break;
        }
        if (strpos($content, "{$vv} => {$two}") !== false) {
            break;
        }
    }
}
$_word .= $v ? "-{$v}" : '';
$pos = strpos(file_get_contents($file), $marker);
if ($pos === false) {
    exit();
}
$head = substr($content, 0, $pos + strlen($marker));
$tail = substr($content, $pos + strlen($marker));
file_put_contents($file, $head . $echo . $tail);
echo $_word;

После того как убедитесь, что все скрипты рабочие, не забудьте повесить команду на какую-либо комбинацию клавиш (Preferences → Key Bindings - User):

[
    {
        "keys": ["ctrl+shift+t"],
        "command": "my_translate"
    }
]

2) Автоматизация переводов:

Исходим из того, что те константы, что подлежат переводы имеют пустое значение. Непосредственно перевод осуществляется через CLI-утилиту:

$ wget git.io/trans
$ chmod +x ./trans
$ mv ./trans /usr/local/bin

Вспомогательный скрипт, который вычисляет "что нужно перевести" и "откуда":

<?php

// список языков
$langs = ['en', 'ru', 'de'];
// файл с картой переводов
$file = 'lang.php';
$all = require $file;
foreach ($all as $k => $v) {
    // переводить только константы с пустым значением
    if ($v !== "") {
        continue;
    }
    $k = explode('-', $k);
    $l = array_shift($k);
    foreach ($langs as $lang) {
        if ($lang == $l) {
            continue;
        }
        if (isset($all[$_ = $lang . '-' . implode('-', $k)])) {
            $result = trim(shell_exec(sprintf(
                "trans -brief {$lang}:{$l} %s",
                escapeshellarg($all[$_])
            )));
            $reg = '~(\'' . $l . '-' . implode('-', $k) . '\'\s*=>\s*\')(\')~';
            file_put_contents(
                $file,
                preg_replace($reg, "$1{$result}$2", file_get_contents($file))
            );
            // задержка небольшая
            sleep(3);
        }
    }
}

На этом все! Желаю успехов!