PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label translate. Show all posts
Showing posts with label translate. Show all posts

Friday, April 22, 2022

[FIXED] How to keep HABTM with TranslateBehaviour in CakePHP

 April 22, 2022     cakephp, cakephp-2.3, translate     No comments   

Issue

I have a model "Report" where some fields are translatable through TranslateBehaviour. Each Report "Has And Belongs To Many" ReportTags and ReportCategories.

In my ReportsController, I try to add a new Report to DB with:

public function admin_add() {
if ($this -> request -> is('post')) {
    $this -> Report -> create();
    if ($this -> Report -> saveMany($this -> request -> data)) {
        $this -> Session -> setFlash(__('Report saved OK'), 'flash/backend/success');
        return $this -> redirect(array('action' => 'index'));
    } else {
        $this->Session->setFlash(__('Report saved KO. Please, try again'), 'flash/backend/error');
    }
}
$users = $this->Report->User->find('list');
$reportCategories = $this->Report->ReportCategory->find('list');
$reportTags = $this->Report->ReportTag->find('list');
$this->set(compact('users', 'reportCategories', 'reportTags'));
$this->set('title',__('New report'));
$this->set('item_selected',4);
}

But doing this I add three reports to Reports table, the one I want to add and two more empty. i18n table adds the correct rows for translations (one per locale and translatable field), but also the rows with fields for the two empty models added, with "content" field empty.

How can I add only the right values? I tried also to do

unset($this->request->data['ReportCategory']);
unset($this->request->data['ReportTag']);

before saveMany, but this eliminates associations between Report, ReportCategory and ReportTag.

For more info, $this -> request -> data contains:

array(3) { 
["Report"]=> array(11) { 
    ["published"]=> string(1) "0" 
    ["sticky"]=> string(1) "0" 
    ["in_rss"]=> string(1) "1" 
    ["slug"]=> string(4) "asdf" 
    ["media_uri"]=> string(4) "ssss" 
    ["title"]=> array(3) {  
        ["spa"]=> string(3) "www" 
        ["eng"]=> string(3) "eee" 
    } 
    ["summary"]=> array(3) { 
        ["spa"]=> string(3) "www" 
        ["eng"]=> string(3) "eee" 
    } 
    ["body"]=> array(3) { 
        ["spa"]=> string(12) "www" 
        ["eng"]=> string(12) "eee" 
        } 
    } 
["ReportCategory"]=> array(1) { 
    ["ReportCategory"]=> array(1) { 
        [0]=> string(1) "7" 
    } 
} 
["ReportTag"]=> array(1) { 
    ["ReportTag"]=> array(2) { 
        [0]=> string(2) "23" 
        [1]=> string(2) "24" 
    } 
} 
}

Solution

Solved. Problem was saveMany. It must be replaced by saveAll. I use saveMany in other controllers when there are HasMany associations, to save the array of translations for translatable fields. In HABTM associations, this does not work. Hope this helps to somebody.



Answered By - anuf
Answer Checked By - Mary Flores (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Tuesday, March 15, 2022

[FIXED] CakePHP 3.5 Translate behavior I18n::getDefaultLocale() changes by itself

 March 15, 2022     cakephp, cakephp-3.0, internationalization, php, translate     No comments   

Issue

I am using CakePHP 3.5. When My browser is in english, enverything is fine. The default locale is en_US, as I set it, and I can display content in french if I set the locale to fr_CA (I18n::setLocale('fr_CA'))

But when I change my browser's language to fr_CA, it somehow changes the default locale as well to fr_CA. So the website displays in french, but the content still displays in english since it is now the default locale

Setting the default locale in config\app.php

'App' => [
    'namespace' => 'App',
    'encoding' => env('APP_ENCODING', 'UTF-8'),
    'defaultLocale' => env('APP_DEFAULT_LOCALE', 'en_US'),
    .....
],

Adding the valid locales in src\Application.php

$middlewareQueue->add(new LocaleSelectorMiddleware(['en_US', 'fr_CA']));

Adding the Translate behavior in ArticlesTable.php

$this->addBehavior('Translate', [
    'fields' => ['name', 'slug'],
    'allowEmptyTranslations' => false,
]);

Fetching the content in ArticlesController.php

$query = $this->Articles->find('all')
    ->where(['Articles.name !=' => ''])
    ->contain(['Media' => function ($q) {
        return $q->find('medium');
}]);

When my browser is in english (en_US) and I echo I18n::getDefaultLocale()

'en_US'

When it's in french (fr_CA) and I echo I18n::getDefaultLocale();

'fr_CA'

Note that I updated to CakePHP 3.5 recently and followed the guide to add the Middleware: Adding the new HTTP Stack to an Existing Application


Solution

That's a bug that will be fixed in the next release (3.5.3).

See https://github.com/cakephp/cakephp/pull/11200

Until this is fixed you can either apply the patch locally on own your own, or manually invoke \Cake\I18n\I18n::getDefaultLocale() once in your bootstrap so that the default locale is being stored before the modifications of the locale selector are being aplied.



Answered By - ndm
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Saturday, January 22, 2022

[FIXED] CakePHP actsAs Translate and $Model::find()

 January 22, 2022     cakephp, translate     No comments   

Issue

I have attached the Translate behavior to one of my models and I have some shortcomings regarding this:

1) If I don't save data in all fields passed as params when attaching the behavior to the model, $Model::find() method doesn't get the inserted rows.

public $actsAs = array(
    'Translate' => array(
        'title' => 'title_Translation',
        'description' => 'description_Translation',
        'description_long' => 'description_long_Translation'
    )
);

Ex: if i pass to $Model::save() method only a value for 'title', the data is saved, even in the i18n table, but the $Model::find() doesn't get anything. I must pass data for all the fields.

Can I force it to retrieve those records ?

2) How can I get all the records in the admin side of the application (regardless of the language in which a record is saved) in order to list them so the user can alter it (edit data, save data in multiple languages)? Right now, I can only get the records that correspond to the current language (read from Configure or set explicitly)..

Thank you!


Solution

OK, I might be a bit late, but anyway...

1) Cake uses an INNER JOIN when fetching a row and it's associated translations, so basically there's no easy way around this. You have to make sure you save every translatable field, every time - even if you just save it as blank. The only alternative would be to go hacking round the core to make it use a left join rather than an inner join - but don't do that.

2) The cookbook explains how to fetch all records here: http://book.cakephp.org/2.0/en/core-libraries/behaviors/translate.html#retrieve-all-translation-records-for-a-field

Now, probably most of the time you want to get just one translation, so you don't want to modify the definition of your $actsAs['Translate'] array in your model. So what I did, was set up a method in AppModel.php which modifies the $actsAs['Translate'] array on the fly:

/*  
 * See http://book.cakephp.org/2.0/en/core-libraries/behaviors/translate.html#using-the-bindtranslation-method
 * This is for making it so we fetch all translations, as opposed to just that of the current locale.
 * Used for eg. editing (multiple translations) via the admin interface.
 */
public function bindAllTranslations(){
    $translatableFields = $this->actsAs['Translate'];

    $keyValueFields = array();
    foreach($translatableFields as $field){
        $keyValueFields[$field] = $field.'Translation';
    }

    $this->bindTranslation($keyValueFields,false);  // false means it will be changed for all future DB transactions in this page request - and won't be reset after the next transaction.
}

So, if it's an admin method (or any other situation you want all translations) you call that code before doing a find:

$this->MyModel->bindAllTranslations();
$this->MyModel->find('all');

Hope that helps!



Answered By - joshua.paling
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home
View mobile version

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing