annotate includes/language.inc @ 13:134d4b2e75f6

updated quicktabs and google analytics modules
author danieleb <danielebarchiesi@me.com>
date Tue, 29 Oct 2013 13:48:59 +0000
parents ff03f76ab3fe
children
rev   line source
danielebarchiesi@0 1 <?php
danielebarchiesi@0 2
danielebarchiesi@0 3 /**
danielebarchiesi@0 4 * @file
danielebarchiesi@0 5 * Language Negotiation API.
danielebarchiesi@0 6 *
danielebarchiesi@0 7 * @see http://drupal.org/node/1497272
danielebarchiesi@0 8 */
danielebarchiesi@0 9
danielebarchiesi@0 10 /**
danielebarchiesi@0 11 * No language negotiation. The default language is used.
danielebarchiesi@0 12 */
danielebarchiesi@0 13 define('LANGUAGE_NEGOTIATION_DEFAULT', 'language-default');
danielebarchiesi@0 14
danielebarchiesi@0 15 /**
danielebarchiesi@0 16 * @defgroup language_negotiation Language Negotiation API functionality
danielebarchiesi@0 17 * @{
danielebarchiesi@0 18 * Functions to customize the language types and the negotiation process.
danielebarchiesi@0 19 *
danielebarchiesi@0 20 * The language negotiation API is based on two major concepts:
danielebarchiesi@0 21 * - Language types: types of translatable data (the types of data that a user
danielebarchiesi@0 22 * can view or request).
danielebarchiesi@0 23 * - Language negotiation providers: functions for determining which language to
danielebarchiesi@0 24 * use to present a particular piece of data to the user.
danielebarchiesi@0 25 * Both language types and language negotiation providers are customizable.
danielebarchiesi@0 26 *
danielebarchiesi@0 27 * Drupal defines three built-in language types:
danielebarchiesi@0 28 * - Interface language: The page's main language, used to present translated
danielebarchiesi@0 29 * user interface elements such as titles, labels, help text, and messages.
danielebarchiesi@0 30 * - Content language: The language used to present content that is available
danielebarchiesi@0 31 * in more than one language (see
danielebarchiesi@0 32 * @link field_language Field Language API @endlink for details).
danielebarchiesi@0 33 * - URL language: The language associated with URLs. When generating a URL,
danielebarchiesi@0 34 * this value will be used by url() as a default if no explicit preference is
danielebarchiesi@0 35 * provided.
danielebarchiesi@0 36 * Modules can define additional language types through
danielebarchiesi@0 37 * hook_language_types_info(), and alter existing language type definitions
danielebarchiesi@0 38 * through hook_language_types_info_alter().
danielebarchiesi@0 39 *
danielebarchiesi@0 40 * Language types may be configurable or fixed. The language negotiation
danielebarchiesi@0 41 * providers associated with a configurable language type can be explicitly
danielebarchiesi@0 42 * set through the user interface. A fixed language type has predetermined
danielebarchiesi@0 43 * (module-defined) language negotiation settings and, thus, does not appear in
danielebarchiesi@0 44 * the configuration page. Here is a code snippet that makes the content
danielebarchiesi@0 45 * language (which by default inherits the interface language's values)
danielebarchiesi@0 46 * configurable:
danielebarchiesi@0 47 * @code
danielebarchiesi@0 48 * function mymodule_language_types_info_alter(&$language_types) {
danielebarchiesi@0 49 * unset($language_types[LANGUAGE_TYPE_CONTENT]['fixed']);
danielebarchiesi@0 50 * }
danielebarchiesi@0 51 * @endcode
danielebarchiesi@0 52 *
danielebarchiesi@0 53 * Every language type can have a different set of language negotiation
danielebarchiesi@0 54 * providers assigned to it. Different language types often share the same
danielebarchiesi@0 55 * language negotiation settings, but they can have independent settings if
danielebarchiesi@0 56 * needed. If two language types are configured the same way, their language
danielebarchiesi@0 57 * switcher configuration will be functionally identical and the same settings
danielebarchiesi@0 58 * will act on both language types.
danielebarchiesi@0 59 *
danielebarchiesi@0 60 * Drupal defines the following built-in language negotiation providers:
danielebarchiesi@0 61 * - URL: Determine the language from the URL (path prefix or domain).
danielebarchiesi@0 62 * - Session: Determine the language from a request/session parameter.
danielebarchiesi@0 63 * - User: Follow the user's language preference.
danielebarchiesi@0 64 * - Browser: Determine the language from the browser's language settings.
danielebarchiesi@0 65 * - Default language: Use the default site language.
danielebarchiesi@0 66 * Language negotiation providers are simple callback functions that implement a
danielebarchiesi@0 67 * particular logic to return a language code. For instance, the URL provider
danielebarchiesi@0 68 * searches for a valid path prefix or domain name in the current request URL.
danielebarchiesi@0 69 * If a language negotiation provider does not return a valid language code, the
danielebarchiesi@0 70 * next provider associated to the language type (based on provider weight) is
danielebarchiesi@0 71 * invoked.
danielebarchiesi@0 72 *
danielebarchiesi@0 73 * Modules can define additional language negotiation providers through
danielebarchiesi@0 74 * hook_language_negotiation_info(), and alter existing providers through
danielebarchiesi@0 75 * hook_language_negotiation_info_alter(). Here is an example snippet that lets
danielebarchiesi@0 76 * path prefixes be ignored for administrative paths:
danielebarchiesi@0 77 * @code
danielebarchiesi@0 78 * function mymodule_language_negotiation_info_alter(&$negotiation_info) {
danielebarchiesi@0 79 * // Replace the core function with our own function.
danielebarchiesi@0 80 * module_load_include('language', 'inc', 'language.negotiation');
danielebarchiesi@0 81 * $negotiation_info[LANGUAGE_NEGOTIATION_URL]['callbacks']['negotiation'] = 'mymodule_from_url';
danielebarchiesi@0 82 * $negotiation_info[LANGUAGE_NEGOTIATION_URL]['file'] = drupal_get_path('module', 'mymodule') . '/mymodule.module';
danielebarchiesi@0 83 * }
danielebarchiesi@0 84 *
danielebarchiesi@0 85 * function mymodule_from_url($languages) {
danielebarchiesi@0 86 * // Use the core URL language negotiation provider to get a valid language
danielebarchiesi@0 87 * // code.
danielebarchiesi@0 88 * module_load_include('language', 'inc', 'language.negotiation');
danielebarchiesi@0 89 * $langcode = language_from_url($languages);
danielebarchiesi@0 90 *
danielebarchiesi@0 91 * // If we are on an administrative path, override with the default language.
danielebarchiesi@0 92 * if (isset($_GET['q']) && strtok($_GET['q'], '/') == 'admin') {
danielebarchiesi@0 93 * return language_default()->langcode;
danielebarchiesi@0 94 * }
danielebarchiesi@0 95 * return $langcode;
danielebarchiesi@0 96 * }
danielebarchiesi@0 97 * ?>
danielebarchiesi@0 98 * @endcode
danielebarchiesi@0 99 *
danielebarchiesi@0 100 * For more information, see
danielebarchiesi@0 101 * @link http://drupal.org/node/1497272 Language Negotiation API @endlink
danielebarchiesi@0 102 */
danielebarchiesi@0 103
danielebarchiesi@0 104 /**
danielebarchiesi@0 105 * Returns all the defined language types.
danielebarchiesi@0 106 *
danielebarchiesi@0 107 * @return
danielebarchiesi@0 108 * An array of language type names. The name will be used as the global
danielebarchiesi@0 109 * variable name the language value will be stored in.
danielebarchiesi@0 110 */
danielebarchiesi@0 111 function language_types_info() {
danielebarchiesi@0 112 $language_types = &drupal_static(__FUNCTION__);
danielebarchiesi@0 113
danielebarchiesi@0 114 if (!isset($language_types)) {
danielebarchiesi@0 115 $language_types = module_invoke_all('language_types_info');
danielebarchiesi@0 116 // Let other modules alter the list of language types.
danielebarchiesi@0 117 drupal_alter('language_types_info', $language_types);
danielebarchiesi@0 118 }
danielebarchiesi@0 119
danielebarchiesi@0 120 return $language_types;
danielebarchiesi@0 121 }
danielebarchiesi@0 122
danielebarchiesi@0 123 /**
danielebarchiesi@0 124 * Returns only the configurable language types.
danielebarchiesi@0 125 *
danielebarchiesi@0 126 * A language type maybe configurable or fixed. A fixed language type is a type
danielebarchiesi@0 127 * whose language negotiation providers are module-defined and not altered
danielebarchiesi@0 128 * through the user interface.
danielebarchiesi@0 129 *
danielebarchiesi@0 130 * @param $stored
danielebarchiesi@0 131 * Optional. By default retrieves values from the 'language_types' variable to
danielebarchiesi@0 132 * avoid unnecessary hook invocations.
danielebarchiesi@0 133 * If set to FALSE retrieves values from the actual language type definitions.
danielebarchiesi@0 134 * This allows to react to alterations performed on the definitions by modules
danielebarchiesi@0 135 * installed after the 'language_types' variable is set.
danielebarchiesi@0 136 *
danielebarchiesi@0 137 * @return
danielebarchiesi@0 138 * An array of language type names.
danielebarchiesi@0 139 */
danielebarchiesi@0 140 function language_types_configurable($stored = TRUE) {
danielebarchiesi@0 141 $configurable = &drupal_static(__FUNCTION__);
danielebarchiesi@0 142
danielebarchiesi@0 143 if ($stored && !isset($configurable)) {
danielebarchiesi@0 144 $types = variable_get('language_types', drupal_language_types());
danielebarchiesi@0 145 $configurable = array_keys(array_filter($types));
danielebarchiesi@0 146 }
danielebarchiesi@0 147
danielebarchiesi@0 148 if (!$stored) {
danielebarchiesi@0 149 $result = array();
danielebarchiesi@0 150 foreach (language_types_info() as $type => $info) {
danielebarchiesi@0 151 if (!isset($info['fixed'])) {
danielebarchiesi@0 152 $result[] = $type;
danielebarchiesi@0 153 }
danielebarchiesi@0 154 }
danielebarchiesi@0 155 return $result;
danielebarchiesi@0 156 }
danielebarchiesi@0 157
danielebarchiesi@0 158 return $configurable;
danielebarchiesi@0 159 }
danielebarchiesi@0 160
danielebarchiesi@0 161 /**
danielebarchiesi@0 162 * Disables the given language types.
danielebarchiesi@0 163 *
danielebarchiesi@0 164 * @param $types
danielebarchiesi@0 165 * An array of language types.
danielebarchiesi@0 166 */
danielebarchiesi@0 167 function language_types_disable($types) {
danielebarchiesi@0 168 $enabled_types = variable_get('language_types', drupal_language_types());
danielebarchiesi@0 169
danielebarchiesi@0 170 foreach ($types as $type) {
danielebarchiesi@0 171 unset($enabled_types[$type]);
danielebarchiesi@0 172 }
danielebarchiesi@0 173
danielebarchiesi@0 174 variable_set('language_types', $enabled_types);
danielebarchiesi@0 175 }
danielebarchiesi@0 176
danielebarchiesi@0 177 /**
danielebarchiesi@0 178 * Updates the language type configuration.
danielebarchiesi@0 179 */
danielebarchiesi@0 180 function language_types_set() {
danielebarchiesi@0 181 // Ensure that we are getting the defined language negotiation information. An
danielebarchiesi@0 182 // invocation of module_enable() or module_disable() could outdate the cached
danielebarchiesi@0 183 // information.
danielebarchiesi@0 184 drupal_static_reset('language_types_info');
danielebarchiesi@0 185 drupal_static_reset('language_negotiation_info');
danielebarchiesi@0 186
danielebarchiesi@0 187 // Determine which language types are configurable and which not by checking
danielebarchiesi@0 188 // whether the 'fixed' key is defined. Non-configurable (fixed) language types
danielebarchiesi@0 189 // have their language negotiation settings stored there.
danielebarchiesi@0 190 $defined_providers = language_negotiation_info();
danielebarchiesi@0 191 foreach (language_types_info() as $type => $info) {
danielebarchiesi@0 192 if (isset($info['fixed'])) {
danielebarchiesi@0 193 $language_types[$type] = FALSE;
danielebarchiesi@0 194 $negotiation = array();
danielebarchiesi@0 195 foreach ($info['fixed'] as $weight => $id) {
danielebarchiesi@0 196 if (isset($defined_providers[$id])) {
danielebarchiesi@0 197 $negotiation[$id] = $weight;
danielebarchiesi@0 198 }
danielebarchiesi@0 199 }
danielebarchiesi@0 200 language_negotiation_set($type, $negotiation);
danielebarchiesi@0 201 }
danielebarchiesi@0 202 else {
danielebarchiesi@0 203 $language_types[$type] = TRUE;
danielebarchiesi@0 204 }
danielebarchiesi@0 205 }
danielebarchiesi@0 206
danielebarchiesi@0 207 // Save language types.
danielebarchiesi@0 208 variable_set('language_types', $language_types);
danielebarchiesi@0 209
danielebarchiesi@0 210 // Ensure that subsequent calls of language_types_configurable() return the
danielebarchiesi@0 211 // updated language type information.
danielebarchiesi@0 212 drupal_static_reset('language_types_configurable');
danielebarchiesi@0 213 }
danielebarchiesi@0 214
danielebarchiesi@0 215 /**
danielebarchiesi@0 216 * Checks whether a language negotiation provider is enabled for a language type.
danielebarchiesi@0 217 *
danielebarchiesi@0 218 * This has two possible behaviors:
danielebarchiesi@0 219 * - If $provider_id is given return its ID if enabled, FALSE otherwise.
danielebarchiesi@0 220 * - If no ID is passed the first enabled language negotiation provider is
danielebarchiesi@0 221 * returned.
danielebarchiesi@0 222 *
danielebarchiesi@0 223 * @param $type
danielebarchiesi@0 224 * The language negotiation provider type.
danielebarchiesi@0 225 * @param $provider_id
danielebarchiesi@0 226 * The language negotiation provider ID.
danielebarchiesi@0 227 *
danielebarchiesi@0 228 * @return
danielebarchiesi@0 229 * The provider ID if it is enabled, FALSE otherwise.
danielebarchiesi@0 230 */
danielebarchiesi@0 231 function language_negotiation_get($type, $provider_id = NULL) {
danielebarchiesi@0 232 $negotiation = variable_get("language_negotiation_$type", array());
danielebarchiesi@0 233
danielebarchiesi@0 234 if (empty($negotiation)) {
danielebarchiesi@0 235 return empty($provider_id) ? LANGUAGE_NEGOTIATION_DEFAULT : FALSE;
danielebarchiesi@0 236 }
danielebarchiesi@0 237
danielebarchiesi@0 238 if (empty($provider_id)) {
danielebarchiesi@0 239 return key($negotiation);
danielebarchiesi@0 240 }
danielebarchiesi@0 241
danielebarchiesi@0 242 if (isset($negotiation[$provider_id])) {
danielebarchiesi@0 243 return $provider_id;
danielebarchiesi@0 244 }
danielebarchiesi@0 245
danielebarchiesi@0 246 return FALSE;
danielebarchiesi@0 247 }
danielebarchiesi@0 248
danielebarchiesi@0 249 /**
danielebarchiesi@0 250 * Checks if the language negotiation provider is enabled for any language type.
danielebarchiesi@0 251 *
danielebarchiesi@0 252 * @param $provider_id
danielebarchiesi@0 253 * The language negotiation provider ID.
danielebarchiesi@0 254 *
danielebarchiesi@0 255 * @return
danielebarchiesi@0 256 * TRUE if there is at least one language type for which the given language
danielebarchiesi@0 257 * provider is enabled, FALSE otherwise.
danielebarchiesi@0 258 */
danielebarchiesi@0 259 function language_negotiation_get_any($provider_id) {
danielebarchiesi@0 260 foreach (language_types_configurable() as $type) {
danielebarchiesi@0 261 if (language_negotiation_get($type, $provider_id)) {
danielebarchiesi@0 262 return TRUE;
danielebarchiesi@0 263 }
danielebarchiesi@0 264 }
danielebarchiesi@0 265
danielebarchiesi@0 266 return FALSE;
danielebarchiesi@0 267 }
danielebarchiesi@0 268
danielebarchiesi@0 269 /**
danielebarchiesi@0 270 * Returns the language switch links for the given language.
danielebarchiesi@0 271 *
danielebarchiesi@0 272 * @param $type
danielebarchiesi@0 273 * The language negotiation type.
danielebarchiesi@0 274 * @param $path
danielebarchiesi@0 275 * The internal path the switch links will be relative to.
danielebarchiesi@0 276 *
danielebarchiesi@0 277 * @return
danielebarchiesi@0 278 * A keyed array of links ready to be themed.
danielebarchiesi@0 279 */
danielebarchiesi@0 280 function language_negotiation_get_switch_links($type, $path) {
danielebarchiesi@0 281 $links = FALSE;
danielebarchiesi@0 282 $negotiation = variable_get("language_negotiation_$type", array());
danielebarchiesi@0 283
danielebarchiesi@0 284 // Only get the languages if we have more than one.
danielebarchiesi@0 285 if (count(language_list()) >= 2) {
danielebarchiesi@0 286 $language = language_initialize($type);
danielebarchiesi@0 287 }
danielebarchiesi@0 288
danielebarchiesi@0 289 foreach ($negotiation as $id => $provider) {
danielebarchiesi@0 290 if (isset($provider['callbacks']['switcher'])) {
danielebarchiesi@0 291 if (isset($provider['file'])) {
danielebarchiesi@0 292 require_once DRUPAL_ROOT . '/' . $provider['file'];
danielebarchiesi@0 293 }
danielebarchiesi@0 294
danielebarchiesi@0 295 $callback = $provider['callbacks']['switcher'];
danielebarchiesi@0 296 $result = $callback($type, $path);
danielebarchiesi@0 297
danielebarchiesi@0 298 // Add support for WCAG 2.0's Language of Parts to add language identifiers.
danielebarchiesi@0 299 // http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-other-lang-id.html
danielebarchiesi@0 300 foreach ($result as $langcode => $link) {
danielebarchiesi@0 301 $result[$langcode]['attributes']['lang'] = $langcode;
danielebarchiesi@0 302 }
danielebarchiesi@0 303
danielebarchiesi@0 304 if (!empty($result)) {
danielebarchiesi@0 305 // Allow modules to provide translations for specific links.
danielebarchiesi@0 306 drupal_alter('language_switch_links', $result, $type, $path);
danielebarchiesi@0 307 $links = (object) array('links' => $result, 'provider' => $id);
danielebarchiesi@0 308 break;
danielebarchiesi@0 309 }
danielebarchiesi@0 310 }
danielebarchiesi@0 311 }
danielebarchiesi@0 312
danielebarchiesi@0 313 return $links;
danielebarchiesi@0 314 }
danielebarchiesi@0 315
danielebarchiesi@0 316 /**
danielebarchiesi@0 317 * Removes any unused language negotation providers from the configuration.
danielebarchiesi@0 318 */
danielebarchiesi@0 319 function language_negotiation_purge() {
danielebarchiesi@0 320 // Ensure that we are getting the defined language negotiation information. An
danielebarchiesi@0 321 // invocation of module_enable() or module_disable() could outdate the cached
danielebarchiesi@0 322 // information.
danielebarchiesi@0 323 drupal_static_reset('language_negotiation_info');
danielebarchiesi@0 324 drupal_static_reset('language_types_info');
danielebarchiesi@0 325
danielebarchiesi@0 326 $defined_providers = language_negotiation_info();
danielebarchiesi@0 327 foreach (language_types_info() as $type => $type_info) {
danielebarchiesi@0 328 $weight = 0;
danielebarchiesi@0 329 $negotiation = array();
danielebarchiesi@0 330 foreach (variable_get("language_negotiation_$type", array()) as $id => $provider) {
danielebarchiesi@0 331 if (isset($defined_providers[$id])) {
danielebarchiesi@0 332 $negotiation[$id] = $weight++;
danielebarchiesi@0 333 }
danielebarchiesi@0 334 }
danielebarchiesi@0 335 language_negotiation_set($type, $negotiation);
danielebarchiesi@0 336 }
danielebarchiesi@0 337 }
danielebarchiesi@0 338
danielebarchiesi@0 339 /**
danielebarchiesi@0 340 * Saves a list of language negotiation providers.
danielebarchiesi@0 341 *
danielebarchiesi@0 342 * @param $type
danielebarchiesi@0 343 * The language negotiation type.
danielebarchiesi@0 344 * @param $language_providers
danielebarchiesi@0 345 * An array of language negotiation provider weights keyed by provider ID.
danielebarchiesi@0 346 * @see language_provider_weight()
danielebarchiesi@0 347 */
danielebarchiesi@0 348 function language_negotiation_set($type, $language_providers) {
danielebarchiesi@0 349 // Save only the necessary fields.
danielebarchiesi@0 350 $provider_fields = array('callbacks', 'file', 'cache');
danielebarchiesi@0 351
danielebarchiesi@0 352 $negotiation = array();
danielebarchiesi@0 353 $providers_weight = array();
danielebarchiesi@0 354 $defined_providers = language_negotiation_info();
danielebarchiesi@0 355 $default_types = language_types_configurable(FALSE);
danielebarchiesi@0 356
danielebarchiesi@0 357 // Initialize the providers weight list.
danielebarchiesi@0 358 foreach ($language_providers as $id => $provider) {
danielebarchiesi@0 359 $providers_weight[$id] = language_provider_weight($provider);
danielebarchiesi@0 360 }
danielebarchiesi@0 361
danielebarchiesi@0 362 // Order providers list by weight.
danielebarchiesi@0 363 asort($providers_weight);
danielebarchiesi@0 364
danielebarchiesi@0 365 foreach ($providers_weight as $id => $weight) {
danielebarchiesi@0 366 if (isset($defined_providers[$id])) {
danielebarchiesi@0 367 $provider = $defined_providers[$id];
danielebarchiesi@0 368 // If the provider does not express any preference about types, make it
danielebarchiesi@0 369 // available for any configurable type.
danielebarchiesi@0 370 $types = array_flip(isset($provider['types']) ? $provider['types'] : $default_types);
danielebarchiesi@0 371 // Check whether the provider is defined and has the right type.
danielebarchiesi@0 372 if (isset($types[$type])) {
danielebarchiesi@0 373 $provider_data = array();
danielebarchiesi@0 374 foreach ($provider_fields as $field) {
danielebarchiesi@0 375 if (isset($provider[$field])) {
danielebarchiesi@0 376 $provider_data[$field] = $provider[$field];
danielebarchiesi@0 377 }
danielebarchiesi@0 378 }
danielebarchiesi@0 379 $negotiation[$id] = $provider_data;
danielebarchiesi@0 380 }
danielebarchiesi@0 381 }
danielebarchiesi@0 382 }
danielebarchiesi@0 383
danielebarchiesi@0 384 variable_set("language_negotiation_$type", $negotiation);
danielebarchiesi@0 385 }
danielebarchiesi@0 386
danielebarchiesi@0 387 /**
danielebarchiesi@0 388 * Returns all the defined language negotiation providers.
danielebarchiesi@0 389 *
danielebarchiesi@0 390 * @return
danielebarchiesi@0 391 * An array of language negotiation providers.
danielebarchiesi@0 392 */
danielebarchiesi@0 393 function language_negotiation_info() {
danielebarchiesi@0 394 $language_providers = &drupal_static(__FUNCTION__);
danielebarchiesi@0 395
danielebarchiesi@0 396 if (!isset($language_providers)) {
danielebarchiesi@0 397 // Collect all the module-defined language negotiation providers.
danielebarchiesi@0 398 $language_providers = module_invoke_all('language_negotiation_info');
danielebarchiesi@0 399
danielebarchiesi@0 400 // Add the default language negotiation provider.
danielebarchiesi@0 401 $language_providers[LANGUAGE_NEGOTIATION_DEFAULT] = array(
danielebarchiesi@0 402 'callbacks' => array('language' => 'language_from_default'),
danielebarchiesi@0 403 'weight' => 10,
danielebarchiesi@0 404 'name' => t('Default'),
danielebarchiesi@0 405 'description' => t('Use the default site language (@language_name).', array('@language_name' => language_default()->native)),
danielebarchiesi@0 406 );
danielebarchiesi@0 407
danielebarchiesi@0 408 // Let other modules alter the list of language negotiation providers.
danielebarchiesi@0 409 drupal_alter('language_negotiation_info', $language_providers);
danielebarchiesi@0 410 }
danielebarchiesi@0 411
danielebarchiesi@0 412 return $language_providers;
danielebarchiesi@0 413 }
danielebarchiesi@0 414
danielebarchiesi@0 415 /**
danielebarchiesi@0 416 * Helper function used to cache the language negotiation providers results.
danielebarchiesi@0 417 *
danielebarchiesi@0 418 * @param $provider_id
danielebarchiesi@0 419 * The language negotiation provider's identifier.
danielebarchiesi@0 420 * @param $provider
danielebarchiesi@0 421 * (optional) An associative array of information about the provider to be
danielebarchiesi@0 422 * invoked (see hook_language_negotiation_info() for details). If not passed
danielebarchiesi@0 423 * in, it will be loaded through language_negotiation_info().
danielebarchiesi@0 424 *
danielebarchiesi@0 425 * @return
danielebarchiesi@0 426 * A language object representing the language chosen by the provider.
danielebarchiesi@0 427 */
danielebarchiesi@0 428 function language_provider_invoke($provider_id, $provider = NULL) {
danielebarchiesi@0 429 $results = &drupal_static(__FUNCTION__);
danielebarchiesi@0 430
danielebarchiesi@0 431 if (!isset($results[$provider_id])) {
danielebarchiesi@0 432 global $user;
danielebarchiesi@0 433
danielebarchiesi@0 434 // Get languages grouped by status and select only the enabled ones.
danielebarchiesi@0 435 $languages = language_list('enabled');
danielebarchiesi@0 436 $languages = $languages[1];
danielebarchiesi@0 437
danielebarchiesi@0 438 if (!isset($provider)) {
danielebarchiesi@0 439 $providers = language_negotiation_info();
danielebarchiesi@0 440 $provider = $providers[$provider_id];
danielebarchiesi@0 441 }
danielebarchiesi@0 442
danielebarchiesi@0 443 if (isset($provider['file'])) {
danielebarchiesi@0 444 require_once DRUPAL_ROOT . '/' . $provider['file'];
danielebarchiesi@0 445 }
danielebarchiesi@0 446
danielebarchiesi@0 447 // If the language negotiation provider has no cache preference or this is
danielebarchiesi@0 448 // satisfied we can execute the callback.
danielebarchiesi@0 449 $cache = !isset($provider['cache']) || $user->uid || $provider['cache'] == variable_get('cache', 0);
danielebarchiesi@0 450 $callback = isset($provider['callbacks']['language']) ? $provider['callbacks']['language'] : FALSE;
danielebarchiesi@0 451 $langcode = $cache && function_exists($callback) ? $callback($languages) : FALSE;
danielebarchiesi@0 452 $results[$provider_id] = isset($languages[$langcode]) ? $languages[$langcode] : FALSE;
danielebarchiesi@0 453 }
danielebarchiesi@0 454
danielebarchiesi@0 455 // Since objects are resources, we need to return a clone to prevent the
danielebarchiesi@0 456 // language negotiation provider cache from being unintentionally altered. The
danielebarchiesi@0 457 // same providers might be used with different language types based on
danielebarchiesi@0 458 // configuration.
danielebarchiesi@0 459 return !empty($results[$provider_id]) ? clone($results[$provider_id]) : $results[$provider_id];
danielebarchiesi@0 460 }
danielebarchiesi@0 461
danielebarchiesi@0 462 /**
danielebarchiesi@0 463 * Returns the passed language negotiation provider weight or a default value.
danielebarchiesi@0 464 *
danielebarchiesi@0 465 * @param $provider
danielebarchiesi@0 466 * A language negotiation provider data structure.
danielebarchiesi@0 467 *
danielebarchiesi@0 468 * @return
danielebarchiesi@0 469 * A numeric weight.
danielebarchiesi@0 470 */
danielebarchiesi@0 471 function language_provider_weight($provider) {
danielebarchiesi@0 472 $default = is_numeric($provider) ? $provider : 0;
danielebarchiesi@0 473 return isset($provider['weight']) && is_numeric($provider['weight']) ? $provider['weight'] : $default;
danielebarchiesi@0 474 }
danielebarchiesi@0 475
danielebarchiesi@0 476 /**
danielebarchiesi@0 477 * Chooses a language based on language negotiation provider settings.
danielebarchiesi@0 478 *
danielebarchiesi@0 479 * @param $type
danielebarchiesi@0 480 * The language type key to find the language for.
danielebarchiesi@0 481 *
danielebarchiesi@0 482 * @return
danielebarchiesi@0 483 * The negotiated language object.
danielebarchiesi@0 484 */
danielebarchiesi@0 485 function language_initialize($type) {
danielebarchiesi@0 486 // Execute the language negotiation providers in the order they were set up and return the
danielebarchiesi@0 487 // first valid language found.
danielebarchiesi@0 488 $negotiation = variable_get("language_negotiation_$type", array());
danielebarchiesi@0 489
danielebarchiesi@0 490 foreach ($negotiation as $provider_id => $provider) {
danielebarchiesi@0 491 $language = language_provider_invoke($provider_id, $provider);
danielebarchiesi@0 492 if ($language) {
danielebarchiesi@0 493 $language->provider = $provider_id;
danielebarchiesi@0 494 return $language;
danielebarchiesi@0 495 }
danielebarchiesi@0 496 }
danielebarchiesi@0 497
danielebarchiesi@0 498 // If no other language was found use the default one.
danielebarchiesi@0 499 $language = language_default();
danielebarchiesi@0 500 $language->provider = LANGUAGE_NEGOTIATION_DEFAULT;
danielebarchiesi@0 501 return $language;
danielebarchiesi@0 502 }
danielebarchiesi@0 503
danielebarchiesi@0 504 /**
danielebarchiesi@0 505 * Returns the default language negotiation provider.
danielebarchiesi@0 506 *
danielebarchiesi@0 507 * @return
danielebarchiesi@0 508 * The default language code.
danielebarchiesi@0 509 */
danielebarchiesi@0 510 function language_from_default() {
danielebarchiesi@0 511 return language_default()->language;
danielebarchiesi@0 512 }
danielebarchiesi@0 513
danielebarchiesi@0 514 /**
danielebarchiesi@0 515 * Splits the given path into prefix and actual path.
danielebarchiesi@0 516 *
danielebarchiesi@0 517 * Parse the given path and return the language object identified by the prefix
danielebarchiesi@0 518 * and the actual path.
danielebarchiesi@0 519 *
danielebarchiesi@0 520 * @param $path
danielebarchiesi@0 521 * The path to split.
danielebarchiesi@0 522 * @param $languages
danielebarchiesi@0 523 * An array of valid languages.
danielebarchiesi@0 524 *
danielebarchiesi@0 525 * @return
danielebarchiesi@0 526 * An array composed of:
danielebarchiesi@0 527 * - A language object corresponding to the identified prefix on success,
danielebarchiesi@0 528 * FALSE otherwise.
danielebarchiesi@0 529 * - The path without the prefix on success, the given path otherwise.
danielebarchiesi@0 530 */
danielebarchiesi@0 531 function language_url_split_prefix($path, $languages) {
danielebarchiesi@0 532 $args = empty($path) ? array() : explode('/', $path);
danielebarchiesi@0 533 $prefix = array_shift($args);
danielebarchiesi@0 534
danielebarchiesi@0 535 // Search prefix within enabled languages.
danielebarchiesi@0 536 foreach ($languages as $language) {
danielebarchiesi@0 537 if (!empty($language->prefix) && $language->prefix == $prefix) {
danielebarchiesi@0 538 // Rebuild $path with the language removed.
danielebarchiesi@0 539 return array($language, implode('/', $args));
danielebarchiesi@0 540 }
danielebarchiesi@0 541 }
danielebarchiesi@0 542
danielebarchiesi@0 543 return array(FALSE, $path);
danielebarchiesi@0 544 }
danielebarchiesi@0 545
danielebarchiesi@0 546 /**
danielebarchiesi@0 547 * Returns the possible fallback languages ordered by language weight.
danielebarchiesi@0 548 *
danielebarchiesi@0 549 * @param
danielebarchiesi@0 550 * (optional) The language type. Defaults to LANGUAGE_TYPE_CONTENT.
danielebarchiesi@0 551 *
danielebarchiesi@0 552 * @return
danielebarchiesi@0 553 * An array of language codes.
danielebarchiesi@0 554 */
danielebarchiesi@0 555 function language_fallback_get_candidates($type = LANGUAGE_TYPE_CONTENT) {
danielebarchiesi@0 556 $fallback_candidates = &drupal_static(__FUNCTION__);
danielebarchiesi@0 557
danielebarchiesi@0 558 if (!isset($fallback_candidates)) {
danielebarchiesi@0 559 $fallback_candidates = array();
danielebarchiesi@0 560
danielebarchiesi@0 561 // Get languages ordered by weight.
danielebarchiesi@0 562 // Use array keys to avoid duplicated entries.
danielebarchiesi@0 563 foreach (language_list('weight') as $languages) {
danielebarchiesi@0 564 foreach ($languages as $language) {
danielebarchiesi@0 565 $fallback_candidates[$language->language] = NULL;
danielebarchiesi@0 566 }
danielebarchiesi@0 567 }
danielebarchiesi@0 568
danielebarchiesi@0 569 $fallback_candidates = array_keys($fallback_candidates);
danielebarchiesi@0 570 $fallback_candidates[] = LANGUAGE_NONE;
danielebarchiesi@0 571
danielebarchiesi@0 572 // Let other modules hook in and add/change candidates.
danielebarchiesi@0 573 drupal_alter('language_fallback_candidates', $fallback_candidates);
danielebarchiesi@0 574 }
danielebarchiesi@0 575
danielebarchiesi@0 576 return $fallback_candidates;
danielebarchiesi@0 577 }
danielebarchiesi@0 578
danielebarchiesi@0 579 /**
danielebarchiesi@0 580 * @} End of "language_negotiation"
danielebarchiesi@0 581 */