Bir PHP kod tabanı tüm dizeyi bulma

3 Cevap php

Birkaç milyon satırı PHP kod tabanı ekran ve mantık without true ayrılık var ve lokalizasyon amacıyla kod temsil dizeleri ayıklamak çalışıyorum. Ekran ve mantık ayrılık uzun vadeli bir hedeftir, ama şimdi ben sadece lokalize etmek mümkün olmak istiyorum.

Kodda, dizeleri PHP için mümkün olan her formatta temsil yüzden bizim tüm kaynak ayrıştırmak için bir teorik (ya da pratik) yol gerekir ve en azından burada her dize hayatını BULUN edilir. İdeal olarak, tabii ki, örneğin, bir işlev çağrısı ile her dizesini değiştirmek istiyorum

"this is a string"

ile değiştirilmesi gerekmektedir

_("this is a string")

Tabii ki tek hem de çift quote format desteklemek gerekiyordu. Ben çok endişe değilim diğerleri onlar kadar seyrek ben bunları el ile değiştirebilirsiniz görünür.

Ayrıca, tabii indekslediği lokalize etmek istemem. Gibi pek dizeleri

$arr["value"]

haline gelmemelidir

$arr[_("value")]

Herkes bana bu başlamanıza yardımcı olabilir?

3 Cevap

You could use token_get_all() to get all the tokens from a PHP file e.g.

<?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
    }
}

Bunu gibi bir şey ile bir dizi endeks olarak kullanılan olmadığını gerçekten kirli bir kontrol yapabilirdi:

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

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

Birisi size, örneğin bekliyor olabilir bir şey yazdım olabilir çünkü ama gerçekten düzgün bir şekilde bunu yapmak için mücadele edecek:

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


Edit As Ant P says, you would probably be better off looking for [ and ] in the surrounding tokens for the second part of this answer rather than my strpos hack, something like this:

$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
}

Eğer tamamen otomatik arama yaparak kırmak ve ilişkisel diziler yanında yerini alacak kod tabanı bulunması muhtemel diğer bazı durumlar vardır.

SQL sorguları:

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

Dolaylı değişken referans.

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

SQL dizesi manipülasyon.

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

Tüm olasılıklar için filtre otomatik bir yolu yoktur. Belki de çözüm, her biri vurgulanır ve birkaç satır kod bağlamında olası dizeleri ve görüntüler bir "ılımlılık" kuyruk oluşturan bir uygulama yazmak olacaktır. Daha sonra kodu bakış bu yerelleştirme ya da değil ihtiyacı bir dize olup olmadığını belirlemek ve dize lokalize veya görmezden tek bir tuşa vurmak olabilir.

Bunun yerine perl veya grep kullanarak bir aşırı-akıllı komut satırı ile kesmek bu çözmeye çalışırken, bunu yapmak için bir program yazmak gerekir :)

Tek veya çift tırnak bir çift için her dosya üzerinden aramak için bir perl / python / yakut / ne olursa olsun senaryo yazın. Her zaman bir eşleşme bulur, size çizgi fonksiyonu ile değiştirmek ister gerekir, ve bunu yapmak için söyleyebilir ya da diğerine atlamak için.

Mükemmel bir dünyada, sizin için her şeyi bir şey yazmak istiyorum, ama bu muhtemelen sonunda daha az zaman alacak ve daha az hata ile karşı karşıya olurduk.

Sözde:

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

Ben bunu bir daha * nix-fu yolu vardır eminim, ancak bu yöntem her aşamada kendinizi bakalım ve karar verecek. bir milyon satır var ve her biri bir dize içerir ve her biri değerlendirmek size 1 saniye sürerse, o Belki :) bu yazıyı görmezden gerekir ... her şeyi yapmak için yaklaşık 270-imsi saatler alacak