public static function LocalizeFields::fieldWidgetFormAlter in Localize Fields 7
Translates fields' labels, descriptions etc.
Used by hook_field_widget_form_alter() implementation.
Is executed right before hook_preprocess_field_multiple_value_form() and before hook_form_alter().
Parameters
array $element:
array $form_state:
array &$context:
1 call to LocalizeFields::fieldWidgetFormAlter()
- localize_fields_field_widget_form_alter in ./
localize_fields.module - Translates fields' labels, descriptions etc.
File
- ./
LocalizeFields.inc, line 324 - Drupal Localize Fields module
Class
- LocalizeFields
- @file Drupal Localize Fields module
Code
public static function fieldWidgetFormAlter(&$element, &$form_state, &$context) {
if (($localize = self::$localize) == -1) {
// Save a method call if possible.
$localize = self::localize();
}
if (!$localize || empty($context['field']['type'])) {
return;
}
$cntxtDelim = self::CONTEXT_DELIMITER;
// Refer original label and description - to make other module's
// hook_field_widget_form_alter() implementations 'see' translated labels
// (unless 'tentative').
$sourceLabel = $sourceDescription = '';
if (!self::$tentative) {
if (!empty($context['instance']['label'])) {
$sourceLabel =& $context['instance']['label'];
}
if (!empty($context['instance']['description'])) {
$sourceDescription =& $context['instance']['description'];
}
}
else {
if (!empty($context['instance']['label'])) {
$sourceLabel = $context['instance']['label'];
}
if (!empty($context['instance']['description'])) {
$sourceDescription = $context['instance']['description'];
}
}
$field_name = $context['field']['field_name'];
$field_type = $context['field']['type'];
// Set these for preprocess_field_multiple_value_form as fallbacks.
self::$lastKnownEntityType = $context['instance']['entity_type'];
self::$lastKnownBundle = $bundle = $context['instance']['bundle'];
$context_field = 'field' . $cntxtDelim . $field_name . $cntxtDelim;
$context_instance = 'field_instance' . $cntxtDelim . $bundle . self::CONTEXT_DELIMITER_BUNDLE . $field_name . $cntxtDelim;
// File fields are pretty non-standard.
$file_cardinalitySingle = FALSE;
// These might be used more than once.
$filtered_translated_label = $filtered_translated_description = '';
// Find the array listing labels.
if (array_key_exists('value', $element) && array_key_exists('#title', $element['value'])) {
/*
* text and number_ fields have a #title in a value bucket.
*
* Their single row instances' ['value']['#title'] is non-empty (and that
* one is used in widget rendering and validation),
* whereas any/multiple rows instances' ['value']['#title'] is empty.
*
* Their single row instances also #title in in root; it's usually not
* used but let's play it safe.
*
* Single row instance:
* #title: (string) >>Native title<<
* value: (array) {
* . #title: (string) >>Native title<<
* }
*
* Any/multiple row instance:
* value: (array) {
* . #title: (string) >><<
* }
*
* NB: sometimes single row instances have the same structure as
* any/multiple row instance.
* Don't really know what affects/controls the structure.
*/
$props =& $element['value'];
// text and number_ fields single row instances got #title in root too;
// it's usually not used but let's play it safe.
if (array_key_exists('#title', $element)) {
if ($sourceLabel) {
$element['#title'] = $filtered_translated_label = check_plain($sourceLabel = self::translateInternal($sourceLabel, $context_instance . 'label', TRUE));
}
if ($sourceDescription && array_key_exists('#description', $element)) {
$element['#description'] = $filtered_translated_description = field_filter_xss($sourceDescription = self::translateInternal($sourceDescription, $context_instance . 'description', FALSE));
}
}
}
elseif (array_key_exists('#title', $element)) {
// list_ types.
$props =& $element;
}
elseif (array_key_exists(0, $element) && array_key_exists('#title', $element[0])) {
// Single instance file has no props in $element root.
$file_cardinalitySingle = TRUE;
$props =& $element[0];
}
else {
// Unsupported element structure.
return;
}
// For some field types we translate the label/description in a non-generic
// manner.
$genericTranslateLabel = $genericTranslateDescription = TRUE;
// Most field types require that we prepend a custom validate function
// to secure translation during validation.
$preValidate = TRUE;
switch ($field_type) {
// These are all covered by the general behaviour, and may be tested via
// the localize_fields_test Features module.
// case 'text':
// case 'text_long':
// case 'text_with_summary':
// case 'taxonomy_term_reference':
// case 'date':
// case 'datetime':
// case 'datestamp':
// case 'field_collection':
// break;
case 'number_integer':
case 'number_decimal':
case 'number_float':
// Prefix/suffixes are not encoded in form rendering.
if (array_key_exists('#field_prefix', $props) && ($source = $props['#field_prefix']) !== '') {
$props['#field_prefix'] = field_filter_xss(self::translateInternal($source, $context_instance . 'prefix', FALSE));
}
if (array_key_exists('#field_suffix', $props) && ($source = $props['#field_suffix']) !== '') {
$props['#field_suffix'] = field_filter_xss(self::translateInternal($source, $context_instance . 'suffix', FALSE));
}
break;
case 'list_boolean':
case 'list_text':
case 'list_integer':
case 'list_decimal':
case 'list_float':
// @todo: Support custom list types by switch'ing over widget type and
// filter off auto-complete fields by their widget type (on of the text
// widgets) leaving only 'real' list types to this algo.
if (!empty($context['field']['settings']['allowed_values'])) {
// Context is field name only, because options are a field_base
// property.
$context_options = $context_field . 'allowed_values';
// list_boolean that uses the 'on' value as field label
// - except when nested in a field_collection (sic!).
if ($props['#title'] && isset($context['instance']['widget']['settings']['display_label']) && !$context['instance']['widget']['settings']['display_label']) {
$genericTranslateLabel = FALSE;
$props['#title'] = check_plain($sourceLabel = self::translateInternal($props['#title'], $context_options, FALSE));
}
// Translate option labels - unless flagged 'off'.
if (empty($context['field']['settings']['allowed_values_no_localization']) && array_key_exists('#options', $props) && !empty($props['#options'])) {
foreach ($props['#options'] as &$label) {
// Option labels could easily be integers. Decimals on the other
// hand may have to be translated because of the decimal separator.
if ($label && !ctype_digit('' . $label)) {
$label = field_filter_xss(self::translateInternal($label, $context_options, FALSE));
}
}
unset($label);
// Iteration ref.
}
}
break;
case 'file':
case 'image':
// Doesn't need our pre validator.
$preValidate = FALSE;
// Multi instance file fields have title and description on instances as
// well as the overall field.
// And the title of such instances are used by core field validation.
if (!$file_cardinalitySingle) {
$limit = 100;
for ($i = 0; $i < $limit; ++$i) {
if (array_key_exists($i, $element)) {
if ($sourceLabel && array_key_exists('#title', $element[$i])) {
$element[$i]['#title'] = $filtered_translated_label ? $filtered_translated_label : ($filtered_translated_label = check_plain($sourceLabel = self::translateInternal($sourceLabel, $context_instance . 'label', TRUE)));
}
if ($sourceDescription && array_key_exists('#description', $element[$i])) {
$element[$i]['#description'] = $filtered_translated_description ? $filtered_translated_description : ($filtered_translated_description = field_filter_xss($sourceDescription = self::translateInternal($sourceDescription, $context_instance . 'description', FALSE)));
}
}
else {
break;
}
}
}
elseif (array_key_exists('#description', $props) && $sourceDescription && ($source = $props['#description']) && strpos($source, '<br')) {
$genericTranslateDescription = FALSE;
$a = explode('<br', $source);
$a[0] = field_filter_xss($sourceDescription = self::translateInternal($sourceDescription, $context_instance . 'description', FALSE));
$props['#description'] = join('<br', $a);
}
break;
}
// All types has a label (at least here; because of the initial process
// of finding the right element array).
if ($genericTranslateLabel && $sourceLabel) {
$props['#title'] = $filtered_translated_label ? $filtered_translated_label : ($filtered_translated_label = check_plain($sourceLabel = self::translateInternal($sourceLabel, $context_instance . 'label', TRUE)));
}
// Most types has a description.
if ($genericTranslateDescription && $sourceDescription && array_key_exists('#description', $props)) {
$props['#description'] = $filtered_translated_description ? $filtered_translated_description : ($filtered_translated_description = field_filter_xss($sourceDescription = self::translateInternal($sourceDescription, $context_instance . 'description', FALSE)));
}
// Most types need custom validator (which only translates).
if ($preValidate && array_key_exists('#element_validate', $props) && !in_array('localize_fields_pre_element_validate', $props['#element_validate'])) {
array_unshift($props['#element_validate'], 'localize_fields_pre_element_validate');
}
}