Hi,
I wanted to share a Perl script my friend Casey wrote for us to find
untranslated strings in our PHP controllers and PHTML view scripts. We use
Zend_Translate with the gettext adapter and this script has been an
incredible time saver. Usage should be obvious. Put strings such as id
strings or class names into skip_strings.txt.

Best,
Peter

#!/usr/bin/perl

# find_untranslated_strings.pl
#
#################################################################
#                         Revision History                      
#
# 2009/03/11 - Casey - Created script
#
#################################################################

#################################################################
#                       Information for users
# Debug?
   my $DEBUG = 0;
# Verbose?
   my $VERBOSE = 0;
# File extensions
   my @fileExtensions = (".php", ".phtml");
# Base directory to start from "." is the current directory
   my $startDirectory = "./../application";
# Recurse subdirectories
   my $recurseSubdirectories = 1;
# Skip these
   # Strings
   my @skipStrings=();
   # Prefixes
   my @skipPrefixes=("this->translate(", "this->view->translate(");
   # Optionally include files containing strings and prefixes
   # to skip, one per line
   my $skipStringsFile = "skip_strings.txt";
   my $skipPrefixesFile = "skip_prefixes.txt";
#
#################################################################

#################################################################
# Supporting Functions
# Get files recursively
# Note $fileExt is a regex
sub getFilesFromDirectory {
   my ($fileExt, $startDir, $recurse)=...@_;

   my (@returnFiles,@dirList,@allFiles)=();

   print STDERR "Scanning directory: $startDir\n";

   opendir DIRINPUT, $startDir;

   @allFiles=sort readdir DIRINPUT;

   closedir DIRINPUT;

   foreach my $file (@allFiles) {
      my $actualFile="$startDir/$file";
      next if($file=~/^\.$/ || $file=~/^\.\.$/);
      print STDERR "Found file: $file\n" if(-f $actualFile && $DEBUG);
      print STDERR "Found directory: $file\n" if(-d $actualFile && $DEBUG);
      push @returnFiles, $actualFile if(-f $actualFile &&
$actualFile=~/\w+$fileExt/);
      push @dirList, $actualFile if(-d $actualFile);
   }

   if($recurse) {
      foreach my $dir (@dirList) {
         push @returnFiles, getFilesFromDirectory($fileExt, $dir, $recurse);
      }
   }
   return @returnFiles;
}

# Function to load the contents of a file into a string
sub loadFileContents {
   my ($filename, $dontDie) = @_;
   my $totalFile = "";

   if(!open INPUT, $filename) {
      return undef if($dontDie);
      die("Unable to open file $filename\n");
   }

   # Slurp the entire file into memory
   print STDERR "   loading file $filename...\n" if($DEBUG);
   {
      local $/ = undef;
      $totalFile=<INPUT>;
   }

   # Close the file
   close INPUT;

   return $totalFile;
}
#################################################################

if(-f $skipStringsFile) {
   open INPUT, $skipStringsFile;
   while(my $string=<INPUT>) {
      chomp($string);
      push @skipStrings, $string;
   }
   close INPUT;
}

if(-f $skipPrefixesFile) {
   open INPUT, $skipPrefixesFile;
   while(my $prefix=<INPUT>) {
      chomp($prefix);
      push @skipPrefixes, $prefix;
   }
   close INPUT;
}

# Change arrays to hashes for efficiency
my %skipStrings;
my %skipPrefixes;
foreach my $string (@skipStrings) {
   $skipStrings{$string}=1;
}
foreach my $prefix (@skipPrefixes) {
   $skipPrefixes{$prefix}=1;
}

my @fileList;
foreach $ext (@fileExtensions) {
   push @fileList, getFilesFromDirectory($ext, $startDirectory,
$recurseSubdirectories);
}

# Cycle through the files
foreach my $filename (@fileList) {
   print STDERR "parsing: $filename\n" if($VERBOSE);
   
   my $totalFile = loadFileContents($filename);

   # Pull out PHP segments from file
   while($totalFile=~/<\?(.*?)\?>/s) {
      $phpSegment=$1;
      $totalFile=~s/\Q$phpSegment\E//;

      # Parse the PHP for strings line by line
      @lines=split("\n", $phpSegment);
      foreach my $line (@lines) {
         while($line=~/('[^']+')/ || $line=~/("[^"]+")/) {
            $string=$1;
            $exactString=$string;
            $string=~s/^['"]//;
            $string=~s/['"]$//;
            print STDERR "DEBUG: exactString: $exactString\n" if($DEBUG);
            if($skipStrings{$string}) {
               print STDERR "DEBUG: skipping string: $exactString\n"
if($DEBUG);
               $line=~s/\Q$exactString\E//;
               next;
            }
            $line=~/\b(.*?[(])*\Q$exactString\E/;
            $prefix=$1;
            print STDERR "DEBUG: prefix: $prefix\n" if($DEBUG && $prefix);
            if($prefix && $skipPrefixes{$prefix}) {
               print STDERR "DEBUG: skipping prefix: $prefix\n" if($DEBUG);
               $line=~s/\Q$exactString\E//;
               next;
            }
            print STDOUT "$string\n";
            $line=~s/\Q$exactString\E//;
         }
      }
   }
}

# vim: sw=3 ts=3 expandtab

-- 
View this message in context: 
http://www.nabble.com/Finding-untranslated-strings-tp22541448p22541448.html
Sent from the Zend Framework mailing list archive at Nabble.com.

Reply via email to