Symfony translations using PoEdit

For my Symfony project, that has to support two languages, I started with created a xliff file manually. This was really annoying. Not only the creation of the xml, but also the inability to see if you didn’t already translate this string. So, I wanted to use Poedit. But this wasn’t so easy.

I needed to create .po files, which are the uncompiled language files that contain all translations. Actually, a .pot file would even be better. I didn’t know how to extract the strings.

The LeaseWeb gettext bundle looked great, but I already had used normal translation strings in twig, like {% trans %} and {% endtrans %}. I didn’t want to refactor my whole project, just to be able to use gettext (with a third party bundle anyways). It might be a good option if you start your project from scratch though.

So then I found the Twig Gettext Extractor. This seemed rather complicated, as I never worked with Poedit before too. I am working on a Mac, and my code is on a virtual machine. This project seems to be about a tool that extracts the language strings from Twig. I decided to give it a try, and installed the project standalone.

When I tried to run through the project in Poedit, it came up with an error. I copy and pasted the commands in my terminal, and found out that it couldn’t render the Twig template, because I was using KnpPaginatorBundle. It didn’t understand a twig function that it was using.

Ok, fair enough, so I decided to add the bundle to my Symfony project. It didn’t help much: it was still throwing php errors, so it couldn’t extract anything.

Then I tried the JMSTranslationBundle for a second time. I had already tried this, but when I ran

as stated in the docs, it would output to xliff again. I don’t exactly remember why, but I installed the bundle again, and ran this extract again. This time, a .mo en .po file were present in my /Resource/translations bundle. To my great surprise, it now updated this .po file!

I was also surprised, because the website says the bundle doesn’t support .mo files.

 

Anyways, it turns out it is supported. At least on Symfony 2.3.6. The command you need to issue on an empty translations directory is this:

After that you can update your translations with this command:

Still, I think I am missing something in the workflow. When I add new strings to be translated to my project, the strings are added to the .po file, but they are not marked as “new” in Poedit. So it’s difficult to see what strings still need to be translated.

But, it’s much better than creating those language files by hand.

Created entities are all wrong

So I was performing a console doctrine:generate:entities for my bundle. The first thing I noticed is that it did’t create the appropriate getters and setters, especially for my OneToMany relations. The add and remove methods weren’t there.

So I started deleting all the methods, recreating them, and weird stuff kept happening. It even created some private properties that I didn’t define in my entity at all.

Eventually I found out that there was old ORM data in my project. Although I deleted the cache, this ORM data was still there. So, go to your bundle directory, and then to Resources/config/doctrine. Delete all the files in here. Then recreate your entities.

Raw mysql in Doctrine

To perform a raw mysql statement in symfony through Doctrine:

This example was being used in a controller.

Pass array of options to form builder

This post is just to archive a solution I used to pass an option list, to create a selectbox. The code I used to create the form type:

The setDefaultOptions method makes sure you pass the array of options. If you don’t, it will throw an exception.

Force Doctrine to close mysql connections

So I wrote a nice shell within app/console, which also used pcntl_fork(). Of course there was a very old archive somewhere in my mind that knew that this would mean trouble when you use mysql connections. But since I don’t explicitly use mysql_connect anymore, because Doctrine does this for me, I didn’t realise I faced the same problem as years ago.

When you fork a process with pcntl_fork(), it will copy the current process. This also contains the handles to your mysql connection. When the first child process dies, it will clean up these handles, and therefore close the connection.

Simple solution: make sure all connections are closed before you fork a child. That way, the child is forced to create a new connection.

I solved this using the following piece of code in the script.

 

Use Twig’s renderBlock to update a table row with AJAX

So I was developing a page with a table, where one could delete and edit the data on the table. Deleting was simple, it would do an AJAX request to delete, and then I’d remove the table row using jQuery.

But when you edit the row, you would also need to update the row after you did the edit. The table row was already defined in the twig template though, so couldn’t I just reuse it? Yes we can. This is probably rookie beginners stuff, but well, I’m still learning Symfony (and bootstrap, and basically all frontend stuff).

So, to illustrate, I had this piece of template in my page.

With jQuery, I had an event handler on the paginationContainer, to catch the edit button. This would open up a modal where the record can be edited. After that, the save button was pressed, which I was also catching using jQuery.

So this javascript code looked like this:

So the controller needed to just return the table row, as defined in the template at the beginning of the post. The code in the controller was like this:

 

Use KnpPaginatorBundle just for calculation

I was working on a table in Symfony where I needed to show a table. To add pagination without doing the hard work myself, I added KnpPaginatorBundle to my project. This worked really nice, and I had my tables paginated in no time. I just followed the example on the github page.

But then it gave me an error that looked much like this:

Not all identifier properties can be found in the ResultSetMapping: id

Right. So I googled the error message, and found that it had something to do with Doctrine, that could use Pagination if you select only specific fields of a table. And of course, that’s exactly what I did.

I built a repository class that would give me some results, based on a comprehensive html form. I would store the entire form in the database, to be able to reproduce the search, just by applying the search form again.

When processing the result, I already limited the search results though, using setFirstResult and setMaxResults. So it should be possible to create pagination.

Fortunately, I took a closer look to the paginator bundle, before I continued writing my own paginator code. I started with taking a look at the twig template, to give me inspiration on what variables my paginator should return. But then it seemed to me that KnpPaginatorBundle could do the math for me. All I had to do, is fill some variables my self.

So need to set:

  • the total number of records
  • the number of items on a page
  • the current page

Easy does it!

I ended up with the following code in my controller: