I'm currently internationalising my cake-php-webapp which is working very fine.
Everything is translated but form inputs:
echo $this->Form->input('name', array('class' => 'form-control'));
This generates a label
<label for="UserName">Name</label>
How can I specify that "Name" should be translated as well?
I think this would be the best way I know so far:
echo $this->Form->input('name', array('class' => 'form-control', 'label'=>__('field_name')));
But is there a way without specifying the label?
In CakePHP 2.3, if you take a look in the built-in FormHelper class:
public function label($fieldName = null, $text = null, $options = array()) {
...
if ($text === null) {
if (strpos($fieldName, '.') !== false) {
$fieldElements = explode('.', $fieldName);
$text = array_pop($fieldElements);
} else {
$text = $fieldName;
}
if (substr($text, -3) === '_id') {
$text = substr($text, 0, -3);
}
$text = __(Inflector::humanize(Inflector::underscore($text)));
}
...
}
It looks to me like if you don't set the label text, it derives your label text from the field name, then calls the translate function on it.
Have you tried just creating an input without specifying the label text, then saving a translation for the text that automatically gets generated for that input's label in your corresponding .po file?
Related
I am trying to pass selected checkbox values from a real estate contract via the REST API. Currently I am able to make the check boxes show up on the document but they do not show checked or uncheck based on the True/False data passed. What am I doing wrong? I've tried setting them as read only and mandatory on the template and they still don't populate the checks in the boxes.
*updated with correct code below
$sellerTabs = new \DocuSign\eSign\Model\Tabs();
$count_fields = 0;
foreach ($fields_data as $key => $field_value) {
//echo $field_value."\n";
$seller_address[$count_fields] = new
\DocuSign\eSign\Model\Text(["tab_label" => $key,
"value" => $field_value]);
$count_fields++;
}
$tab_group = $_REQUEST["group"];
$sellerTabs = new \DocuSign\eSign\Model\Tabs();
$count_checks = 0;
foreach ($checks_data as $key => $check_value) {
//echo $check_value."\n";
$seller_checks[$count_checks]= new
DocuSign\eSign\Model\Checkbox(["tab_label" => $key,
"selected" =>
$check_value,"Checkbox_Group"=>$tab_group]);
$count_checks++;
}
//file_put_contents("create_event.log",
"json_decode($checks, true);" ,FILE_APPEND;
"json_decode($fields, true);", FILE_APPEND);
//exit();
$sellerTabs->setTextTabs($seller_address);
$sellerTabs->setCheckboxTabs($seller_checks);
$envelop_definition = new
DocuSign\eSign\Model\EnvelopeDefinition();
$b_roles = array();
//exit();
// echo $roles_data;
foreach ($roles_data as $role_data) {
// echo $role_data;
$data = explode("|", $role_data);
$role_data = new DocuSign\eSign\Model\TemplateRole();
$role_data->setName($data[0]);
$role_data->setEmail($data[1]);
$role_data->setRoleName($data[2]);
$role_data->setRoutingOrder($data[3]);
$role_data->setTabs($sellerTabs);
//echo $role_data;
array_push($b_roles, $role_data);
}
//var_dump($b_roles);
/*echo "<pre>";
print_r($_REQUEST["templateID"]);
exit();*/
// $envelop_definition-
>setTemplateRoles(array($sellerRole /,
$templateRole3/));
I am trying to get a custom field assigned to taxonomy. I have tried this:
$vid = 'zeme';
$terms =\Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid);
$terms is now storing all the terms from the vocabulary called 'zeme'. The problem is when I print this variable, it doesnt show the custom field that I need to get.
Any idea how can I get this custom field?
My code looks like this:
$vid = 'zeme';
$terms =\Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid);
foreach ($terms as $term) {
$term_data[] = array(
'id' => $term->tid,
'name' => $term->name
);
}
Here is the loadTree function official documentation :
TermStorage::loadTree
When you use the loadTree function, it will only get you the minimal datas to save execution time. You can see there is a $load_entities parameter set to false by default.
bool $load_entities: If TRUE, a full entity load will occur on the
term objects. Otherwise they are partial objects queried directly from
the {taxonomy_term_data} table to save execution time and memory
consumption when listing large numbers of terms. Defaults to FALSE.
So if you want to get all the datas of each of your taxonomy terms, you have to set $load_entities to true.
$vid = 'zeme';
$terms =\Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadTree($vid, 0, null, true);
Found this way from this post Get custom fields assigned to taxonomy:
$contact_countries = \Drupal::service('entity_type.manager')->getStorage("taxonomy_term")->loadTree('contact_country');
$terms = array();
foreach($contact_countries as $contact_countrie) {
$terms[] = array(
'contact_country' => $contact_countrie->name,
'contact_phone' => \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($contact_countrie->tid)->get('field_phone')->getValue()[0]['value'],
'contact_flag' => \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($contact_countrie->tid)->get('field_category_flag')->entity->uri->value,
);
}
Very usefull!
public function getTaxonomyBuild(){
$terms = \Drupal::service('entity_type.manager')->getStorage("taxonomy_term")->loadTree('faq_sec');
foreach($terms as $term) {
$term_data[] = array(
'name' => $term->name,
'img' => file_create_url(\Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($term->tid)->get('field_sec_img')->entity->uri->value),
);
}
return $term_data;
}
good solution
When using $this->Form->input('fieldname'), CakePHP creates a label element that, by convention, uses the fieldname. I know I can specify another string to use for the label as an argument to the input method, but is there any way I can specify the label name in the model, so I don't have to repeat the label name in multiple ctp files (e.g. so I only have to change it in one place)?
So I created this and made a quick test which worked, however, can't guarantee it's bug free:
<?php
App::uses('FormHelper', 'View/Helper');
class MyFormHelper extends FormHelper {
public function label($fieldName = null, $text = null, $options = array()) {
if ($text === null) {
$entity = $this->entity();
$field = array_pop($entity);
$model = $this->model();
$object = $this->_models[$model];
if (isset($object->labels[$field])) {
$text = $object->labels[$field];
}
}
return parent::label($fieldName, $text, $options);
}
}
Drop that in app/View/Helper/MyFormHelper.php
Add it to the helper array and alias it if you want to.
Add a public $labels array to the model with field => label-text structure.
Hope it works.
I've started working on a theme from scratch, I've tried to replace the title of the textfield but when imploding the search variable into search_form, the result is blank. Any error that I could be missing?
`function mytheme_preprocess_search_block_form(&$form) {
$form['search'] = array();
$hidden = array();
// Provide variables named after form keys so themers can print each element independently.
foreach (element_children($form['form']) as $key) {
echo $key;
$type = $form['form'][$key]['#type'];
echo '__'.$type.'<br />';
if ($type == 'hidden' || $type == 'token') {
$hidden[] = drupal_render($form['form'][$key]);
}
else {
if($key == 'search_block_form')
{
$form['form'][$key]['#title'] = t('');
//$form['search'][$key] = drupal_render($form['form'][$key]);
}
else
{
$form['search'][$key] = drupal_render($form['form'][$key]);
}
}
}
// Hidden form elements have no value to themers. No need for separation.
$form['search']['hidden'] = implode($hidden);
// Collect all form elements to make it easier to print the whole form.
$form['search_form'] = implode($form['search']);
var_dump($form);
exit;
}`
Refer to http://drupal.org/node/1092122:
<?php
/**
* Implements hook_theme().
*/
function MYMODULE_theme($existing, $type, $theme, $path) {
return array(
'article_node_form' => array(
'render element' => 'form',
'template' => 'article-node-form',
// this will set to module/theme path by default:
'path' => drupal_get_path('module', 'MYMODULE'),
),
);
}
?>
<?php
/**
* Preprocessor for theme('article_node_form').
*/
function template_preprocess_article_node_form(&$variables) {
// nodeformcols is an alternative for this solution.
if (!module_exists('nodeformcols')) {
$variables['sidebar'] = array(); // Put taxonomy fields in sidebar.
$variables['sidebar'][] = $variables['form']['field_tags'];
hide($variables['form']['field_tags']);
// Extract the form buttons, and put them in independent variable.
$variables['buttons'] = $variables['form']['actions'];
hide($variables['form']['actions']);
}
}
?>
article-node-form.tpl.php
<?php echo drupal_render_children($form)?>
Quoting from the cakephp Book (ver 1.3):
Note that only fields of the model you are directly doing find on will be translated. Models attached via associations won't be translated because triggering callbacks on associated models is currently not supported.
Has anyone come up with a solution for this?
If not could you give me some pointers concerning the following simple scenario.
I have 2 models:
Project, Category.
Project HABTM Category
I have properly set up i18n table and I have a few entries in the db, all translated. When I retrieve a project it does retrieve the translation but not the translated category because as it says in the cakephp book models attached via associations won't be translated.
I have another workaround; I don't know if it is any better or worse performance- or style-wise, only that it suits the "fat models, skinny controllers" goal:
AppModel.php
public function getTranslatedModelField($id = 0, $field) {
$res = false;
$db = $this->getDataSource();
$tmp = $db->fetchAll('SELECT content from s2h_i18n WHERE model = ? AND locale = ? AND foreign_key = ? AND field = ? LIMIT 1',
array($this->alias, Configure::read('Config.language'), $id, $field)
);
if (!empty($tmp)) {
$res = $tmp[0]['s2h_i18n']['content'];
}
return $res;
}
SomeModel.php
public function afterFind($results, $primary = false) {
foreach ($results as $key => $val) {
if (isset($val['SomeOtherModel']) && isset($val['SomeOtherModel']['id'])) {
$results[$key]['SomeOtherModel']['name'] =
$this->SomeOtherModel->getTranslatedModelField($val['SomeOtherModel']['id'], 'name');
}
// other possible queries for other models and/or fields
}
return $results;
}
OK I found a solution. Which is mostly a workaround. I should have thought of that earlier.
What I'm doing is the following. I'm finding all projects and recursively all categories associated with projects. Now since cakephp does not translate categories I am using the results from the initial query and I am performing a second one only for categories but using the category id values that I found on the first query. Now cakephp translates categories since I'm only searching for them and I can have their data translated.
At the moment I'm OK with this solution but it would be nice if first cakephp makes the translate behavior out of the box ready or secondly if someone had a behavior that could support retrieval of translation on associated models.
I generalized the afterFind part a bit, so that it automatically grabs the fields to translate from the associated models' actsAs["Translate"] array, and uses an array of associated models to (potentially) translate:
public function afterFind($results, $primary = false){
$modelsToTranslate = array("SomeModel", "AnotherModel");
foreach ($results as $key => $val){
foreach($modelsToTranslate as $mtt){
if (isset($val[$mtt])){
foreach($val[$mtt] as $fieldname => $fieldval){
foreach ($this->$mtt->actsAs["Translate"] as $fieldToTranslate){
$results[$key][$mtt][$fieldname][$fieldToTranslate] = $this->$mtt->getTranslatedModelField($val[$mtt][$fieldname]['id'], $fieldToTranslate);
}
}
}
}
}
return $results;
}
I took above solution and generalized both functions a bit, now it needs to be used together with the translate behaviour and both functions need to go into the model.php - everything else should work by itself:
public function getTranslatedModelField($id = 0, $field) {
$res = false;
$translateTable = (isset($this->translateTable))?$this->translateTable:"i18n";
$db = $this->getDataSource();
$tmp = $db->fetchAll(
"SELECT content from {$translateTable} WHERE model = ? AND locale = ? AND foreign_key = ? AND field = ? LIMIT 1",
array($this->alias, Configure::read('Config.language'), $id, $field)
);
if (!empty($tmp)) {
$res = $tmp[0][$translateTable]['content'];
}
return $res;
}
public function afterFind($results, $primary = false) {
if($primary == false && array_key_exists('Translate', $this->actsAs)) {
foreach ($results as $key => $val) {
if (isset($val[$this->name]) && isset($val[$this->name]['id'])) {
foreach($this->actsAs['Translate'] as $translationfield) {
$results[$key][$this->name][$translationfield] =
$this->getTranslatedModelField($val[$this->name]['id'], $translationfield);
}
} else if($key == 'id' && is_numeric($val)) {
foreach($this->actsAs['Translate'] as $translationfield) {
$results[$translationfield] =
$this->getTranslatedModelField($val, $translationfield);
}
}
}
}
return $results;
}