Поиск всей строки в базе кода PHP - PullRequest
4 голосов
/ 21 февраля 2009

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

В коде строки представлены в каждом возможном формате для PHP, поэтому мне нужен теоретический (или практический) способ для анализа всего нашего источника и, по крайней мере, LOCATE, где живет каждая строка. В идеале, конечно, я бы заменил каждую строку вызовом функции, например

"this is a string"

будет заменено на

_("this is a string")

Конечно, мне нужно поддерживать одинарный и двойной формат цитаты . Остальные, которые меня не особо беспокоят, появляются так редко, что я могу их поменять вручную.

Кроме того, я бы, конечно, не хотел бы локализовать индексы массива. Так что строки вроде

$arr["value"]

не должно становиться

$arr[_("value")]

Может кто-нибудь помочь мне начать в этом?

Ответы [ 3 ]

11 голосов
/ 21 февраля 2009

Вы можете использовать token_get_all(), чтобы получить все токены из файла PHP например,

<?php

$fileStr = file_get_contents('file.php');

foreach (token_get_all($fileStr) as $token) {
    if ($token[0] == T_CONSTANT_ENCAPSED_STRING) {
        echo "found string {$token[1]}\r\n";
        //$token[2] is line number of the string
    }
}

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

$fileLines = file('file.php');

//inside the loop and if
$line = $fileLines[$token[2] - 1];
if (false === strpos($line, "[{$token[1]}]")) {
    //not an array index
}

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

$str = 'string that is not immediately an array index';
doSomething($array[$str]);

Редактировать Как говорит Ant P, вам, вероятно, было бы лучше искать [ и ] в окружающих токенах для второй части этого ответа, а не моего strpos хака, что-то вроде этого:

$i = 0;
$tokens = token_get_all(file_get_contents('file.php'));
$num = count($tokens);
for ($i = 0; $i < $num; $i++) {
    $token = $tokens[$i];

    if ($token[0] != T_CONSTANT_ENCAPSED_STRING) {
        //not a string, ignore
        continue;
    }

    if ($tokens[$i - 1] == '[' && $tokens[$i + 1] == ']') {
        //immediately used as an array index, ignore
        continue; 
    }

    echo "found string {$token[1]}\r\n";
    //$token[2] is line number of the string
}
5 голосов
/ 21 февраля 2009

Существуют и другие ситуации, которые могут существовать в базе кода, которые вы полностью прекратите, выполнив автоматический поиск и замену в дополнение к ассоциативным массивам.

SQL-запросы:

$myname = "steve";
$sql = "SELECT foo FROM bar WHERE name = " . $myname;

Ссылка на косвенную переменную.

$bar = "Hello, World"; // a string that needs localization
$foo = "bar"; // a string that should not be localized
echo($$foo);

Работа со строками SQL.

$sql = "SELECT CONCAT('Greetings, ', firstname) as greeting from users where id = ?";

Не существует автоматического способа фильтрации всех возможностей. Возможно, решением было бы написать приложение, которое создает «модерируемую» очередь возможных строк и отображает каждую выделенную строку в контексте нескольких строк кода. Затем вы можете взглянуть на код, чтобы определить, нужна ли ему локализация строки, и нажать один ключ, чтобы локализовать или проигнорировать строку.

0 голосов
/ 21 февраля 2009

Вместо того, чтобы пытаться решить эту проблему с помощью хитроумного хакера командной строки, использующего perl или grep, вы должны написать программу для этого:)

Напишите perl / python / ruby ​​/ любой другой скрипт для поиска в каждом файле пары одинарных или двойных кавычек. Каждый раз, когда он находит совпадение, он должен предлагать вам заменить его на функцию подчеркивания, и вы можете либо сказать ему сделать это, либо перейти к следующему.

В идеальном мире вы бы написали что-то, что сделало бы все для вас, но в конечном итоге это заняло бы меньше времени, и вы столкнулись бы с меньшим количеством ошибок.

Псевдо:

for fname in yourBigFileList:
    create file handle for actual source file
    create temp file handle (like fname +".tmp" or something)
    for fline in fname:
        get quoted strings
        for qstring in quoted_strings:
            show it in context, i.e. the entire line of code.
            replace with _()?
                if Y, replace and write line to tmp file
                if N, just write that line to the tmp file
    close file handles
    rename it to current name + ".old"
    rename ".tmp" file to name of orignal file

Я уверен, что есть более * nix-fu способ сделать это, но этот метод позволит вам посмотреть на каждый экземпляр самостоятельно и принять решение. если это миллион строк и каждая из них содержит строку и каждая из них занимает у вас 1 секунду для оценки, тогда вам понадобится около 270 часов, чтобы сделать все это ... Возможно, вам следует игнорировать этот пост:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...