Browse Source

Fix saving empty values for translated fields with multiple locales

mark_story 13 years ago
parent
commit
788cf52572

+ 40 - 12
lib/Cake/Model/Behavior/TranslateBehavior.php

@@ -385,7 +385,6 @@ class TranslateBehavior extends ModelBehavior {
 		if (!isset($this->runtime[$Model->alias]['beforeValidate']) && !isset($this->runtime[$Model->alias]['beforeSave'])) {
 			return true;
 		}
-		$locale = $this->_getLocale($Model);
 		if (isset($this->runtime[$Model->alias]['beforeValidate'])) {
 			$tempData = $this->runtime[$Model->alias]['beforeValidate'];
 		} else {
@@ -396,18 +395,10 @@ class TranslateBehavior extends ModelBehavior {
 		$conditions = array('model' => $Model->alias, 'foreign_key' => $Model->id);
 		$RuntimeModel = $this->translateModel($Model);
 
-		$fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']);
 		if ($created) {
-			// set each field value to an empty string
-			foreach ($fields as $key => $field) {
-				if (!is_numeric($key)) {
-					$field = $key;
-				}
-				if (!isset($tempData[$field])) {
-					$tempData[$field] = '';
-				}
-			}
+			$tempData = $this->_prepareTranslations($Model, $tempData);
 		}
+		$locale = $this->_getLocale($Model);
 
 		foreach ($tempData as $field => $value) {
 			unset($conditions['content']);
@@ -422,7 +413,13 @@ class TranslateBehavior extends ModelBehavior {
 					$value = array($locale => $value);
 				}
 			}
-			$translations = $RuntimeModel->find('list', array('conditions' => $conditions, 'fields' => array($RuntimeModel->alias . '.locale', $RuntimeModel->alias . '.id')));
+			$translations = $RuntimeModel->find('list', array(
+				'conditions' => $conditions,
+				'fields' => array(
+					$RuntimeModel->alias . '.locale',
+					$RuntimeModel->alias . '.id'
+				)
+			));
 			foreach ($value as $_locale => $_value) {
 				$RuntimeModel->create();
 				$conditions['locale'] = $_locale;
@@ -437,6 +434,37 @@ class TranslateBehavior extends ModelBehavior {
 	}
 
 /**
+ * Prepares the data to be saved for translated records.
+ * Add blank fields, and populates data for multi-locale saves.
+ *
+ * @param array $data The sparse data that was provided.
+ * @return array The fully populated data to save.
+ */
+	protected function _prepareTranslations(Model $Model, $data) {
+		$fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']);
+		$locales = array();
+		foreach ($data as $key => $value) {
+			if (is_array($value)) {
+				$locales = array_merge($locales, array_keys($value));
+			}
+		}
+		$locales = array_unique($locales);
+		$hasLocales = count($locales) > 0;
+
+		foreach ($fields as $key => $field) {
+			if (!is_numeric($key)) {
+				$field = $key;
+			}
+			if ($hasLocales && !isset($data[$field])) {
+				$data[$field] = array_fill_keys($locales, '');
+			} elseif (!isset($data[$field])) {
+				$data[$field] = '';
+			}
+		}
+		return $data;
+	}
+
+/**
  * afterDelete Callback
  *
  * @param Model $Model Model the callback was run on.

+ 23 - 16
lib/Cake/Test/Case/Model/Behavior/TranslateBehaviorTest.php

@@ -552,7 +552,17 @@ class TranslateBehaviorTest extends CakeTestCase {
 			) + $data
 		);
 		$this->assertEquals($expected, $result);
-		
+	}
+
+/**
+ * Test that all fields are create with partial data + multiple locales.
+ *
+ * @return void
+ */
+	public function testSavePartialFieldMultipleLocales() {
+		$this->loadFixtures('Translate', 'TranslatedItem');
+
+		$TestModel = new TranslatedItem();
 		$TestModel->locale = 'eng';
 		$data = array(
 			'slug' => 'fifth_translated',
@@ -561,60 +571,57 @@ class TranslateBehaviorTest extends CakeTestCase {
 		$TestModel->create($data);
 		$TestModel->save();
 		$TestModel->unbindTranslation();
+
 		$translations = array('title' => 'Title', 'content' => 'Content');
 		$TestModel->bindTranslation($translations, false);
 		$result = $TestModel->read(null, $TestModel->id);
 		$expected = array(
 			'TranslatedItem' => array(
-				'id' => '5',
+				'id' => '4',
 				'translated_article_id' => null,
 				'slug' => 'fifth_translated',
 				'locale' => 'eng',
-				'title' => '',
+				'title' => 'Title #5',
 				'content' => ''
 			),
-			0 => array(
-				'TranslatedItem__i18n_Title' => 'Title #5',
-				'TranslatedItem__i18n_Content' => ''
-			),
 			'Title' => array(
 				0 => array(
-					'id' => '21',
+					'id' => '19',
 					'locale' => 'eng',
 					'model' => 'TranslatedItem',
-					'foreign_key' => '5',
+					'foreign_key' => '4',
 					'field' => 'title',
 					'content' => 'Title #5'
 				),
 				1 => array(
-					'id' => '22',
+					'id' => '20',
 					'locale' => 'spa',
 					'model' => 'TranslatedItem',
-					'foreign_key' => '5',
+					'foreign_key' => '4',
 					'field' => 'title',
 					'content' => 'Leyenda #5'
 				)
 			),
 			'Content' => array(
 				0 => array(
-					'id' => '23',
+					'id' => '21',
 					'locale' => 'eng',
 					'model' => 'TranslatedItem',
-					'foreign_key' => '5',
+					'foreign_key' => '4',
 					'field' => 'content',
 					'content' => ''
 				),
 				1 => array(
-					'id' => '24',
+					'id' => '22',
 					'locale' => 'spa',
 					'model' => 'TranslatedItem',
-					'foreign_key' => '5',
+					'foreign_key' => '4',
 					'field' => 'content',
 					'content' => ''
 				)
 			)
 		);
-		$this->assertEquals($expected, $result);		
+		$this->assertEquals($expected, $result);
 	}
 
 /**