Hi

I suggest that the author check whether the translation field is null or not, instead of checking if empty or not.

I encountered an issue with submitting string translation. This is the error message I got:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry "lang-code-lid-0" for key 'PRIMARY': INSERT INTO {locales_target} (lid, translation, language) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2); Array ( [:db_insert_placeholder_0] => lid [:db_insert_placeholder_1] => translation text [:db_insert_placeholder_2] => lang-code ) in locale_translate_edit_form_submit() (line 1213 of /mnt/www/html/powerintdev/docroot/modules/locale/locale.admin.inc).

I looked into my database and found that this particular data already exist but the translation is an empty string

| lid | translation | language | plid | plural | i18n_status |
+-------+-------------+----------+------+--------+-------------+
| lid | | lang-code | 0 | 0 | 1 |

I checked the code in locale_translate_edit_form_submit(). it checks if the translation field in the locales_target table is empty, if yes then insert the translation. In my case, the translation text is an empty string (but the data row does exist), so when using !empty($translation), the result is no, according to http://us1.php.net/empty (an empty string is considered to be empty)
, then db_insert is used and it generate error of "duplicate entry" because "insert" is supposed to add new data, not update existing data. So, I suggest that the author check whether the translation field is null or not, instead of checking if empty or not. Or use

$translation = db_query("SELECT Count (*) FROM {locales_target} WHERE lid = :lid AND language = :language", array(':lid' => $lid, ':language' => $key))->fetchField();
if ($translation) {
db_update('locales_target').....

else (
db_insert('locales_target').....

This is the original code:

$translation = db_query("SELECT translation FROM {locales_target} WHERE lid = :lid AND language = :language", array(':lid' => $lid, ':language' => $key))->fetchField();
if (!empty($translation)) {
db_update('locales_target')
->fields(array(
'translation' => $value,
))
->condition('lid', $lid)
->condition('language', $key)
->execute();
}
else {
db_insert('locales_target')
->fields(array(
'lid' => $lid,
'translation' => $value,
'language' => $key,
))
->execute();
}

API page: https://api.drupal.org/api/drupal/modules%21locale%21locale.module/7

Enter a descriptive title (above) relating to locale.module, then describe the problem you have found:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Stanislav_B’s picture

I faced with this issue too when try translate strings from "Path breadcrumbs" module. Thank you Pearl that help to resolve this issue for me.

I just replace if (!empty($translation)) to if (is_string($translation) || !empty($translation))

I think this issue related to this - https://www.drupal.org/node/2669614

I am surprised how core issue opened more than two years when change one line code is enough to fix it

hgoto’s picture

Thank you for sharing and confirming the issue. I also think this should be fixed.

Surely this occurs if I change the database cell value but it seems to be impossible to register such an empty string row in the locales_target table through the admin UI. How did you insert an empty target string in the table?

Anyway. For the next step, I created a patch for this following the suggested ideas. This contains a test, too. I'd like someone to review this.

(I changed the version because this exists in 7.x-dev.)

The last submitted patch, 2: drupal-fix_empty_translation_error-2201615-2-test_only.patch, failed testing.

hgoto’s picture

I checked if D8 has the same issue and found it doesn't.

The D8 version of locale_translate_edit_form_submit() is TranslateEditForm::submitForm() and it checks the existence of the record properly.

    // Preload all translations for strings in the form.
    $lids = array_keys($form_state->getValue('strings'));
    $existing_translation_objects = array();
    foreach ($this->localeStorage->getTranslations(array('lid' => $lids, 'language' => $langcode, 'translated' => TRUE)) as $existing_translation_object) {
      $existing_translation_objects[$existing_translation_object->lid] = $existing_translation_object;
    }

    foreach ($form_state->getValue('strings') as $lid => $new_translation) {
      $existing_translation = isset($existing_translation_objects[$lid]);
Fabianx’s picture

Title: should check is_nul, instead of !empty for string » should check is_string(), instead of !empty() for string
Status: Needs review » Reviewed & tested by the community

RTBC, looks good to me.

Test looks good to.

stefan.r’s picture

Issue tags: +Pending Drupal 7 commit
stefan.r’s picture

Title: should check is_string(), instead of !empty() for string » locale_translate_edit_form_submit() should check is_string(), instead of !empty() for string
Fabianx’s picture

Assigned: Unassigned » stefan.r
Issue tags: +Drupal bugfix target

I think Stefan should commit that as I RTBC'ed it.

  • stefan.r committed bbb3a19 on 7.x
    Issue #2201615 by hgoto: locale_translate_edit_form_submit() should...
stefan.r’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Pending Drupal 7 commit, -Drupal bugfix target

Committed and pushed to 7.x, thanks!

hgoto’s picture

Thank you!

stefan.r’s picture

Assigned: stefan.r » Unassigned

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.