PHP code scanner to use with gettext/gettext

Overview

PHP Scanner

Latest Version on Packagist Software License Build Status Quality Score Total Downloads

Created by Oscar Otero http://oscarotero.com [email protected] (MIT License)

PHP code scanner to use with gettext/gettext

Installation

composer require gettext/php-scanner

Usage example

use Gettext\Scanner\PhpScanner;
use Gettext\Generator\PoGenerator;
use Gettext\Translations;

//Create a new scanner, adding a translation for each domain we want to get:
$phpScanner = new PhpScanner(
    Translations::create('domain1'),
    Translations::create('domain2'),
    Translations::create('domain3')
);

//Set a default domain, so any translations with no domain specified, will be added to that domain
$phpScanner->setDefaultDomain('domain1');

//Extract all comments starting with 'i18n:' and 'Translators:'
$phpScanner->extractCommentsStartingWith('i18n:', 'Translators:');

//Scan files
foreach (glob('*.php') as $file) {
    $phpScanner->scanFile($file);
}

//Save the translations in .po files
$generator = new PoGenerator();

foreach ($phpScanner->getTranslations() as $domain => $translations) {
    $generator->generateFile($translations, "locales/{$domain}.po");
}

Please see CHANGELOG for more information about recent changes and CONTRIBUTING for contributing details.

The MIT License (MIT). Please see LICENSE for more information.

Comments
  • Comment extraction doesnt seem to work...?

    Comment extraction doesnt seem to work...?

    Is it just me or doesnt the comment extraction work with the new version? With the old version I think there was enableCommentsExtraction. With the new version there is no such method and the extraction also doesn't happen automatically it seems. I use this code for testing:

    $translations=Translations::create();
    $phpScanner=new PhpScanner($translations);
    $php=<<<PHP
    <?php
    //I love comment extraction
    echo gettext('hello world');
    PHP;
    $phpScanner->scanString($php,"hello.php");
    print_r($translations);
    exit;
    

    $translation->extractedComments seems to be empty.

    This feature was very useful for parsing the PHP compiled from Twig template files, because the compiled PHP code included the original line number in the Twig file so you get a kind of source-map feature where you can see where the real line of the respective translation was...

    opened by rgpublic 12
  • The php-format flag is missing

    The php-format flag is missing

    The scanner does not add the php-format flag for gettext() arguments that are a format string for sprintf() functions such as %s or %d. For example: sprintf(gettext("This is %s"), $value); does not return flag #, php-format

    opened by Goral64 5
  • Comment extraction not working in certain cases

    Comment extraction not working in certain cases

    Trying to leverage the comment extraction functionality of the PhpScanner class. I am having a hard time getting anything except in the simplest of cases.
    Working:

    //Translators: foo
    gettext('bar');
    //Translators: bar
    echo gettext('foo');
    

    Not Working:

    //Translators: foo
    $foo = gettext('foo');
    //Translators: bar
    $bar = sprintf(_('bar %s', 'foo'));
    
    opened by lbarbula 5
  • Parser Failing on Multi-Line Code

    Parser Failing on Multi-Line Code

    In the process of trying to upgrade from php-gettext version 4.x to 5.x in my code, and the following example code:

    <?php
    $var = __(
      'Test string. This is a very long string, so I want to wrap it across '
      . 'multiple lines.'
    );
    

    Yields the error:

    Invalid gettext function in (file). Some required arguments are not valid
    

    I believe this is because the parser isn't correctly handling the multiline string inside the function call.

    opened by BusterNeece 4
  • fatal error while scanning a php file

    fatal error while scanning a php file

    I'm getting the following error:

    PHP Fatal error:  Uncaught Error: Call to undefined method PhpParser\Node\Expr\Variable::getLast() in .../vendor/gettext/php-scanner/src/PhpNodeVisitor.php:31
    

    the line of code triggering the error is:

        $phpScanner->scanFile($file->getRelativePathname());
    

    the contents of the file which would still trigger the error

    <?php
    
    class AuthMiddleware
    {
        public function test()
        {
           return __('Accessing the Backoffice is not allowed at this time.');
        }
    }
    

    Versions:

    gettext/gettext                     v5.0.0             PHP gettext manager
    gettext/languages                   2.5.0              gettext languages with plural rules
    gettext/php-scanner                 v1.0.0             PHP scanner for gettext
    
    opened by mjrider 4
  • Please do not silently drop unknown argument types in PhpNodeVisitor

    Please do not silently drop unknown argument types in PhpNodeVisitor

    Currently there is: default: $function->addArgument(); So, if the argument is not Scalar_String, Scalar_LNumber or Scalar_DNumber then the argument is silently discarded. It would be very helpful if the class could at least call an empty protected method so that a child class can then decide what happens with that argument without completely overriding createFunction(). Drupal has the following syntax to supply context info: t("Translatable string","",["context"=>"Context string"]); Unfortunately the array type in the 3rd argument is discarded and there's no easy way to get to it even in a child class.

    opened by rgpublic 3
  • Exception

    Exception "Some required arguments are not valid" thrown when output of a function is translated

    adding to tests/assets/code.php will trigger this case:

    __(ucfirst('test'));
    

    While it seems logical that the scanner can't index this line, a warning/notice is a lot better. Because this exception is not catched internally, it's impossible to ignore it and continue the rest of the file, we add the translations like this manually to the translation file. This works in the previous version of php-gettext

    opened by mjrider 3
  • Scanner not adding language and utf-8 encoding headers to .po file

    Scanner not adding language and utf-8 encoding headers to .po file

    Hello

    I have the following po file contents, resulting from a scan for php files:

    msgid ""
    msgstr ""
    "X-Domain: messages\n"
    
    #: /var/www/html/the_site/_teste.php:41
    msgid "dah"
    msgstr ""
    

    I have the following code to scan for files:

    /*considering the following folder structure:
    vendor
        /my_plugins
            /module1
            /module2
    */
    $LOCALES = ["en" => "en_GB","pt" => "pt_PT"];
    
    $folders= new DirectoryIterator("vendor/my_plugins");
    
    foreach($folders as $folder) {
    
        $path = $folder->getFilename();
        
        $DOMAIN = "module1"; //in my actual code, domain takes several different names depending on the folder the iterator is working on
        
        $destination_folder = $folder->getPathname()."/locale/"; //will save in vendor/my_plugins/module1/locale
        
        foreach($LOCALES as $code => $locale) {
        
                if (!file_exists($destination_folder) || !file_exists($destination_folder.$locale)) {
                        //folder creation
                        mkdir($destination_folder.$locale,0777,true);
                        
                }
        }
        
         foreach(LOCALES as $codigo => $locale) {
         
             $phpScanner = new PhpScanner(
                 Translations::create($DOMAIN)
              );
              $phpScanner->setDefaultDomain($DOMAIN);
              //resulting PO file matches $DOMAIN
              
              $phpScanner->scanFile("some_file.php");  //this also works
              
              //done scanning, let's go to generate files
              $FILE = $destination_folder.$locale."/".$DOMAIN.".po";
              
              $po_generator = new PoGenerator();
              $mo_generator = new MoGenerator();
              
              foreach ($phpScanner->getTranslations() as $domain => $translations) {
                      //line below raises: Fatal error: Uncaught Error: Call to undefined method Gettext\Translations::setHeader() in
                      $translations->setHeader("Content-Type", "text/plain; charset=UTF-8");
    
                      //seems to work, but po file does not seem to have the "language" header
                      $translations->setLanguage($locale); //should be pt_PT or pt_PT.utf8 ( the latter is installed in my system )
    
                      $po_generator->generateFile($translations, $FILE);
              }
         }
         
    
    

    What is the proper way to set headers in the file, using PHP-Scanner? Should I load it again with Loader and the set the headers it, and finally generate the mo file?

    opened by ideiasfrescas 2
  • Add option to extract messages from static method calls

    Add option to extract messages from static method calls

    I'm not sure, maybe this issue should be submitted to nikic/php-parser repo instead. I use own Translator helper class with static methods and I cannot extract messages from it method invocations.

    Translator helper class:

    use Gettext\Loader\PoLoader;
    use Gettext\Translation;
    
    final class Translator
    {
        /** @var Gettext\Loader\LoaderInterface|null */
        protected static $loader;
    
        /** @var Gettext\Translations|null */
        protected static $translations;
    
        /**
         * Loads translations from PO file with php/gettext package.
         * @ref https://github.com/php-gettext/Gettext
         *
         * @param string $filePath Path to PO file
         */
        public static function loadPo(string $filePath)
        {
            if (!static::$loader) {
                static::$loader = new PoLoader();
            }
            static::$translations = static::$loader->loadFile($filePath);
        }
    
        /**
         * Translates message.
         *
         * @param string $msg Original message
         *
         * @return string Localized message or original if doesn't exist in PO file
         */
        public static function translate(string $msg): string
        {
            $t = static::$translations->find(null, $msg);
            if (
                $t instanceof Translation
                && $t->isTranslated()
            ) {
                return $t->getTranslation();
            }
    
            return $msg;
        }
    }
    

    scanner configuration:

    //Create a new scanner, adding a translation for each domain we want to get:
    $phpScanner = new PhpScanner(
        Translations::create('domain')
    );
    
    $phpScanner->setFunctions(
        array_merge(
            $phpScanner->getFunctions(),
            // none of following works
            ['Translator::translate' => 'gettext'],
            ['::translate' => 'gettext'],
            ['translate' => 'gettext']
        )
    );
    

    scanned file example:

    Translator::loadPo('../locale/en/LC_MESSAGES/domain.po');
    // i18n: 'Hello World' should be extracted
    $msg = Translator::translate('Hello World');
    echo $msg;
    
    // po file saving omitted
    
    opened by ybelenko 2
  • Find __('text') occurrences

    Find __('text') occurrences

    Hi, im using gettext/gettext with this php-scanner but when use the scanner: $scanner->scanFile($file); $translations = $scanner->getTranslations(); but never find translations, the $file have __('text') inside. I have initialized the Scanner like: $scanner = new PhpScanner(); $scanner->setDefaultDomain('domain1'); Any suggestions? Thanks in advance

    opened by lavitzz 1
Owner
Gettext
PHP implementation of gettext
Gettext
A full-scale PHP sandbox class that utilizes PHP-Parser to prevent sandboxed code from running unsafe code

A full-scale PHP 7.4+ sandbox class that utilizes PHP-Parser to prevent sandboxed code from running unsafe code. It also utilizes FunctionParser to di

Corveda 192 Dec 10, 2022
A full-scale PHP 5.3.2+ sandbox class that utilizes PHPParser to prevent sandboxed code from running unsafe code.

##DEPRECATED: The PHPSandbox project has transfered to Corveda/PHPSandbox and will be actively maintained there. This branch is no longer being active

Elijah Horton 219 Sep 2, 2022
Library for counting the lines of code in PHP source code

sebastian/lines-of-code Library for counting the lines of code in PHP source code. Installation You can add this library as a local, per-project depen

Sebastian Bergmann 715 Jan 5, 2023
Provides functionality that helps writing PHP code that has runtime-specific (PHP / HHVM) execution paths

sebastian/environment This component provides functionality that helps writing PHP code that has runtime-specific (PHP / HHVM) execution paths. Instal

Sebastian Bergmann 6.5k Jan 3, 2023
Search PHP source code for function & method calls, variables, and more from PHP.

Searching PHP source code made easy Search PHP source code for function & method calls, variable assignments, classes and more directly from PHP. Inst

Permafrost Software 22 Nov 24, 2022
PHP Architecture Tester - Easy to use architectural testing tool for PHP :heavy_check_mark:

Easy to use architecture testing tool for PHP Introduction ?? PHP Architecture Tester is a static analysis tool to verify architectural requirements.

Carlos A Sastre 765 Dec 30, 2022
PHP Static Analysis Tool - discover bugs in your code without running it!

PHPStan - PHP Static Analysis Tool PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even b

PHPStan 11.6k Dec 30, 2022
A PHP code-quality tool

GrumPHP Sick and tired of defending code quality over and over again? GrumPHP will do it for you! This composer plugin will register some git hooks in

PHPro 3.9k Jan 1, 2023
Copy/Paste Detector (CPD) for PHP code.

PHP Copy/Paste Detector (PHPCPD) phpcpd is a Copy/Paste Detector (CPD) for PHP code. Installation This tool is distributed as a PHP Archive (PHAR): $

Sebastian Bergmann 2.2k Jan 1, 2023
Analyze PHP code with one command

PHPQA Analyze PHP code with one command. Requirements PHP >= 5.4.0 xsl extension for HTML reports Why? Every analyzer has different arguments and opti

edgedesign/phpqa 542 Dec 24, 2022
Performs advanced static analysis on PHP code

PHP Analyzer Please report bugs or feature requests via our website support system ? in bottom right or by emailing [email protected]. Contri

Continuous Inspection 443 Sep 23, 2022
A static php code analysis tool using the Graph Theory

Mondrian Ok guyz, you have a master degree in Graph Theory, you follow Law of Demeter and you live on S.O.L.I.D principles ? Let's have some Fun ! (^ω

Florent Genette 391 Nov 30, 2022
Instant Upgrades and Instant Refactoring of any PHP 5.3+ code

Rector - Speedup Your PHP Development Rector helps you with 2 areas - major code changes and in daily work. Do you have a legacy code base? Do you wan

RectorPHP 6.5k Jan 8, 2023
Deptrac is a static code analysis tool for PHP that helps you communicate, visualize and enforce architectural decisions in your projects

Deptrac is a static code analysis tool for PHP that helps you communicate, visualize and enforce architectural decisions in your projects. You can freely define your architectural layers over classes and which rules should apply to them.

QOSSMIC GmbH 2.2k Dec 30, 2022
phpcs-security-audit is a set of PHP_CodeSniffer rules that finds vulnerabilities and weaknesses related to security in PHP code

phpcs-security-audit v3 About phpcs-security-audit is a set of PHP_CodeSniffer rules that finds vulnerabilities and weaknesses related to security in

Floe design + technologies 655 Jan 3, 2023
A tool to automatically fix PHP Coding Standards issues by Dragon Code.

A tool to automatically fix PHP Coding Standards issues by Dragon Code.

The Dragon Code 24 Aug 27, 2022
PHP Functional Programming library. Monads and common use functions.

Functional PHP PHP Functional Programming library. Monads and common use functions. Documentation Functions Monads Installation Composer $ composer re

Alexander Sv. 169 Dec 27, 2022
Code Climate CLI

Code Climate CLI Overview codeclimate is a command line interface for the Code Climate analysis platform. It allows you to run Code Climate engines on

Code Climate 2.4k Dec 26, 2022
Static code analysis to find violations in a dependency graph

PhpDependencyAnalysis PhpDependencyAnalysis is an extendable static code analysis for object-oriented PHP-Projects to generate dependency graphs from

Marco Muths 546 Dec 7, 2022