diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index 31e4426d012afebc9a5e48d9f524863e9bb832f6..1004e40e156f3393a163995bb91488a083b8b44f 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -1215,7 +1215,9 @@ class SelectionField extends FormField { 'id'=>3, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'', 'hint'=>__('Leading text shown before a value is selected'), - 'configuration'=>array('size'=>40, 'length'=>40), + 'configuration'=>array('size'=>40, 'length'=>40, + 'translatable'=>$this->getTranslateTag('prompt'), + ), )), 'default' => new SelectionField(array( 'id'=>4, 'label'=>__('Default'), 'required'=>false, 'default'=>'', diff --git a/include/class.forms.php b/include/class.forms.php index 75d3bfc83914e8689edb856a48c16816164b7f84..1d7f95031193175f8a0c363b6e50739f34489375 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -931,7 +931,9 @@ class ChoiceField extends FormField { 'prompt' => new TextboxField(array( 'id'=>2, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'', 'hint'=>__('Leading text shown before a value is selected'), - 'configuration'=>array('size'=>40, 'length'=>40), + 'configuration'=>array('size'=>40, 'length'=>40, + 'translatable'=>$this->getTranslateTag('prompt'), + ), )), 'multiselect' => new BooleanField(array( 'id'=>1, 'label'=>'Multiselect', 'required'=>false, 'default'=>false, @@ -1835,7 +1837,10 @@ class ChoicesWidget extends Widget { // Determine the value for the default (the one listed if nothing is // selected) $choices = $this->field->getChoices(true); - $prompt = $config['prompt'] ?: __('Select'); + $prompt = ($config['prompt']) + ? $this->field->getLocal('prompt', $config['prompt']) + : __('Select' + /* Used as a default prompt for a custom drop-down list */); $have_def = false; // We don't consider the 'default' when rendering in 'search' mode diff --git a/include/class.list.php b/include/class.list.php index f5f9c4bd2551f5605dc4228da9b827e6c62ac010..8a6e4667558eb2733dfdd8cc3e9e50145bab08e9 100644 --- a/include/class.list.php +++ b/include/class.list.php @@ -315,6 +315,15 @@ class DynamicList extends VerySimpleModel implements CustomList { return JsonDataParser::parse($this->_config->get('configuration')); } + function getTranslateTag($subtag) { + return _H(sprintf('list.%s.%s', $subtag, $this->id)); + } + function getLocal($subtag) { + $tag = $this->getTranslateTag($subtag); + $T = CustomDataTranslation::translate($tag); + return $T != $tag ? $T : $this->get($subtag); + } + function update($vars, &$errors) { $required = array(); @@ -520,7 +529,7 @@ class DynamicListItem extends VerySimpleModel implements CustomListItem { } function getValue() { - return $this->get('value'); + return $this->getLocal('value'); } function getAbbrev() { @@ -587,6 +596,15 @@ class DynamicListItem extends VerySimpleModel implements CustomListItem { } } + function getTranslateTag($subtag) { + return _H(sprintf('listitem.%s.%s', $subtag, $this->id)); + } + function getLocal($subtag) { + $tag = $this->getTranslateTag($subtag); + $T = CustomDataTranslation::translate($tag); + return $T != $tag ? $T : $this->get($subtag); + } + function toString() { return $this->get('value'); } @@ -1010,6 +1028,15 @@ class TicketStatus extends VerySimpleModel implements CustomListItem { return $this->_properties; } + function getTranslateTag($subtag) { + return _H(sprintf('status.%s.%s', $subtag, $this->id)); + } + function getLocal($subtag) { + $tag = $this->getTranslateTag($subtag); + $T = CustomDataTranslation::translate($tag); + return $T != $tag ? $T : $this->get($subtag); + } + function getConfiguration() { if (!$this->_settings) { diff --git a/include/class.sla.php b/include/class.sla.php index 070743a2bb6f0c8e22c3664be229c8817a401852..93e39307175c053d345b31b0c597124268b1a029 100644 --- a/include/class.sla.php +++ b/include/class.sla.php @@ -94,6 +94,20 @@ class SLA { return ($this->ht['enable_priority_escalation']); } + function getTranslateTag($subtag) { + return _H(sprintf('sla.%s.%s', $subtag, $this->id)); + } + function getLocal($subtag) { + $tag = $this->getTranslateTag($subtag); + $T = CustomDataTranslation::translate($tag); + return $T != $tag ? $T : $this->ht[$subtag]; + } + static function getLocalById($id, $subtag, $default) { + $tag = _H(sprintf('sla.%s.%s', $subtag, $id)); + $T = CustomDataTranslation::translate($tag); + return $T != $tag ? $T : $default; + } + function update($vars,&$errors) { if(!SLA::save($this->getId(),$vars,$errors)) @@ -139,7 +153,7 @@ class SLA { while($row=db_fetch_array($res)) $slas[$row['id']] = sprintf(__('%s (%d hours - %s)' /* Tokens are <name> (<#> hours - <Active|Disabled>) */), - $row['name'], + self::getLocalById($row['id'], 'name', $row['name']), $row['grace_period'], $row['isactive']?__('Active'):__('Disabled')); } diff --git a/include/class.topic.php b/include/class.topic.php index 9139f9e6d0926efe6d27bc2dc9145ef02f17b151..395e482ad52722cfa886ef346d0d9e7444009bcd 100644 --- a/include/class.topic.php +++ b/include/class.topic.php @@ -215,6 +215,15 @@ class Topic { array('Ticket', 'isTicketNumberUnique')); } + function getTranslateTag($subtag) { + return _H(sprintf('topic.%s.%s', $subtag, $this->id)); + } + function getLocal($subtag) { + $tag = $this->getTranslateTag($subtag); + $T = CustomDataTranslation::translate($tag); + return $T != $tag ? $T : $this->ht[$subtag]; + } + function setSortOrder($i) { if ($i != $this->ht['sort']) { $sql = 'UPDATE '.TOPIC_TABLE.' SET `sort`='.db_input($i) @@ -254,11 +263,12 @@ class Topic { return self::save(0, $vars, $errors); } - static function getHelpTopics($publicOnly=false, $disabled=false) { + static function getHelpTopics($publicOnly=false, $disabled=false, $localize=true) { global $cfg; static $topics, $names = array(); - if (!$names) { + // If localization is specifically requested, then rebuild the list. + if (!$names || $localize) { $sql = 'SELECT topic_id, topic_pid, ispublic, isactive, topic FROM '.TOPIC_TABLE . ' ORDER BY `sort`'; $res = db_query($sql); @@ -269,13 +279,23 @@ class Topic { $topics[$id] = array('pid'=>$pid, 'public'=>$pub, 'disabled'=>!$act, 'topic'=>$topic); + $localize_this = function($id, $default) use ($localize) { + if (!$localize) + return $default; + + $tag = _H("topic.name.{$id}"); + $T = CustomDataTranslation::translate($tag); + return $T != $tag ? $T : $default; + }; + // Resolve parent names foreach ($topics as $id=>$info) { - $name = $info['topic']; + $name = $localize_this($id, $info['topic']); $loop = array($id=>true); $parent = false; - while ($info['pid'] && ($info = $topics[$info['pid']])) { - $name = sprintf('%s / %s', $info['topic'], $name); + while (($pid = $info['pid']) && ($info = $topics[$info['pid']])) { + $name = sprintf('%s / %s', $localize_this($pid, $info['topic']), + $name); if ($parent && $parent['disabled']) // Cascade disabled flag $topics[$id]['disabled'] = true; @@ -301,6 +321,11 @@ class Topic { $requested_names[$id] = $n; } + // XXX: If localization requested and the current locale is not the + // primary, the list may need to be sorted. Caching is ok here, + // because the locale is not going to be changed within a single + // request. + return $requested_names; } @@ -308,8 +333,8 @@ class Topic { return self::getHelpTopics(true); } - function getAllHelpTopics() { - return self::getHelpTopics(false, true); + function getAllHelpTopics($localize=false) { + return self::getHelpTopics(false, true, $localize); } function getIdByName($name, $pid=0) { @@ -412,10 +437,19 @@ class Topic { static function updateSortOrder() { // Fetch (un)sorted names - if (!($names = static::getHelpTopics(false, true))) + if (!($names = static::getHelpTopics(false, true, false))) return; - uasort($names, function($a, $b) { return strcmp($a, $b); }); + if (function_exists('collator_create')) { + $coll = Collator::create($cfg->getPrimaryLanguage()); + // UASORT is necessary to preserve the keys + uasort($names, function($a, $b) use ($coll) { + return $coll->compare($a, $b); }); + } + else { + // Really only works on English names + asort($names); + } $update = array_keys($names); foreach ($update as $idx=>&$id) { diff --git a/include/staff/dynamic-list.inc.php b/include/staff/dynamic-list.inc.php index 0b4ed80996b418ff19d6bf020dc7bc190e08ef37..3b5d9319779ab9b8302917b8217b989b5252150d 100644 --- a/include/staff/dynamic-list.inc.php +++ b/include/staff/dynamic-list.inc.php @@ -6,6 +6,8 @@ if ($list) { $action = 'update'; $submit_text = __('Save Changes'); $info = $list->getInfo(); + $trans['name'] = $list->getTranslateTag('name'); + $trans['plural'] = $list->getTranslateTag('plural'); $newcount=2; } else { $title = __('Add New Custom List'); @@ -55,9 +57,10 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) echo $list->getName(); else { echo sprintf('<input size="50" type="text" name="name" + data-translate-tag="%s" value="%s"/> <span class="error">*<br/>%s</span>', - $info['name'], $errors['name']); + $trans['name'], $info['name'], $errors['name']); } ?> </td> @@ -70,8 +73,9 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) echo $list->getPluralName(); else echo sprintf('<input size="50" type="text" + data-translate-tag="%s" name="name_plural" value="%s"/>', - $info['name_plural']); + $trans['plural'], $info['name_plural']); ?> </td> </tr> @@ -131,6 +135,7 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) <tr> <td><i class="icon-sort"></i></td> <td><input type="text" size="32" name="prop-label-<?php echo $id; ?>" + data-translate-tag="<?php echo $f->getTranslateTag('label'); ?>" value="<?php echo Format::htmlchars($f->get('label')); ?>"/> <font class="error"><?php if ($ferrors['label']) echo '<br/>'; echo $ferrors['label']; ?> @@ -251,6 +256,7 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) <input type="hidden" name="sort-<?php echo $id; ?>" value="<?php echo $i->getSortOrder(); ?>"/></td> <td><input type="text" size="40" name="value-<?php echo $id; ?>" + data-translate-tag="<?php echo $i->getTranslateTag('value'); ?>" value="<?php echo $i->getValue(); ?>"/> <?php if ($list->hasProperties()) { ?> <a class="action-button field-config" diff --git a/include/staff/helptopic.inc.php b/include/staff/helptopic.inc.php index bd254cd2db7e1b7a1bc5d06ac42706cb5b6b3375..73db1e02235e16af3f67678d704d41a98c03908d 100644 --- a/include/staff/helptopic.inc.php +++ b/include/staff/helptopic.inc.php @@ -9,6 +9,7 @@ if($topic && $_REQUEST['a']!='add') { $info=$topic->getInfo(); $info['id']=$topic->getId(); $info['pid']=$topic->getPid(); + $trans['name'] = $topic->getTranslateTag('name'); $qstr.='&id='.$topic->getId(); } else { $title=__('Add New Help Topic'); @@ -43,7 +44,8 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info); <?php echo __('Topic');?>: </td> <td> - <input type="text" size="30" name="topic" value="<?php echo $info['topic']; ?>"> + <input type="text" size="30" name="topic" value="<?php echo $info['topic']; ?>" + data-translate-tag="<?php echo $trans['name']; ?>"/> <span class="error">* <?php echo $errors['topic']; ?></span> <i class="help-tip icon-question-sign" href="#topic"></i> </td> </tr> diff --git a/include/staff/helptopics.inc.php b/include/staff/helptopics.inc.php index d124a67a26f8118829b7758e7310dc42c01b2630..a161409e18943a850617525ffc0385c8b0789fdc 100644 --- a/include/staff/helptopics.inc.php +++ b/include/staff/helptopics.inc.php @@ -8,7 +8,7 @@ $sql='SELECT topic.* ' .' LEFT JOIN '.DEPT_TABLE.' dept ON (dept.dept_id=topic.dept_id) ' .' LEFT JOIN '.TICKET_PRIORITY_TABLE.' pri ON (pri.priority_id=topic.priority_id) '; $sql.=' WHERE 1'; -$order_by = ($cfg->getTopicSortMode() == 'm' ? '`sort`' : '`topic_id`'); +$order_by = '`sort`'; $page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1; //Ok..lets roll...create the actual query @@ -27,9 +27,6 @@ while ($row = db_fetch_array($res)) foreach ($topics as &$t) $t['name'] = Topic::getTopicName($t['topic_id']); -if ($cfg->getTopicSortMode() == 'a') - usort($topics, function($a, $b) { return strcmp($a['name'], $b['name']); }); - ?> <div class="pull-left" style="width:700px;padding-top:5px;"> <h2><?php echo __('Help Topics');?></h2> diff --git a/include/staff/slaplan.inc.php b/include/staff/slaplan.inc.php index 2e72720b8f2cd8030b70e039a321177196eb282a..91dba3a2b735c40e43cf6c2b8f155176283d0326 100644 --- a/include/staff/slaplan.inc.php +++ b/include/staff/slaplan.inc.php @@ -8,6 +8,7 @@ if($sla && $_REQUEST['a']!='add'){ $submit_text=__('Save Changes'); $info=$sla->getInfo(); $info['id']=$sla->getId(); + $trans['name'] = $sla->getTranslateTag('name'); $qstr.='&id='.$sla->getId(); }else { $title=__('Add New SLA Plan' /* SLA is abbreviation for Service Level Agreement */); @@ -41,7 +42,8 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info); <?php echo __('Name');?>: </td> <td> - <input type="text" size="30" name="name" value="<?php echo $info['name']; ?>"> + <input type="text" size="30" name="name" value="<?php echo $info['name']; ?>" + data-translate-tag="<?php echo $trans['name']; ?>"/> <span class="error">* <?php echo $errors['name']; ?></span> <i class="help-tip icon-question-sign" href="#name"></i> </td> </tr> diff --git a/include/staff/templates/dynamic-field-config.tmpl.php b/include/staff/templates/dynamic-field-config.tmpl.php index aba9966d27f34a22c22937e8bbf1a8c30c79cdc0..8051e31ef4fa2ee4834d5447d3d448d44441bded 100644 --- a/include/staff/templates/dynamic-field-config.tmpl.php +++ b/include/staff/templates/dynamic-field-config.tmpl.php @@ -12,7 +12,7 @@ ?>" <?php if (!$f->isVisible()) echo 'style="display:none;"'; ?>> <div class="field-label <?php if ($f->get('required')) echo 'required'; ?>"> <label for="<?php echo $f->getWidget()->name; ?>"> - <?php echo Format::htmlchars($f->get('label')); ?>: + <?php echo Format::htmlchars($f->getLocal('label')); ?>: <?php if ($f->get('required')) { ?> <span class="error">*</span> <?php } ?> diff --git a/include/staff/templates/dynamic-form.tmpl.php b/include/staff/templates/dynamic-form.tmpl.php index 7f8cd82b88148122c8545c458121c83b27cef56b..6d0e15121a93b5d77bfee69335397e345a4da70a 100644 --- a/include/staff/templates/dynamic-form.tmpl.php +++ b/include/staff/templates/dynamic-form.tmpl.php @@ -79,7 +79,7 @@ if (isset($options['entry']) && $options['mode'] == 'edit') { ?> } if ($field->get('hint') && !$field->isBlockLevel()) { ?> <br /><em style="color:gray;display:inline-block"><?php - echo Format::htmlchars($field->get('hint')); ?></em> + echo Format::htmlchars($field->getLocal('hint')); ?></em> <?php } foreach ($field->errors() as $e) { ?> diff --git a/include/staff/templates/list-item-properties.tmpl.php b/include/staff/templates/list-item-properties.tmpl.php index dcfc34b92d5bb7f51497cd227a13a2f609a79bc6..df6487fd814857d2ffac204829a59110b4a57b03 100644 --- a/include/staff/templates/list-item-properties.tmpl.php +++ b/include/staff/templates/list-item-properties.tmpl.php @@ -19,7 +19,7 @@ <div class="field-label"> <label for="<?php echo $f->getWidget()->name; ?>" style="vertical-align:top;padding-top:0.2em"> - <?php echo Format::htmlchars($f->get('label')); ?>:</label> + <?php echo Format::htmlchars($f->getLocal('label')); ?>:</label> <?php if (!$internal && $f->isEditable() && $f->get('hint')) { ?> <br /><em style="color:gray;display:inline-block"><?php diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php index d70af212e8d692ada02827e3423978bb4d28ed3d..4956c74287c2ad2df7986f6f8f7958388a0b0cff 100644 --- a/include/staff/ticket-open.inc.php +++ b/include/staff/ticket-open.inc.php @@ -143,7 +143,7 @@ if ($_POST) } });"> <?php - if ($topics=Topic::getHelpTopics()) { + if ($topics=Topic::getHelpTopics(false, false, true)) { if (count($topics) == 1) $selected = 'selected="selected"'; else { ?>