1. sfI18nFindTask.class.php
  2. /** * Finds non "i18n ready" strings in an application. * * @package symfony * @subpackage task * @author Fabien Potencier * @version SVN: $Id: sfI18nFindTask.class.php 8453 2008-04-14 16:39:14Z fabien $ */
  3. class sfI18nFindTask extends sfBaseTask
  4. {
  5. /**
  6. * @see sfTask
  7. */
  8. protected function configure()
  9. {
  10. $this->addArguments(array(
  11. new sfCommandArgument('application', sfCommandArgument::REQUIRED, 'The application name'),
  12. ));
  13. $this->addOptions(array(
  14. new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
  15. ));
  16. $this->namespace = 'i18n';
  17. $this->name = 'find';
  18. $this->briefDescription = 'Finds non "i18n ready" strings in an application';
  19. $this->detailedDescription = <<<EOF
  20. The [i18n:find|INFO] task finds non internationalized strings embedded in templates:
  21. [./symfony i18n:find frontend|INFO]
  22. This task is able to find non internationalized strings in pure HTML and in PHP code:
  23. <p>Non i18n text</p>
  24. <p><?php echo 'Test' ?></p>
  25. As the task returns all strings embedded in PHP, you can have some false positive (especially
  26. if you use the string syntax for helper arguments).
  27. EOF;
  28. }
  29. /**
  30. * @see sfTask
  31. */
  32. public function execute($arguments = array(), $options = array())
  33. {
  34. $this->logSection('i18n', sprintf('find non "i18n ready" strings in the "%s" application', $arguments['application']));
  35. // Look in templates
  36. $dirs = array();
  37. $moduleNames = sfFinder::type('dir')->maxdepth(0)->relative()->in(sfConfig::get('sf_app_module_dir'));
  38. foreach ($moduleNames as $moduleName)
  39. {
  40. $dirs[] = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/templates';
  41. }
  42. $dirs[] = sfConfig::get('sf_app_dir').'/templates';
  43. $strings = array();
  44. foreach ($dirs as $dir)
  45. {
  46. $templates = sfFinder::type('file')->name('*.php')->in($dir);
  47. foreach ($templates as $template)
  48. {
  49. if (!isset($strings[$template]))
  50. {
  51. $strings[$template] = array();
  52. }
  53. $dom = new DomDocument('1.0', sfConfig::get('sf_charset', 'UTF-8'));
  54. $content = file_get_contents($template);
  55. // remove doctype
  56. $content = preg_replace('/<!DOCTYPE.*?>/', '', $content);
  57. @$dom->loadXML('<doc>'.$content.'</doc>');
  58. $nodes = array($dom);
  59. while ($nodes)
  60. {
  61. $node = array_shift($nodes);
  62. if (XML_TEXT_NODE === $node->nodeType)
  63. {
  64. if (!$node->isWhitespaceInElementContent())
  65. {
  66. $strings[$template][] = $node->nodeValue;
  67. }
  68. }
  69. else if ($node->childNodes)
  70. {
  71. for ($i = 0, $max = $node->childNodes->length; $i < $max; $i++)
  72. {
  73. $nodes[] = $node->childNodes->item($i);
  74. }
  75. }
  76. else if ('DOMProcessingInstruction' == get_class($node) && 'php' == $node->target)
  77. {
  78. // processing instruction node
  79. $tokens = token_get_all('<?php '.$node->nodeValue);
  80. foreach ($tokens as $token)
  81. {
  82. if (is_array($token))
  83. {
  84. list($id, $text) = $token;
  85. if (T_CONSTANT_ENCAPSED_STRING === $id)
  86. {
  87. $strings[$template][] = substr($text, 1, -1);
  88. }
  89. }
  90. }
  91. }
  92. }
  93. }
  94. }
  95. foreach ($strings as $template => $messages)
  96. {
  97. if (!$messages)
  98. {
  99. continue;
  100. }
  101. $this->logSection('i18n', sprintf('strings in "%s"', str_replace(sfConfig::get('sf_root_dir'), '', $template)), 1000);
  102. foreach ($messages as $message)
  103. {
  104. $this->log(" $message\n");
  105. }
  106. }
  107. }
  108. }

Debug toolbar