Newer
Older
Angie Byron
committed
<?php
/**
* @file
* Contains \Drupal\locale\Form\TranslateEditForm.
*/
namespace Drupal\locale\Form;
use Drupal\Component\Utility\String;
Dries Buytaert
committed
use Drupal\Core\Form\FormStateInterface;
Angie Byron
committed
use Drupal\Core\Render\Element;
Angie Byron
committed
use Drupal\locale\SourceString;
/**
* Defines a translation edit form.
*/
class TranslateEditForm extends TranslateFormBase {
/**
* {@inheritdoc}
*/
Alex Pott
committed
public function getFormId() {
Angie Byron
committed
return 'locale_translate_edit_form';
}
/**
* {@inheritdoc}
*/
Dries Buytaert
committed
public function buildForm(array $form, FormStateInterface $form_state) {
Angie Byron
committed
$filter_values = $this->translateFilterValues();
$langcode = $filter_values['langcode'];
$this->languageManager->reset();
Angie Byron
committed
$languages = language_list();
$langname = isset($langcode) ? $languages[$langcode]->name : "- None -";
$form['#attached']['library'][] = 'locale/drupal.locale.admin';
Angie Byron
committed
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
$form['langcode'] = array(
'#type' => 'value',
'#value' => $filter_values['langcode'],
);
$form['strings'] = array(
'#type' => 'item',
'#tree' => TRUE,
'#language' => $langname,
'#theme' => 'locale_translate_edit_form_strings',
);
if (isset($langcode)) {
$strings = $this->translateFilterLoadStrings();
$plural_formulas = $this->state->get('locale.translation.plurals') ?: array();
foreach ($strings as $string) {
// Cast into source string, will do for our purposes.
$source = new SourceString($string);
// Split source to work with plural values.
$source_array = $source->getPlurals();
$translation_array = $string->getPlurals();
if (count($source_array) == 1) {
// Add original string value and mark as non-plural.
$form['strings'][$string->lid]['plural'] = array(
'#type' => 'value',
'#value' => 0,
);
$form['strings'][$string->lid]['original'] = array(
'#type' => 'item',
'#title' => $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))),
'#title_display' => 'invisible',
'#markup' => '<span lang="en">' . String::checkPlain($source_array[0]) . '</span>',
);
}
else {
// Add original string value and mark as plural.
$form['strings'][$string->lid]['plural'] = array(
'#type' => 'value',
'#value' => 1,
);
$form['strings'][$string->lid]['original_singular'] = array(
'#type' => 'item',
'#title' => $this->t('Singular form'),
'#markup' => '<span lang="en">' . String::checkPlain($source_array[0]) . '</span>',
'#prefix' => '<span class="visually-hidden">' . $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))) . '</span>',
Angie Byron
committed
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
);
$form['strings'][$string->lid]['original_plural'] = array(
'#type' => 'item',
'#title' => $this->t('Plural form'),
'#markup' => '<span lang="en">' . String::checkPlain($source_array[1]) . '</span>',
);
}
if (!empty($string->context)) {
$form['strings'][$string->lid]['context'] = array(
'#type' => 'value',
'#value' => '<span lang="en">' . String::checkPlain($string->context) . '</span>',
);
}
// Approximate the number of rows to use in the default textarea.
$rows = min(ceil(str_word_count($source_array[0]) / 12), 10);
if (empty($form['strings'][$string->lid]['plural']['#value'])) {
$form['strings'][$string->lid]['translations'][0] = array(
'#type' => 'textarea',
'#title' => $this->t('Translated string (@language)', array('@language' => $langname)),
'#title_display' => 'invisible',
'#rows' => $rows,
'#default_value' => $translation_array[0],
'#attributes' => array('lang' => $langcode),
);
}
else {
// Dealing with plural strings.
if (isset($plural_formulas[$langcode]['plurals']) && $plural_formulas[$langcode]['plurals'] > 2) {
// Add a textarea for each plural variant.
for ($i = 0; $i < $plural_formulas[$langcode]['plurals']; $i++) {
$form['strings'][$string->lid]['translations'][$i] = array(
'#type' => 'textarea',
'#title' => ($i == 0 ? $this->t('Singular form') : format_plural($i, 'First plural form', '@count. plural form')),
'#rows' => $rows,
'#default_value' => isset($translation_array[$i]) ? $translation_array[$i] : '',
'#attributes' => array('lang' => $langcode),
'#prefix' => $i == 0 ? ('<span class="visually-hidden">' . $this->t('Translated string (@language)', array('@language' => $langname)) . '</span>') : '',
Angie Byron
committed
);
}
}
else {
// Fallback for unknown number of plurals.
$form['strings'][$string->lid]['translations'][0] = array(
'#type' => 'textarea',
'#title' => $this->t('Singular form'),
'#rows' => $rows,
'#default_value' => $translation_array[0],
'#attributes' => array('lang' => $langcode),
'#prefix' => '<span class="visually-hidden">' . $this->t('Translated string (@language)', array('@language' => $langname)) . '</span>',
Angie Byron
committed
);
$form['strings'][$string->lid]['translations'][1] = array(
'#type' => 'textarea',
'#title' => $this->t('Plural form'),
'#rows' => $rows,
'#default_value' => isset($translation_array[1]) ? $translation_array[1] : '',
'#attributes' => array('lang' => $langcode),
);
}
}
}
Angie Byron
committed
if (count(Element::children($form['strings']))) {
Angie Byron
committed
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Save translations'),
);
}
}
return $form;
}
/**
* {@inheritdoc}
*/
Dries Buytaert
committed
public function validateForm(array &$form, FormStateInterface $form_state) {
Alex Pott
committed
$langcode = $form_state->getValue('langcode');
foreach ($form_state->getValue('strings') as $lid => $translations) {
Angie Byron
committed
foreach ($translations['translations'] as $key => $value) {
if (!locale_string_is_safe($value)) {
$form_state->setErrorByName("strings][$lid][translations][$key", $this->t('The submitted string contains disallowed HTML: %string', array('%string' => $value)));
$form_state->setErrorByName("translations][$langcode][$key", $this->t('The submitted string contains disallowed HTML: %string', array('%string' => $value)));
$this->logger('locale')->warning('Attempted submission of a translation string with disallowed HTML: %string', array('%string' => $value));
Angie Byron
committed
}
}
}
}
/**
* {@inheritdoc}
*/
Dries Buytaert
committed
public function submitForm(array &$form, FormStateInterface $form_state) {
Alex Pott
committed
$langcode = $form_state->getValue('langcode');
Angie Byron
committed
$updated = array();
// Preload all translations for strings in the form.
Alex Pott
committed
$lids = array_keys($form_state->getValue('strings'));
Angie Byron
committed
$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;
}
Alex Pott
committed
foreach ($form_state->getValue('strings') as $lid => $new_translation) {
Angie Byron
committed
$existing_translation = isset($existing_translation_objects[$lid]);
// Plural translations are saved in a delimited string. To be able to
// compare the new strings with the existing strings a string in the same
// format is created.
Angie Byron
committed
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
$new_translation_string_delimited = implode(LOCALE_PLURAL_DELIMITER, $new_translation['translations']);
// Generate an imploded string without delimiter, to be able to run
// empty() on it.
$new_translation_string = implode('', $new_translation['translations']);
$is_changed = FALSE;
if ($existing_translation && $existing_translation_objects[$lid]->translation != $new_translation_string_delimited) {
// If there is an existing translation in the DB and the new translation
// is not the same as the existing one.
$is_changed = TRUE;
}
elseif (!$existing_translation && !empty($new_translation_string)) {
// Newly entered translation.
$is_changed = TRUE;
}
if ($is_changed) {
// Only update or insert if we have a value to use.
$target = isset($existing_translation_objects[$lid]) ? $existing_translation_objects[$lid] : $this->localeStorage->createTranslation(array('lid' => $lid, 'language' => $langcode));
$target->setPlurals($new_translation['translations'])
->setCustomized()
->save();
$updated[] = $target->getId();
}
if (empty($new_translation_string) && isset($existing_translation_objects[$lid])) {
// Empty new translation entered: remove existing entry from database.
$existing_translation_objects[$lid]->delete();
$updated[] = $lid;
}
}
drupal_set_message($this->t('The strings have been saved.'));
// Keep the user on the current pager page.
$page = $this->getRequest()->query->get('page');
if (isset($page)) {
Alex Pott
committed
$form_state->setRedirect(
'locale.translate_page',
array(),
array('page' => $page)
Angie Byron
committed
);
Angie Byron
committed
}
if ($updated) {
// Clear cache and force refresh of JavaScript translations.
_locale_refresh_translations(array($langcode), $updated);
_locale_refresh_configuration(array($langcode), $updated);
}
}
}