1 |
85ad3d82
|
Assos Assos
|
<?php
|
2 |
|
|
|
3 |
|
|
/**
|
4 |
|
|
* @file
|
5 |
|
|
* Internationalization (i18n) module - Field handling
|
6 |
|
|
*
|
7 |
|
|
* For string keys we use:
|
8 |
|
|
* - field:[field_name]:[bundle]:property, when it is an instance property (linked to bundle)
|
9 |
|
|
* - field:[field_name]:#property..., when it is a field property (that may have multiple values)
|
10 |
|
|
*/
|
11 |
|
|
|
12 |
|
|
/**
|
13 |
|
|
* Implements hook_menu().
|
14 |
|
|
*/
|
15 |
|
|
function i18n_field_menu() {
|
16 |
|
|
$items = array();
|
17 |
|
|
|
18 |
|
|
// Ensure the following is not executed until field_bundles is working and
|
19 |
|
|
// tables are updated. Needed to avoid errors on initial installation.
|
20 |
|
|
if (!module_exists('field_ui') || defined('MAINTENANCE_MODE')) {
|
21 |
|
|
return $items;
|
22 |
|
|
}
|
23 |
|
|
|
24 |
|
|
// Create tabs for all possible bundles. From field_ui_menu().
|
25 |
|
|
foreach (entity_get_info() as $entity_type => $entity_info) {
|
26 |
|
|
if ($entity_info['fieldable']) {
|
27 |
|
|
foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) {
|
28 |
|
|
if (isset($bundle_info['admin'])) {
|
29 |
|
|
// Extract path information from the bundle.
|
30 |
|
|
$path = $bundle_info['admin']['path'];
|
31 |
|
|
// Different bundles can appear on the same path (e.g. %node_type and
|
32 |
|
|
// %comment_node_type). To allow field_ui_menu_load() to extract the
|
33 |
|
|
// actual bundle object from the translated menu router path
|
34 |
|
|
// arguments, we need to identify the argument position of the bundle
|
35 |
|
|
// name string ('bundle argument') and pass that position to the menu
|
36 |
|
|
// loader. The position needs to be casted into a string; otherwise it
|
37 |
|
|
// would be replaced with the bundle name string.
|
38 |
|
|
if (isset($bundle_info['admin']['bundle argument'])) {
|
39 |
|
|
$bundle_arg = $bundle_info['admin']['bundle argument'];
|
40 |
|
|
$bundle_pos = (string) $bundle_arg;
|
41 |
|
|
}
|
42 |
|
|
else {
|
43 |
|
|
$bundle_arg = $bundle_name;
|
44 |
|
|
$bundle_pos = '0';
|
45 |
|
|
}
|
46 |
|
|
// This is the position of the %field_ui_menu placeholder in the
|
47 |
|
|
// items below.
|
48 |
|
|
$field_position = count(explode('/', $path)) + 1;
|
49 |
|
|
|
50 |
|
|
// Extract access information, providing defaults.
|
51 |
|
|
$access = array_intersect_key($bundle_info['admin'], drupal_map_assoc(array('access callback', 'access arguments')));
|
52 |
|
|
$access += array(
|
53 |
|
|
'access callback' => 'user_access',
|
54 |
|
|
'access arguments' => array('administer site configuration'),
|
55 |
|
|
);
|
56 |
|
|
$items["$path/fields/%field_ui_menu/translate"] = array(
|
57 |
|
|
'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'),
|
58 |
|
|
'title' => 'Translate',
|
59 |
|
|
'page callback' => 'i18n_field_page_translate',
|
60 |
|
|
'page arguments' => array($field_position),
|
61 |
|
|
'file' => 'i18n_field.pages.inc',
|
62 |
|
|
'type' => MENU_LOCAL_TASK,
|
63 |
|
|
) + $access;
|
64 |
|
|
|
65 |
|
|
$items["$path/fields/%field_ui_menu/translate/%i18n_language"] = array(
|
66 |
|
|
'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'),
|
67 |
|
|
'title' => 'Instance',
|
68 |
|
|
'page callback' => 'i18n_field_page_translate',
|
69 |
|
|
'page arguments' => array($field_position, $field_position + 2),
|
70 |
|
|
'file' => 'i18n_field.pages.inc',
|
71 |
|
|
'type' => MENU_CALLBACK,
|
72 |
|
|
) + $access;
|
73 |
|
|
}
|
74 |
|
|
}
|
75 |
|
|
}
|
76 |
|
|
}
|
77 |
|
|
return $items;
|
78 |
|
|
}
|
79 |
|
|
|
80 |
|
|
/**
|
81 |
|
|
* Implements hook_hook_info().
|
82 |
|
|
*/
|
83 |
|
|
function i18n_field_hook_info() {
|
84 |
|
|
$hooks['i18n_field_info'] = array(
|
85 |
|
|
'group' => 'i18n',
|
86 |
|
|
);
|
87 |
|
|
return $hooks;
|
88 |
|
|
}
|
89 |
|
|
|
90 |
|
|
/**
|
91 |
|
|
* Implements hook_field_attach_form().
|
92 |
|
|
*
|
93 |
|
|
* After the form fields are built. Translate title and description for fields with multiple values.
|
94 |
|
|
*/
|
95 |
|
|
function i18n_field_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
|
96 |
|
|
// Determine the list of instances to iterate on.
|
97 |
|
|
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
|
98 |
|
|
$instances = field_info_instances($entity_type, $bundle);
|
99 |
|
|
foreach ($instances as $field_name => $instance) {
|
100 |
|
|
if (isset($form[$field_name])) {
|
101 |
|
|
$langcode = $form[$field_name]['#language'];
|
102 |
|
|
$field = &$form[$field_name];
|
103 |
|
|
// Note: cardinality for unlimited fields is -1
|
104 |
|
|
if (isset($field[$langcode]['#cardinality']) && $field[$langcode]['#cardinality'] != 1) {
|
105 |
|
|
$translated = i18n_string_object_translate('field_instance', $instance);
|
106 |
|
|
if (!empty($field[$langcode]['#title'])) {
|
107 |
|
|
$field[$langcode]['#title'] = $translated['label'];
|
108 |
|
|
}
|
109 |
|
|
if (!empty($field[$langcode]['#description'])) {
|
110 |
|
|
$field[$langcode]['#description'] = $translated['description'];
|
111 |
|
|
}
|
112 |
|
|
}
|
113 |
|
|
}
|
114 |
|
|
}
|
115 |
|
|
}
|
116 |
|
|
|
117 |
|
|
/**
|
118 |
|
|
* Implements hook_field_formatter_info().
|
119 |
|
|
*/
|
120 |
|
|
function i18n_field_field_formatter_info() {
|
121 |
|
|
$types = array();
|
122 |
|
|
foreach (i18n_field_type_info() as $type => $info) {
|
123 |
|
|
if (!empty($info['translate_options'])) {
|
124 |
|
|
$types[] = $type;
|
125 |
|
|
}
|
126 |
|
|
}
|
127 |
|
|
return array(
|
128 |
|
|
'i18n_list_default' => array(
|
129 |
|
|
'label' => t('Default translated'),
|
130 |
|
|
'field types' => $types,
|
131 |
|
|
),
|
132 |
|
|
);
|
133 |
|
|
}
|
134 |
|
|
|
135 |
|
|
/**
|
136 |
|
|
* Implements hook_field_formatter_view().
|
137 |
|
|
*/
|
138 |
|
|
function i18n_field_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
|
139 |
|
|
$element = array();
|
140 |
|
|
|
141 |
|
|
switch ($display['type']) {
|
142 |
|
|
case 'i18n_list_default':
|
143 |
|
|
if (($translate = i18n_field_type_info($field['type'], 'translate_options'))) {
|
144 |
|
|
$allowed_values = $translate($field);
|
145 |
|
|
}
|
146 |
|
|
else {
|
147 |
|
|
// Defaults to list_default behavior
|
148 |
|
|
$allowed_values = list_allowed_values($field);
|
149 |
|
|
}
|
150 |
|
|
foreach ($items as $delta => $item) {
|
151 |
|
|
if (isset($allowed_values[$item['value']])) {
|
152 |
|
|
$output = field_filter_xss($allowed_values[$item['value']]);
|
153 |
|
|
}
|
154 |
|
|
else {
|
155 |
|
|
// If no match was found in allowed values, fall back to the key.
|
156 |
|
|
$output = field_filter_xss($item['value']);
|
157 |
|
|
}
|
158 |
|
|
$element[$delta] = array('#markup' => $output);
|
159 |
|
|
}
|
160 |
|
|
break;
|
161 |
|
|
}
|
162 |
|
|
|
163 |
|
|
return $element;
|
164 |
|
|
}
|
165 |
|
|
|
166 |
|
|
/**
|
167 |
|
|
* Implements hook_field_widget_form_alter().
|
168 |
|
|
*
|
169 |
|
|
* Translate:
|
170 |
|
|
* - Title (label)
|
171 |
|
|
* - Description (help)
|
172 |
|
|
* - Default value
|
173 |
|
|
* - List options
|
174 |
|
|
*/
|
175 |
|
|
function i18n_field_field_widget_form_alter(&$element, &$form_state, $context) {
|
176 |
|
|
global $language;
|
177 |
|
|
|
178 |
|
|
// Don't translate if the widget is being shown on the field edit form.
|
179 |
9faa5de0
|
Assos Assos
|
if (isset($form_state['build_info']['form_id']) && $form_state['build_info']['form_id'] == 'field_ui_field_edit_form') {
|
180 |
85ad3d82
|
Assos Assos
|
return;
|
181 |
|
|
}
|
182 |
|
|
|
183 |
|
|
// Skip if we are missing any of the parameters
|
184 |
|
|
if (empty($context['field']) || empty($context['instance']) || empty($context['langcode'])) {
|
185 |
|
|
return;
|
186 |
|
|
}
|
187 |
|
|
$field = $context['field'];
|
188 |
|
|
$instance = $context['instance'];
|
189 |
|
|
$langcode = $context['langcode'];
|
190 |
|
|
|
191 |
|
|
// Get the element to alter. Account for inconsistencies in how the element
|
192 |
|
|
// is built for different field types.
|
193 |
|
|
if (isset($element[0]) && count($element) == 1) {
|
194 |
|
|
// Single-value file fields and image fields.
|
195 |
|
|
$alter_element = &$element[0];
|
196 |
|
|
}
|
197 |
01f36513
|
Assos Assos
|
elseif ($field['type'] == 'url' && $field['module'] == 'url' && $field['cardinality'] == 1) {
|
198 |
|
|
$alter_element = &$element;
|
199 |
|
|
}
|
200 |
85ad3d82
|
Assos Assos
|
elseif (isset($element['value'])) {
|
201 |
|
|
// Number fields. Single-value text fields.
|
202 |
|
|
$alter_element = &$element['value'];
|
203 |
|
|
}
|
204 |
|
|
elseif ($field['type'] == 'entityreference' && isset($element['target_id'])) {
|
205 |
|
|
// Entityreference fields using the entityreference_autocomplete widget.
|
206 |
|
|
$alter_element = &$element['target_id'];
|
207 |
|
|
}
|
208 |
e013fa40
|
Assos Assos
|
elseif ($field['type'] == 'node_reference' && isset($element['nid'])) {
|
209 |
|
|
// The node_reference fields using the entityreference_autocomplete widget.
|
210 |
|
|
$alter_element = &$element['nid'];
|
211 |
|
|
}
|
212 |
85ad3d82
|
Assos Assos
|
else {
|
213 |
|
|
// All other fields.
|
214 |
|
|
$alter_element = &$element;
|
215 |
|
|
}
|
216 |
|
|
|
217 |
|
|
// If a subelement has the same title as the parent, translate it instead.
|
218 |
|
|
// Allows fields such as email and commerce_price to be translated.
|
219 |
|
|
foreach (element_get_visible_children($element) as $key) {
|
220 |
|
|
$single_value = ($field['cardinality'] == 1);
|
221 |
|
|
$has_title = (isset($element['#title']) && isset($element[$key]['#title']));
|
222 |
|
|
if ($single_value && $has_title && $element[$key]['#title'] == $element['#title']) {
|
223 |
|
|
$alter_element = &$element[$key];
|
224 |
|
|
break;
|
225 |
|
|
}
|
226 |
|
|
}
|
227 |
|
|
|
228 |
|
|
// The field language may affect some variables (default) but not others (description will be in current page language)
|
229 |
|
|
$i18n_langcode = empty($alter_element['#language']) || $alter_element['#language'] == LANGUAGE_NONE ? $language->language : $alter_element['#language'];
|
230 |
|
|
|
231 |
|
|
// Translate instance to current page language and set to form_state
|
232 |
|
|
// so it will be used for validation messages later.
|
233 |
|
|
$instance_current = i18n_string_object_translate('field_instance', $instance);
|
234 |
|
|
if (isset($form_state['field'][$instance['field_name']][$langcode]['instance'])) {
|
235 |
|
|
$form_state['field'][$instance['field_name']][$langcode]['instance'] = $instance_current;
|
236 |
|
|
}
|
237 |
|
|
|
238 |
|
|
// Translate field title if set and it is the default one.
|
239 |
|
|
if (!empty($instance_current['label']) && $instance_current['label'] != $instance['label']) {
|
240 |
|
|
if (!empty($alter_element['#title']) && $alter_element['#title'] == check_plain($instance['label'])) {
|
241 |
|
|
$alter_element['#title'] = check_plain($instance_current['label']);
|
242 |
|
|
}
|
243 |
|
|
}
|
244 |
|
|
|
245 |
|
|
// Translate field description if set and it is the default one.
|
246 |
|
|
if (!empty($instance_current['description']) && $instance_current['description'] != $instance['description']) {
|
247 |
|
|
if (!empty($alter_element['#description'])) {
|
248 |
|
|
// Allow single-value file fields and image fields to have their
|
249 |
|
|
// descriptions translated. file_field_widget_form() passes the
|
250 |
|
|
// description through theme('file_upload_help'), so i18n_field
|
251 |
|
|
// must do the same.
|
252 |
|
|
$filefield = in_array($field['type'], array('file', 'image'));
|
253 |
|
|
$single_value = ($field['cardinality'] == 1);
|
254 |
|
|
$no_default = empty($alter_element['#default_value']['fid']);
|
255 |
|
|
if ($filefield && $single_value && $no_default) {
|
256 |
|
|
$help_variables = array(
|
257 |
|
|
'description' => field_filter_xss($instance['description']),
|
258 |
e4c061ad
|
Assos Assos
|
'upload_validators' => isset($alter_element['#upload_validators']) ? $alter_element['#upload_validators'] : array(),
|
259 |
85ad3d82
|
Assos Assos
|
);
|
260 |
|
|
$original_description = theme('file_upload_help', $help_variables);
|
261 |
|
|
if ($alter_element['#description'] == $original_description) {
|
262 |
|
|
$help_variables = array(
|
263 |
|
|
'description' => field_filter_xss($instance_current['description']),
|
264 |
e4c061ad
|
Assos Assos
|
'upload_validators' => isset($alter_element['#upload_validators']) ? $alter_element['#upload_validators'] : array(),
|
265 |
85ad3d82
|
Assos Assos
|
);
|
266 |
|
|
$alter_element['#description'] = theme('file_upload_help', $help_variables);
|
267 |
|
|
}
|
268 |
|
|
}
|
269 |
|
|
elseif ($alter_element['#description'] == field_filter_xss($instance['description'])) {
|
270 |
|
|
$alter_element['#description'] = field_filter_xss($instance_current['description']);
|
271 |
|
|
}
|
272 |
|
|
}
|
273 |
|
|
}
|
274 |
|
|
|
275 |
|
|
// Translate list options.
|
276 |
|
|
$has_options = (!empty($alter_element['#options']) || $field['type'] == 'list_boolean');
|
277 |
|
|
$has_allowed_values = !empty($field['settings']['allowed_values']);
|
278 |
|
|
$translate = i18n_field_type_info($field['type'], 'translate_options');
|
279 |
|
|
if ($has_options && $has_allowed_values && $translate) {
|
280 |
|
|
$alter_element['#options'] = $translate($field, $i18n_langcode);
|
281 |
|
|
if (isset($alter_element['#properties']) && !empty($alter_element['#properties']['empty_option'])) {
|
282 |
|
|
$label = theme('options_none', array('instance' => $instance, 'option' => $alter_element['#properties']['empty_option']));
|
283 |
|
|
$alter_element['#options'] = array('_none' => $label) + $alter_element['#options'];
|
284 |
|
|
}
|
285 |
|
|
// Translate list_boolean fields using the checkboxes widget.
|
286 |
|
|
if (!empty($alter_element['#title']) && $field['type'] == 'list_boolean' && !empty($alter_element['#on_value'])) {
|
287 |
|
|
$on_value = $alter_element['#on_value'];
|
288 |
|
|
$alter_element['#options'];
|
289 |
|
|
$alter_element['#title'] = $alter_element['#options'][$on_value];
|
290 |
|
|
// For using label instead of "On value".
|
291 |
|
|
if ($instance['widget']['settings']['display_label']) {
|
292 |
|
|
$alter_element['#title'] = $instance_current['label'];
|
293 |
|
|
}
|
294 |
|
|
}
|
295 |
|
|
}
|
296 |
|
|
|
297 |
|
|
// Check for more parameters, skip this part if missing.
|
298 |
|
|
if (!isset($context['delta']) || !isset($context['items'])) {
|
299 |
|
|
return;
|
300 |
|
|
}
|
301 |
|
|
$delta = $context['delta'];
|
302 |
|
|
$items = $context['items'];
|
303 |
|
|
|
304 |
|
|
// Translate default value.
|
305 |
|
|
$has_default_value = (isset($alter_element['#default_value']) && !empty($instance['default_value'][$delta]['value']));
|
306 |
|
|
$storage_has_value = !empty($items[$delta]['value']);
|
307 |
|
|
$translate = i18n_field_type_info($field['type'], 'translate_default');
|
308 |
|
|
if ($has_default_value && $storage_has_value && $translate) {
|
309 |
|
|
// Compare the default value with the value currently in storage.
|
310 |
|
|
if ($instance['default_value'][$delta]['value'] === $items[$delta]['value']) {
|
311 |
|
|
$alter_element['#default_value'] = $translate($instance, $items[$delta]['value'], $i18n_langcode);
|
312 |
|
|
}
|
313 |
|
|
}
|
314 |
|
|
}
|
315 |
|
|
|
316 |
|
|
/**
|
317 |
|
|
* Implements hook_field_attach_view_alter().
|
318 |
|
|
*/
|
319 |
|
|
function i18n_field_field_attach_view_alter(&$output, $context) {
|
320 |
|
|
foreach (element_children($output) as $field_name) {
|
321 |
|
|
$element = &$output[$field_name];
|
322 |
|
|
if (!empty($element['#entity_type']) && !empty($element['#field_name']) && !empty($element['#bundle'])) {
|
323 |
|
|
$instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
|
324 |
|
|
|
325 |
|
|
// Translate field title if set
|
326 |
|
|
if (!empty($instance['label'])) {
|
327 |
|
|
$element['#title'] = i18n_field_translate_property($instance, 'label');
|
328 |
|
|
}
|
329 |
|
|
|
330 |
|
|
// Translate field description if set
|
331 |
|
|
if (!empty($instance['description'])) {
|
332 |
|
|
$element['#description'] = i18n_field_translate_property($instance, 'description');
|
333 |
|
|
}
|
334 |
|
|
}
|
335 |
|
|
}
|
336 |
|
|
}
|
337 |
|
|
|
338 |
|
|
/**
|
339 |
|
|
* Implements hook_field_create_field().
|
340 |
|
|
*/
|
341 |
|
|
function i18n_field_field_create_field($field) {
|
342 |
|
|
i18n_field_field_update_strings($field);
|
343 |
|
|
}
|
344 |
|
|
|
345 |
|
|
/**
|
346 |
|
|
* Implements hook_field_create_instance().
|
347 |
|
|
*/
|
348 |
|
|
function i18n_field_field_create_instance($instance) {
|
349 |
|
|
i18n_field_instance_update_strings($instance);
|
350 |
|
|
}
|
351 |
|
|
|
352 |
|
|
/**
|
353 |
|
|
* Implements hook_field_delete_instance().
|
354 |
|
|
*/
|
355 |
|
|
function i18n_field_field_delete_instance($instance) {
|
356 |
|
|
i18n_string_object_remove('field_instance', $instance);
|
357 |
|
|
}
|
358 |
|
|
|
359 |
|
|
/**
|
360 |
|
|
* Implements hook_field_update_instance().
|
361 |
|
|
*/
|
362 |
|
|
function i18n_field_field_update_instance($instance, $prior_instance) {
|
363 |
|
|
i18n_field_instance_update_strings($instance);
|
364 |
|
|
}
|
365 |
|
|
|
366 |
|
|
/**
|
367 |
|
|
* Implements hook_field_update_field().
|
368 |
|
|
*/
|
369 |
|
|
function i18n_field_field_update_field($field) {
|
370 |
|
|
i18n_field_field_update_strings($field);
|
371 |
|
|
}
|
372 |
|
|
|
373 |
|
|
/**
|
374 |
|
|
* Update field strings
|
375 |
|
|
*/
|
376 |
|
|
function i18n_field_field_update_strings($field) {
|
377 |
|
|
i18n_string_object_update('field', $field);
|
378 |
|
|
}
|
379 |
|
|
|
380 |
|
|
/**
|
381 |
|
|
* Update field instance strings
|
382 |
|
|
*/
|
383 |
|
|
function i18n_field_instance_update_strings($instance) {
|
384 |
|
|
i18n_string_object_update('field_instance', $instance);
|
385 |
|
|
}
|
386 |
|
|
|
387 |
|
|
/**
|
388 |
|
|
* Returns the array of translated allowed values for a list field.
|
389 |
|
|
*
|
390 |
|
|
* The strings are not safe for output. Keys and values of the array should be
|
391 |
|
|
* sanitized through field_filter_xss() before being displayed.
|
392 |
|
|
*
|
393 |
|
|
* @param $field
|
394 |
|
|
* The field definition.
|
395 |
|
|
*
|
396 |
|
|
* @return
|
397 |
|
|
* The array of allowed values. Keys of the array are the raw stored values
|
398 |
|
|
* (number or text), values of the array are the display labels.
|
399 |
|
|
*/
|
400 |
|
|
function i18n_field_translate_allowed_values($field, $langcode = NULL) {
|
401 |
9faa5de0
|
Assos Assos
|
$allowed_values = list_allowed_values($field);
|
402 |
|
|
if (!$allowed_values) {
|
403 |
85ad3d82
|
Assos Assos
|
return array();
|
404 |
|
|
}
|
405 |
9faa5de0
|
Assos Assos
|
// Do not attempt to translate options from a callback.
|
406 |
|
|
$function = $field['settings']['allowed_values_function'];
|
407 |
|
|
if (!empty($function) && function_exists($function)) {
|
408 |
|
|
return $allowed_values;
|
409 |
|
|
}
|
410 |
|
|
return i18n_string_translate(array('field', $field['field_name'], '#allowed_values'), $allowed_values, array('langcode' => $langcode, 'sanitize' => FALSE));
|
411 |
85ad3d82
|
Assos Assos
|
}
|
412 |
|
|
|
413 |
|
|
/**
|
414 |
|
|
* Translate field default.
|
415 |
|
|
*/
|
416 |
|
|
function i18n_field_translate_default($instance, $value, $langcode = NULL) {
|
417 |
e4c061ad
|
Assos Assos
|
// The default value does not need sanitizing in a text_textfield widget.
|
418 |
|
|
$sanitize = !($instance['widget']['type'] == 'text_textfield' && $instance['widget']['module'] == 'text');
|
419 |
|
|
return i18n_string_translate(array('field', $instance['field_name'], $instance['bundle'], 'default_value'), $value, array('langcode' => $langcode, 'sanitize' => $sanitize));
|
420 |
85ad3d82
|
Assos Assos
|
}
|
421 |
|
|
|
422 |
|
|
/**
|
423 |
|
|
* Translate field property
|
424 |
|
|
*/
|
425 |
|
|
function i18n_field_translate_property($instance, $property, $langcode = NULL) {
|
426 |
|
|
// For performance reasons, we translate the whole instance once, which is cached.
|
427 |
|
|
$instance = i18n_string_object_translate('field_instance', $instance, array('langcode' => $langcode));
|
428 |
|
|
return $instance[$property];
|
429 |
|
|
}
|
430 |
|
|
|
431 |
|
|
/**
|
432 |
|
|
* Get i18n information for translating fields.
|
433 |
|
|
*
|
434 |
|
|
* @param $type
|
435 |
|
|
* Optional field type.
|
436 |
|
|
* @param $property
|
437 |
|
|
* Optional property to get from field type.
|
438 |
|
|
*
|
439 |
|
|
* @return
|
440 |
|
|
* - The property for the field if $type and $property set.
|
441 |
|
|
* - Array of properties for the field type if only $type is set.
|
442 |
|
|
* - Array of translation information for all field types.
|
443 |
|
|
*/
|
444 |
|
|
function i18n_field_type_info($type = NULL, $property = NULL) {
|
445 |
|
|
$info = &drupal_static(__FUNCTION__);
|
446 |
|
|
if (!isset($info)) {
|
447 |
|
|
$info = module_invoke_all('i18n_field_info');
|
448 |
|
|
drupal_alter('i18n_field_info', $info);
|
449 |
|
|
}
|
450 |
|
|
if ($property) {
|
451 |
|
|
return isset($info[$type]) && isset($info[$type][$property]) ? $info[$type][$property] : NULL;
|
452 |
|
|
}
|
453 |
|
|
elseif ($type) {
|
454 |
|
|
return isset($info[$type]) ? $info[$type] : array();
|
455 |
|
|
}
|
456 |
|
|
else {
|
457 |
|
|
return $info;
|
458 |
|
|
}
|
459 |
|
|
}
|
460 |
b3ab3446
|
Assos Assos
|
|
461 |
|
|
/**
|
462 |
|
|
* Implements hook_field_info_alter().
|
463 |
|
|
*/
|
464 |
|
|
function i18n_field_field_info_alter(&$field_info) {
|
465 |
|
|
foreach(array_keys($field_info) as $type) {
|
466 |
|
|
$field_info[$type]['property_callbacks'][] = 'i18n_field_entity_property_callback';
|
467 |
|
|
}
|
468 |
|
|
}
|
469 |
|
|
|
470 |
3115e37e
|
Assos Assos
|
/**
|
471 |
|
|
* Prime the cache to avoid single db queries for entity fields / properties.
|
472 |
|
|
*
|
473 |
|
|
* This is mainly uses when large operations are occuring like a flush of the
|
474 |
|
|
* entity_property_infos().
|
475 |
|
|
*/
|
476 |
|
|
function i18n_field_prime_caches() {
|
477 |
|
|
global $language;
|
478 |
|
|
static $cache_primed;
|
479 |
|
|
|
480 |
|
|
// Fill the cache. This should avoid single db queries when filling the
|
481 |
|
|
// properties.
|
482 |
|
|
if (empty($cache_primed)) {
|
483 |
|
|
$cache_primed = TRUE;
|
484 |
|
|
$text_group = i18n_string_textgroup('field');
|
485 |
|
|
// Load all strings at once to avoid callbacks for each individual string.
|
486 |
|
|
$text_group->load_strings();
|
487 |
|
|
$text_group->multiple_translation_search(array('type' => '*', 'objectid' => '*', 'property' => '*'), $language->language);
|
488 |
|
|
}
|
489 |
|
|
}
|
490 |
|
|
|
491 |
b3ab3446
|
Assos Assos
|
/**
|
492 |
|
|
* Callback to translate entity property info for a fields.
|
493 |
|
|
*
|
494 |
|
|
* @see entity_metadata_field_entity_property_info()
|
495 |
|
|
* @see entity_metadata_field_default_property_callback()
|
496 |
|
|
* @see i18n_field_i18n_object_info_alter()
|
497 |
|
|
* @see hook_module_implements_alter()
|
498 |
|
|
*/
|
499 |
|
|
function i18n_field_entity_property_callback(&$info, $entity_type, $field, $instance, $field_type) {
|
500 |
|
|
global $language;
|
501 |
|
|
|
502 |
|
|
// This could create a endless recursion if it's called during rebuilding the
|
503 |
|
|
// cache for i18n_object_info(). So if the cache of i18n_object_info isn't
|
504 |
|
|
// available yet we assume the worst case, leave the info alone but trigger a
|
505 |
|
|
// rebuild of the property when hook_i18n_object_info_alter is invoked. At
|
506 |
|
|
// that point the info is available and we can rely on it.
|
507 |
|
|
if (!$info = &drupal_static('i18n_object_info')) {
|
508 |
|
|
$i18n_field_entity_property_callback_fallback = &drupal_static(__FUNCTION__);
|
509 |
|
|
$i18n_field_entity_property_callback_fallback = TRUE;
|
510 |
|
|
return;
|
511 |
|
|
}
|
512 |
|
|
|
513 |
3115e37e
|
Assos Assos
|
i18n_field_prime_caches();
|
514 |
b3ab3446
|
Assos Assos
|
$name = $field['field_name'];
|
515 |
|
|
$property = &$info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name];
|
516 |
|
|
$property['label'] = i18n_field_translate_property($instance, 'label', $language->language);
|
517 |
|
|
}
|
518 |
|
|
|
519 |
|
|
/**
|
520 |
|
|
* Implements hook_i18n_object_info_alter().
|
521 |
|
|
*/
|
522 |
|
|
function i18n_field_i18n_object_info_alter(&$info) {
|
523 |
|
|
if (drupal_static('i18n_field_entity_property_callback')) {
|
524 |
|
|
if ($info = drupal_static('i18n_object_info')) {
|
525 |
|
|
// Clean static and permanent cache of the data and then re-run the property
|
526 |
|
|
// building.
|
527 |
3115e37e
|
Assos Assos
|
// Use a lock to avoid stampeding.
|
528 |
|
|
$lock_name = 'i18n_field_entity_property_callback_fallback:' . $GLOBALS['language']->language;
|
529 |
|
|
// See if another request is already doing this. If so we bail out here as
|
530 |
|
|
// we won't help with anything at the moment.
|
531 |
|
|
if (!lock_may_be_available($lock_name)) {
|
532 |
|
|
return;
|
533 |
|
|
}
|
534 |
|
|
if (lock_acquire($lock_name)) {
|
535 |
|
|
i18n_field_prime_caches();
|
536 |
|
|
// Inject translated properties.
|
537 |
|
|
$entity_property_info = entity_get_property_info();
|
538 |
|
|
foreach ($entity_property_info as $entity_type => $properties) {
|
539 |
|
|
if (isset($properties['bundles'])) {
|
540 |
|
|
foreach ($properties['bundles'] as $bundle => $bundle_properties) {
|
541 |
|
|
if ($bundle_properties['properties']) {
|
542 |
|
|
foreach ($bundle_properties['properties'] as $bundle_property => $bundle_property_info) {
|
543 |
|
|
if ($instance = field_info_instance($entity_type, $bundle_property, $bundle)) {
|
544 |
|
|
$property = &$entity_property_info[$entity_type]['bundles'][$instance['bundle']]['properties'][$bundle_property];
|
545 |
|
|
$property['label'] = i18n_field_translate_property($instance, 'label', $GLOBALS['language']->language);
|
546 |
|
|
}
|
547 |
|
|
}
|
548 |
|
|
}
|
549 |
|
|
}
|
550 |
|
|
}
|
551 |
|
|
}
|
552 |
|
|
// Inject into static cache.
|
553 |
|
|
$entity_get_property_info = &drupal_static('entity_get_property_info', array());
|
554 |
|
|
$entity_get_property_info = $entity_property_info;
|
555 |
|
|
// Write permanent cache.
|
556 |
|
|
cache_set('entity_property_info:' . $GLOBALS['language']->language, $entity_property_info);
|
557 |
|
|
lock_release($lock_name);
|
558 |
|
|
}
|
559 |
b3ab3446
|
Assos Assos
|
}
|
560 |
|
|
else {
|
561 |
|
|
watchdog('i18n_field', 'Unable to run fall-back handling for entity property translation due missing "i18n_object_info" cache', array(), WATCHDOG_WARNING);
|
562 |
|
|
}
|
563 |
|
|
}
|
564 |
|
|
}
|
565 |
|
|
|
566 |
|
|
/**
|
567 |
|
|
* Implements hook_module_implements_alter().
|
568 |
|
|
*/
|
569 |
|
|
function i18n_field_module_implements_alter(&$implementations, $hook) {
|
570 |
|
|
if ($hook == 'i18n_object_info_alter') {
|
571 |
|
|
// Move our hook implementation to the bottom.
|
572 |
|
|
$group = $implementations['i18n_field'];
|
573 |
|
|
unset($implementations['i18n_field']);
|
574 |
|
|
$implementations['i18n_field'] = $group;
|
575 |
|
|
}
|
576 |
e013fa40
|
Assos Assos
|
} |