Browse Source

Fix issues with duplicate msgid values.

Msgid values could be duplicated if the same string was used
for singular and pluralized translations.  Re-index how the data is
stored so duplicate singular detection per domain is easier.

Fixes #2538
mark_story 14 years ago
parent
commit
4949a87b7e

+ 25 - 18
lib/Cake/Console/Command/Task/ExtractTask.php

@@ -70,18 +70,18 @@ class ExtractTask extends AppShell {
 	protected $_tokens = array();
 
 /**
- * Extracted strings
+ * Extracted strings indexed by domain.
  *
  * @var array
  */
 	protected $_strings = array();
 
 /**
- * Extracted sigular strings
+ * Singular strings and their line numbers.
  *
  * @var array
  */
-	protected $_singulars = array();
+	protected $_lines = array();
 
 /**
  * Destination path
@@ -332,14 +332,10 @@ class ExtractTask extends AppShell {
 				if ($mapCount == count($strings)) {
 					extract(array_combine($map, $strings));
 					$domain = isset($domain) ? $domain : 'default';
-					if (isset($plural)) {
-					    if (!isset($_this->_singulars[$domain])) {
-					        $this->_singulars[$domain] = array();
-					    }
-					    array_push($this->_singulars[$domain], $singular);
-					}
+
 					$string = isset($plural) ? $singular . "\0" . $plural : $singular;
-					$this->_strings[$domain][$string][$this->_file][] = $line;
+					$this->_strings[$domain][] = $string;
+					$this->_lines[$domain][$singular][$this->_file][] = $line;
 				} else {
 					$this->_markerError($this->_file, $line, $functionName, $count);
 				}
@@ -419,7 +415,8 @@ class ExtractTask extends AppShell {
 					$message = $rule;
 				}
 				if ($message) {
-					$this->_strings[$domain][$message][$file][] = 'validation for field ' . $field;
+					$this->_strings[$domain][] = $message;
+					$this->_lines[$domain][$message][$file][] =  'validation for field ' . $field;
 				}
 			}
 		}
@@ -432,7 +429,16 @@ class ExtractTask extends AppShell {
  */
 	protected function _buildFiles() {
 		foreach ($this->_strings as $domain => $strings) {
-			foreach ($strings as $string => $files) {
+			$added = array();
+			rsort($strings);
+
+			foreach ($strings as $i => $string) {
+				$plural = false;
+				$singular = $string;
+				if (strpos($string, "\0") !== false) {
+					list($singular, $plural) = explode("\0", $string);
+				}
+				$files = $this->_lines[$domain][$singular];
 				$occurrences = array();
 				foreach ($files as $file => $lines) {
 					$occurrences[] = $file . ':' . implode(';', $lines);
@@ -440,20 +446,21 @@ class ExtractTask extends AppShell {
 				$occurrences = implode("\n#: ", $occurrences);
 				$header = '#: ' . str_replace($this->_paths, '', $occurrences) . "\n";
 
-				if (strpos($string, "\0") === false) {
-				    if (isset($this->_singulars[$domain]) && in_array($string, $this->_singulars[$domain])) {
-                        continue;
-				    }
-				    $sentence = "msgid \"{$string}\"\n";
+				if ($plural === false && !empty($added[$singular])) {
+					continue;
+				}
+
+				if ($plural === false) {
+					$sentence = "msgid \"{$string}\"\n";
 					$sentence .= "msgstr \"\"\n\n";
 				} else {
-					list($singular, $plural) = explode("\0", $string);
 					$sentence = "msgid \"{$singular}\"\n";
 					$sentence .= "msgid_plural \"{$plural}\"\n";
 					$sentence .= "msgstr[0] \"\"\n";
 					$sentence .= "msgstr[1] \"\"\n\n";
 				}
 
+				$added[$singular] = true;
 				$this->_store($domain, $header, $sentence);
 				if ($domain != 'default' && $this->_merge) {
 					$this->_store('default', $header, $sentence);

+ 15 - 2
lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php

@@ -93,27 +93,37 @@ class ExtractTaskTest extends CakeTestCase {
 		// home.ctp
 		$pattern = '/msgid "Your tmp directory is writable."\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+
 		$pattern = '/msgid "Your tmp directory is NOT writable."\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+
 		$pattern = '/msgid "The %s is being used for caching. To change the config edit ';
 		$pattern .= 'APP\/config\/core.php "\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+
 		$pattern = '/msgid "Your cache is NOT working. Please check ';
 		$pattern .= 'the settings in APP\/config\/core.php"\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+
 		$pattern = '/msgid "Your database configuration file is present."\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+
 		$pattern = '/msgid "Your database configuration file is NOT present."\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+		
 		$pattern = '/msgid "Rename config\/database.php.default to ';
 		$pattern .= 'config\/database.php"\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+
 		$pattern = '/msgid "Cake is able to connect to the database."\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+
 		$pattern = '/msgid "Cake is NOT able to connect to the database."\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+
 		$pattern = '/msgid "Editing this Page"\nmsgstr ""\n/';
 		$this->assertRegExp($pattern, $result);
+
 		$pattern = '/msgid "To change the content of this page, create: APP\/views\/pages\/home\.ctp/';
 		$this->assertRegExp($pattern, $result);
 
@@ -121,10 +131,13 @@ class ExtractTaskTest extends CakeTestCase {
 		$this->assertRegExp($pattern, $result);
 
 		// extract.ctp
-		$pattern = '/\#: (\\\\|\/)extract\.ctp:6\n';
+		$pattern = '/\#: (\\\\|\/)extract\.ctp:15;6\n';
 		$pattern .= 'msgid "You have %d new message."\nmsgid_plural "You have %d new messages."/';
 		$this->assertRegExp($pattern, $result);
 
+		$pattern = '/msgid "You have %d new message."\nmsgstr ""/';
+		$this->assertNotRegExp($pattern, $result, 'No duplicate msgid');
+
 		$pattern = '/\#: (\\\\|\/)extract\.ctp:7\n';
 		$pattern .= 'msgid "You deleted %d message."\nmsgid_plural "You deleted %d messages."/';
 		$this->assertRegExp($pattern, $result);
@@ -134,7 +147,7 @@ class ExtractTaskTest extends CakeTestCase {
 		$pattern .= 'msgid "Editing this Page"\nmsgstr ""/';
 		$this->assertRegExp($pattern, $result);
 
-		$pattern = '/\#: (\\\\|\/)extract\.ctp:17\nmsgid "';
+		$pattern = '/\#: (\\\\|\/)extract\.ctp:18\nmsgid "';
 		$pattern .= 'Hot features!';
 		$pattern .= '\\\n - No Configuration: Set-up the database and let the magic begin';
 		$pattern .= '\\\n - Extremely Simple: Just look at the name...It\'s Cake';

+ 1 - 0
lib/Cake/Test/test_app/View/Pages/extract.ctp

@@ -12,6 +12,7 @@ echo __dn('domain', 'You deleted %d message (domain).', 'You deleted %d messages
 
 // Duplicated Message
 echo __('Editing this Page');
+echo __('You have %d new message.');
 
 // Multiline
 __('Hot features!'