diff -r 07239de796bb -r e756a8c72c3d cms/drupal/modules/field/field.multilingual.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/drupal/modules/field/field.multilingual.inc Fri Sep 08 12:04:06 2017 +0200 @@ -0,0 +1,301 @@ +{$field_name}[$langcode][$delta][$column_name] + * @endcode + * Every field can hold a single or multiple value for each language belonging + * to the available languages set: + * - For untranslatable fields this set only contains LANGUAGE_NONE. + * - For translatable fields this set can contain any language code. By default + * it is the list returned by field_content_languages(), which contains all + * installed languages with the addition of LANGUAGE_NONE. This default can be + * altered by modules implementing hook_field_available_languages_alter(). + * + * The available languages for a particular field are returned by + * field_available_languages(). Whether a field is translatable is determined by + * calling field_is_translatable(), which checks the $field['translatable'] + * property returned by field_info_field(), and whether there is at least one + * translation handler available for the field. A translation handler is a + * module registering itself via hook_entity_info() to handle field + * translations. + * + * By default, _field_invoke() and _field_invoke_multiple() are processing a + * field in all available languages, unless they are given a language + * suggestion. Based on that suggestion, _field_language_suggestion() determines + * the languages to act on. + * + * Most field_attach_*() functions act on all available languages, except for + * the following: + * - field_attach_form() only takes a single language code, specifying which + * language the field values will be submitted in. + * - field_attach_view() requires the language the entity will be displayed in. + * Since it is unknown whether a field translation exists for the requested + * language, the translation handler is responsible for performing one of the + * following actions: + * - Ignore missing translations, i.e. do not show any field values for the + * requested language. For example, see locale_field_language_alter(). + * - Provide a value in a different language as fallback. By default, the + * fallback logic is applied separately to each field to ensure that there + * is a value for each field to display. + * The field language fallback logic relies on the global language fallback + * configuration. Therefore, the displayed field values can be in the + * requested language, but may be different if no values for the requested + * language are available. The default language fallback rules inspect all the + * enabled languages ordered by their weight. This behavior can be altered or + * even disabled by modules implementing hook_field_language_alter(), making + * it possible to choose the first approach. The display language for each + * field is returned by field_language(). + * + * See @link field Field API @endlink for information about the other parts of + * the Field API. + */ + +/** + * Implements hook_multilingual_settings_changed(). + */ +function field_multilingual_settings_changed() { + field_info_cache_clear(); +} + +/** + * Collects the available languages for the given entity type and field. + * + * If the given field has language support enabled, an array of available + * languages will be returned, otherwise only LANGUAGE_NONE will be returned. + * Since the default value for a 'translatable' entity property is FALSE, we + * ensure that only entities that are able to handle translations actually get + * translatable fields. + * + * @param $entity_type + * The type of the entity the field is attached to, e.g. 'node' or 'user'. + * @param $field + * A field structure. + * + * @return + * An array of valid language codes. + */ +function field_available_languages($entity_type, $field) { + static $drupal_static_fast; + if (!isset($drupal_static_fast)) { + $drupal_static_fast['field_languages'] = &drupal_static(__FUNCTION__); + } + $field_languages = &$drupal_static_fast['field_languages']; + $field_name = $field['field_name']; + + if (!isset($field_languages[$entity_type][$field_name])) { + // If the field has language support enabled we retrieve an (alterable) list + // of enabled languages, otherwise we return just LANGUAGE_NONE. + if (field_is_translatable($entity_type, $field)) { + $languages = field_content_languages(); + // Let other modules alter the available languages. + $context = array('entity_type' => $entity_type, 'field' => $field); + drupal_alter('field_available_languages', $languages, $context); + $field_languages[$entity_type][$field_name] = $languages; + } + else { + $field_languages[$entity_type][$field_name] = array(LANGUAGE_NONE); + } + } + + return $field_languages[$entity_type][$field_name]; +} + +/** + * Process the given language suggestion based on the available languages. + * + * If a non-empty language suggestion is provided it must appear among the + * available languages, otherwise it will be ignored. + * + * @param $available_languages + * An array of valid language codes. + * @param $language_suggestion + * A language code or an array of language codes keyed by field name. + * @param $field_name + * The name of the field being processed. + * + * @return + * An array of valid language codes. + */ +function _field_language_suggestion($available_languages, $language_suggestion, $field_name) { + // Handle possible language suggestions. + if (!empty($language_suggestion)) { + // We might have an array of language suggestions keyed by field name. + if (is_array($language_suggestion) && isset($language_suggestion[$field_name])) { + $language_suggestion = $language_suggestion[$field_name]; + } + + // If we have a language suggestion and the suggested language is available, + // we return only it. + if (in_array($language_suggestion, $available_languages)) { + $available_languages = array($language_suggestion); + } + } + + return $available_languages; +} + +/** + * Returns available content languages. + * + * The languages that may be associated to fields include LANGUAGE_NONE. + * + * @return + * An array of language codes. + */ +function field_content_languages() { + return array_keys(language_list() + array(LANGUAGE_NONE => NULL)); +} + +/** + * Checks whether a field has language support. + * + * A field has language support enabled if its 'translatable' property is set to + * TRUE, and its entity type has at least one translation handler registered. + * + * @param $entity_type + * The type of the entity the field is attached to. + * @param $field + * A field data structure. + * + * @return + * TRUE if the field can be translated. + */ +function field_is_translatable($entity_type, $field) { + return $field['translatable'] && field_has_translation_handler($entity_type); +} + +/** + * Checks if a module is registered as a translation handler for a given entity. + * + * If no handler is passed, simply check if there is any translation handler + * enabled for the given entity type. + * + * @param $entity_type + * The type of the entity whose fields are to be translated. + * @param $handler + * (optional) The name of the handler to be checked. Defaults to NULL. + * + * @return + * TRUE, if the given handler is allowed to manage field translations. If no + * handler is passed, TRUE means there is at least one registered translation + * handler. + */ +function field_has_translation_handler($entity_type, $handler = NULL) { + $entity_info = entity_get_info($entity_type); + + if (isset($handler)) { + return !empty($entity_info['translation'][$handler]); + } + elseif (isset($entity_info['translation'])) { + foreach ($entity_info['translation'] as $handler_info) { + // The translation handler must use a non-empty data structure. + if (!empty($handler_info)) { + return TRUE; + } + } + } + + return FALSE; +} + +/** + * Ensures that a given language code is valid. + * + * Checks whether the given language is one of the enabled languages. Otherwise, + * it returns the current, global language; or the site's default language, if + * the additional parameter $default is TRUE. + * + * @param $langcode + * The language code to validate. + * @param $default + * Whether to return the default language code or the current language code in + * case $langcode is invalid. + * @return + * A valid language code. + */ +function field_valid_language($langcode, $default = TRUE) { + $enabled_languages = field_content_languages(); + if (in_array($langcode, $enabled_languages)) { + return $langcode; + } + global $language_content; + return $default ? language_default('language') : $language_content->language; +} + +/** + * Returns the display language for the fields attached to the given entity. + * + * The actual language for each given field is determined based on the requested + * language and the actual data available in the fields themselves. + * If there is no registered translation handler for the given entity type, the + * display language to be used is just LANGUAGE_NONE, as no other language code + * is allowed by field_available_languages(). + * If translation handlers are found, we let modules provide alternative display + * languages for fields not having the requested language available. + * Core language fallback rules are provided by locale_field_language_fallback() + * which is called by locale_field_language_alter(). + * + * @param $entity_type + * The type of $entity. + * @param $entity + * The entity to be displayed. + * @param $field_name + * (optional) The name of the field to be displayed. Defaults to NULL. If + * no value is specified, the display languages for every field attached to + * the given entity will be returned. + * @param $langcode + * (optional) The language code $entity has to be displayed in. Defaults to + * NULL. If no value is given the current language will be used. + * + * @return + * A language code if a field name is specified, an array of language codes + * keyed by field name otherwise. + */ +function field_language($entity_type, $entity, $field_name = NULL, $langcode = NULL) { + $display_languages = &drupal_static(__FUNCTION__, array()); + list($id, , $bundle) = entity_extract_ids($entity_type, $entity); + $langcode = field_valid_language($langcode, FALSE); + + if (!isset($display_languages[$entity_type][$id][$langcode])) { + $display_language = array(); + + // By default display language is set to LANGUAGE_NONE if the field + // translation is not available. It is up to translation handlers to + // implement language fallback rules. + foreach (field_info_instances($entity_type, $bundle) as $instance) { + $display_language[$instance['field_name']] = isset($entity->{$instance['field_name']}[$langcode]) ? $langcode : LANGUAGE_NONE; + } + + if (field_has_translation_handler($entity_type)) { + $context = array( + 'entity_type' => $entity_type, + 'entity' => $entity, + 'language' => $langcode, + ); + drupal_alter('field_language', $display_language, $context); + } + + $display_languages[$entity_type][$id][$langcode] = $display_language; + } + + $display_language = $display_languages[$entity_type][$id][$langcode]; + + // Single-field mode. + if (isset($field_name)) { + return isset($display_language[$field_name]) ? $display_language[$field_name] : FALSE; + } + + return $display_language; +}