I was facing a typical issue in the internationalisation with cakephp.
My requirement was to render french characters in the normal flow.
My form fields were accepting the french characters in the normal flow. They were stored and retrieved normally.
But, in the Ajax flow, for eg in comments section, the french characters didnt reach the backend in the normal charset. I was breakinig my head very badly.
I found the solution in one of the forums. The problem was with the prototype.js file, where the character set was set as default to UTF-8. But the french characters need ISO-8859-1.
There are two solutions.
First Solution :
I could have updated to the latest version of the prototype.js and then try to send the encoding as a option in the ajax form field. That would have solved the problem. But I couldnt update to the latest file since I had so many stuff dependent on the existing version. I dont want to take any risk.
Second Solution:
The other option was really cool one.
$name = iconv("UTF-8", "windows-1256", $_POST['name']);
That is PHP gives you a method to convert the charset from any given charset to any required charset.
I simply used the iconv to fix the issue.
Wednesday, February 17, 2010
Tuesday, January 19, 2010
failed to open stream: Permission denied [CORE/cake/libs/file.php, line 146]
Warning (2): fopen(cakephp/app/tmp/cache/persistent/cake_core_dir_map) [function.fopen]: failed to open stream: Permission denied [CORE/cake/libs/file.php, line 146]
The main problem could be the access permission of the cache folder or the files within.
first try to set 777 permission to the app/tmp folder.
try clearing the cache.
If any of the persistent cache files have a different user say webadmin instead of apache, then that could result in these kind of issues
Monday, January 11, 2010
Common file extensions
Text Files
Data Files
Image Files
.doc | Microsoft Word Document |
.docx | Microsoft Word Open XML Document |
.log | Log File |
.msg | Outlook Mail Message |
.pages | Pages Document |
.rtf | Rich Text Format File |
.txt | Plain Text File |
.wpd | WordPerfect Document |
.wps | Microsoft Works Word Processor Document |
Data Files
.123 | Lotus 1-2-3 Spreadsheet |
.accdb | Access 2007 Database File |
.csv | Comma Separated Values File |
.dat | Data File |
.db | Database File |
.dll | Dynamic Link Library |
.efx | eFax Document |
.mdb | Microsoft Access Database |
.pps | PowerPoint Slide Show |
.ppt | PowerPoint Presentation |
.pptx | Microsoft PowerPoint Open XML Document |
.sdb | OpenOffice.org Base Database File |
.sdf | Standard Data File |
.sql | Structured Query Language Data |
.uccapilog | Microsoft UCC API Log File |
.vcf | vCard File |
.wks | Microsoft Works Spreadsheet |
.xls | Microsoft Excel Spreadsheet |
.xlsx | Microsoft Excel Open XML Document |
.xml | XML File |
Image Files
.pct | Picture File |
Raster Image Files
Vector Image Files
3D Image Files
Page Layout Files
.bmp | Bitmap Image File |
.gif | Graphical Interchange Format File |
.jpg | JPEG Image File |
.png | Portable Network Graphic |
.psd | Photoshop Document |
.psp | Paint Shop Pro Image File |
.thm | Thumbnail Image File |
.tif | Tagged Image File |
Vector Image Files
.ai | Adobe Illustrator File |
.drw | Drawing File |
.eps | Encapsulated PostScript File |
.ps | PostScript File |
.svg | Scalable Vector Graphics File |
3D Image Files
.3dm | Rhino 3D Model |
.dwg | AutoCAD Drawing Database File |
.dxf | Drawing Exchange Format File |
.pln | ArchiCAD Project File |
Page Layout Files
Adobe InDesign File | |
Portable Document Format File | |
.qxd | QuarkXPress Document |
.qxp | QuarkXPress Project File |
.rels | Open Office XML Relationships File |
Audio Files
Video Files
Web Files
Font Files
Plugin Files
Advanced Audio Coding File | |
.aif | Audio Interchange File Format |
.iff | Interchange File Format |
.m3u | Media Playlist File |
.mid | MIDI File |
.midi | MIDI File |
.mp3 | MP3 Audio File |
.mpa | MPEG-2 Audio File |
.ra | Real Audio File |
.wav | WAVE Audio File |
.wma | Windows Media Audio File |
Video Files
.3g2 | 3GPP2 Multimedia File |
.3gp | 3GPP Multimedia File |
.asf | Advanced Systems Format File |
.asx | Microsoft ASF Redirector File |
.avi | Audio Video Interleave File |
.flv | Flash Video File |
.mov | Apple QuickTime Movie |
.mp4 | MPEG-4 Video File |
.mpg | MPEG Video File |
.rm | Real Media File |
.swf | Flash Movie |
.vob | DVD Video Object File |
.wmv | Windows Media Video File |
Web Files
Active Server Page | |
.css | Cascading Style Sheet |
.htm | Hypertext Markup Language File |
.html | Hypertext Markup Language File |
.js | JavaScript File |
.jsp | Java Server Page |
.php | Hypertext Preprocessor File |
.rss | Rich Site Summary |
.tvpi | TitanTV Television Listing File |
.tvvi | TitanTV Television Listing File |
.xhtml | Extensible Hypertext Markup Language File |
Font Files
.fnt | Windows Font File |
.fon | Generic Font File |
.otf | OpenType Font |
.ttf | TrueType Font |
Plugin Files
.8bi | Photoshop Plug-in |
.plugin | Mac OS X Plug-in |
.xll | Excel Add-In File |
System Files
.cab | Windows Cabinet File |
.cpl | Windows Control Panel |
.cur | Windows Cursor |
.dmp | Windows Memory Dump |
.drv | Device Driver |
.key | Security Key |
.lnk | File Shortcut |
.sys | Windows System File |
Executable Files
Mac OS X Application | |
.bat | DOS Batch File |
.cgi | Common Gateway Interface Script |
.com | DOS Command File |
.exe | Windows Executable File |
.pif | Program Information File |
.vb | VBScript File |
.ws | Windows Script |
Compressed Files
Encoded Files
Developer Files
.7z | 7-Zip Compressed File |
.deb | Debian Software Package |
.gz | Gnu Zipped File |
.pkg | Mac OS X Installer Package |
.rar | WinRAR Compressed Archive |
.sit | Stuffit Archive |
.sitx | Stuffit X Archive |
.zip | Zipped File |
.zipx | Extended Zip File |
Encoded Files
Macbinary II Encoded File | |
.hqx | BinHex 4.0 Encoded File |
.mim | Multi-Purpose Internet Mail Message |
.uue | Uuencoded File |
Developer Files
.c | C/C++ Source Code File |
.cpp | C++ Source Code File |
.java | Java Source Code File |
.pl | Perl Script |
Backup Files
.asd | Microsoft Word AutoSave File |
.bak | Backup File |
.bup | Backup File |
.gho | Norton Ghost Backup File |
.ori | Original File |
.tmp | Temporary File |
Disk Files
Game Files
Misc Files
.dmg | Mac OS X Disk Image |
.iso | Disc Image File |
.toast | Toast Disc Image |
.vcd | Virtual CD |
Game Files
.gam | Saved Game File |
.nes | Nintendo (NES) ROM File |
.rom | N64 Game ROM File |
.sav | Saved Game |
Misc Files
.msi | Windows Installer Package |
.part | Partially Downloaded File |
.torrent | BitTorrent File |
.yps | Yahoo! Messenger Data File |
Tuesday, January 5, 2010
Internationalisation and Localisation in CakePHP
CakePHP tutorial on this http://book.cakephp.org/complete/161/Internationalization-Localization should be enough.
I should preface this post by saying that it does not cover the basics of i18n and l10n so, please, first take a look at the manual on how to get the basics going.
To better understand the goal and why some things were done the way they were, I’ll summarize the requirements:
The app has to support two languages or more (in this case English and Russian)
Default language is English
The language switching is based on a URL param
The URL format should be: example.com/eng/controller/action
Language choice should persist in the session and a cookie
Just a note here… there are other ways to determine the language requested by the user, for example it could come from a domain name like eng.example.com or rus.example.com. Hopefully the approach outlined here will also be helpful if other methods of language switching are used in your app…
Also, worth while to mention, that having language name in the URL (as opposed to just reading it from the session or cookie) helps with SEO… I won’t bore you here with details, but basically it helps to ensure that a variation of each page, based on the language param in the URL, is properly indexed by the search engines. Thus, each indexed page can be found later in the native language of the user.
Last, but not least, CakePHP uses three letter language name abbreviation, based on this, so I figure, should be fine to use the same in the URL’s.
Alright, so looking at the URL format, instantly raises a question… how do we tack on the language name to the “front” of each URL?
Thankfully the Router accomplishes that pretty easily (in app/config/routes.php):
Router::connect('/:language/:controller/:action/*',
array(),
array('language' => '[a-z]{3}'));
It takes a ‘language’ parameter and throws it to the front of the URL, just as we need it.
Now, we need to specify a default language to use, I just add this to my app/config/core.php
Configure::write('Config.language', 'eng');
So, when someone comes to the http://example.com/users/home, the site is displayed in English by default. Then we usually see a link somewhere (with a little flag next to it :)), to switch to another language.
In cake we can make those language-switching links like this:
$html->link('Русский', array('language'=>'rus'));
Notice that we set the language param, which we’ll rely on to do our switching. Providing no other params, will simply reload the current page (in the new language) with the param tacked to the front of the URL (more about this later).
Side note, it’s not a good idea to use the __() translation function on language-switching links… If I get to the site and it’s displayed in the language I can’t understand even remotely, the only savior would be a link in my native language, which indicates that i can switch to it (and well, a little flag would help too :))
So now we actually need the code to switch the language, when a user clicks on the link, like above.
It’s best done in the App Controller, kinda like here:
var $components = array('Session', 'Cookie');
function beforeFilter() {
$this->_setLanguage();
}
function _setLanguage() {
if ($this->Cookie->read('lang') && !$this->Session->check('Config.language')) {
$this->Session->write('Config.language', $this->Cookie->read('lang'));
}
else if (isset($this->params['language']) && ($this->params['language']
!= $this->Session->read('Config.language'))) {
$this->Session->write('Config.language', $this->params['language']);
$this->Cookie->write('lang', $this->params['language'], null, '20 days');
}
}
Let’s take a look at the code quickly and consider some scenarios…
I created a separate method _setLanguage();, the reason I like doing this is that it keeps the beforeFilter() cleaner, which already has enough crap in there usually.
Secondly, it can be overridden in the child controllers, if required.
So let’s consider some user-case scenarios:
The user comes to the site for the very first time
In this case the default language is read from the core.php file, so the site is set to English
The user starts clicking around the site for the very first time in his native English
Nothing really needs to be done, so we can happily skip that part
The user comes to the site and has to switch the language to Russian
Thankfully he sees a link to do so, and clicks on it. Now we check our else if, since no cookie or session with configured language exist yet. We see that the link has a /rus/ param in the URL and it is not yet stored in the session, therefore we write the new value of the default language to the session and the cookie.
The above user browses around the site, leaves, and then comes back
The session value is still present and therefore the site is automagically translated to Russian. This is good if the user forgot or doesn’t care to use links like example.com/rus/controller/action, because even plain links like example.com/controller/action will display the site in the right language because of the session value.
The above user closes the browser, goes out hunting for wild boars, and comes to the site on some other day
Now we rely on our previously stored cookie to read in the language and ensure we don’t override anything that might be in the session already. (the first if )
Now if the user decides to read the site in English
We pretty much follow through the same steps as above.
Now the last thing we need to do is to ensure that a URL param gets automatically added to all the links on the site, if a given language is chosen. Remember, that this is important to have such links for SEO as well.
Well, we’re sure as hell not going to supply the ‘language’ param manually to each link, so let’s override the cake’s default url() method to ensure the language param is now added to all links.
We create app_helper.php in /app/ (same place for app_controller.php and app_model.php), something like this:
class AppHelper extends Helper {
function url($url = null, $full = false) {
if(!isset($url['language']) && isset($this->params['language'])) {
$url['language'] = $this->params['language'];
}
return parent::url($url, $full);
}
}
Basically we check if ‘language’ param is already in the URL if it is, we don’t need to worry about it.
If not, and $this->params['language'] is available we pre-pend the required language to the URL.
The rest of the site, and all standard links will now include that ‘language’ param at the front of the URL (again, good for SEO).
And that’s pretty much it, even though the post was a bit long-winded (and beer to you, if you’ve made through the whole thing) it is quite nice to be able to do i18n & l10n in just about 15 lines of code.
A little disclaimer: even though the code seems to work fine, it is still experimental… so if you find some problems I haven’t yet encountered, please be sure to let me know.
P.S. Here’s a sampe test view, from which you can generate your .po files (easily done with cake i18n console command, but this is a topic for another tutorial and there are plenty of them “out there”).
Source :
http://teknoid.wordpress.com/2008/11/28/cakephp-url-based-language-switching-for-i18n-and-l10n-internationalization-and-localization/
Once this is done, we need to make sure the character set is proper.
We need to find the corresponding characterset of every language that we are going to translate and use the charsets accordingly.
The bootstrap file can detect the language or condition and then set the character set like this.
Configure::write('App.encoding', 'ISO-8859-1');
The database setting in the database.php in app/config should have the config element
encoding with proper character set.
'encoding' => "UTF-8"
If all of the above steps are followed, hopefully the internationalization should work.
I should preface this post by saying that it does not cover the basics of i18n and l10n so, please, first take a look at the manual on how to get the basics going.
To better understand the goal and why some things were done the way they were, I’ll summarize the requirements:
The app has to support two languages or more (in this case English and Russian)
Default language is English
The language switching is based on a URL param
The URL format should be: example.com/eng/controller/action
Language choice should persist in the session and a cookie
Just a note here… there are other ways to determine the language requested by the user, for example it could come from a domain name like eng.example.com or rus.example.com. Hopefully the approach outlined here will also be helpful if other methods of language switching are used in your app…
Also, worth while to mention, that having language name in the URL (as opposed to just reading it from the session or cookie) helps with SEO… I won’t bore you here with details, but basically it helps to ensure that a variation of each page, based on the language param in the URL, is properly indexed by the search engines. Thus, each indexed page can be found later in the native language of the user.
Last, but not least, CakePHP uses three letter language name abbreviation, based on this, so I figure, should be fine to use the same in the URL’s.
Alright, so looking at the URL format, instantly raises a question… how do we tack on the language name to the “front” of each URL?
Thankfully the Router accomplishes that pretty easily (in app/config/routes.php):
Router::connect('/:language/:controller/:action/*',
array(),
array('language' => '[a-z]{3}'));
It takes a ‘language’ parameter and throws it to the front of the URL, just as we need it.
Now, we need to specify a default language to use, I just add this to my app/config/core.php
Configure::write('Config.language', 'eng');
So, when someone comes to the http://example.com/users/home, the site is displayed in English by default. Then we usually see a link somewhere (with a little flag next to it :)), to switch to another language.
In cake we can make those language-switching links like this:
$html->link('Русский', array('language'=>'rus'));
Notice that we set the language param, which we’ll rely on to do our switching. Providing no other params, will simply reload the current page (in the new language) with the param tacked to the front of the URL (more about this later).
Side note, it’s not a good idea to use the __() translation function on language-switching links… If I get to the site and it’s displayed in the language I can’t understand even remotely, the only savior would be a link in my native language, which indicates that i can switch to it (and well, a little flag would help too :))
So now we actually need the code to switch the language, when a user clicks on the link, like above.
It’s best done in the App Controller, kinda like here:
var $components = array('Session', 'Cookie');
function beforeFilter() {
$this->_setLanguage();
}
function _setLanguage() {
if ($this->Cookie->read('lang') && !$this->Session->check('Config.language')) {
$this->Session->write('Config.language', $this->Cookie->read('lang'));
}
else if (isset($this->params['language']) && ($this->params['language']
!= $this->Session->read('Config.language'))) {
$this->Session->write('Config.language', $this->params['language']);
$this->Cookie->write('lang', $this->params['language'], null, '20 days');
}
}
Let’s take a look at the code quickly and consider some scenarios…
I created a separate method _setLanguage();, the reason I like doing this is that it keeps the beforeFilter() cleaner, which already has enough crap in there usually.
Secondly, it can be overridden in the child controllers, if required.
So let’s consider some user-case scenarios:
The user comes to the site for the very first time
In this case the default language is read from the core.php file, so the site is set to English
The user starts clicking around the site for the very first time in his native English
Nothing really needs to be done, so we can happily skip that part
The user comes to the site and has to switch the language to Russian
Thankfully he sees a link to do so, and clicks on it. Now we check our else if, since no cookie or session with configured language exist yet. We see that the link has a /rus/ param in the URL and it is not yet stored in the session, therefore we write the new value of the default language to the session and the cookie.
The above user browses around the site, leaves, and then comes back
The session value is still present and therefore the site is automagically translated to Russian. This is good if the user forgot or doesn’t care to use links like example.com/rus/controller/action, because even plain links like example.com/controller/action will display the site in the right language because of the session value.
The above user closes the browser, goes out hunting for wild boars, and comes to the site on some other day
Now we rely on our previously stored cookie to read in the language and ensure we don’t override anything that might be in the session already. (the first if )
Now if the user decides to read the site in English
We pretty much follow through the same steps as above.
Now the last thing we need to do is to ensure that a URL param gets automatically added to all the links on the site, if a given language is chosen. Remember, that this is important to have such links for SEO as well.
Well, we’re sure as hell not going to supply the ‘language’ param manually to each link, so let’s override the cake’s default url() method to ensure the language param is now added to all links.
We create app_helper.php in /app/ (same place for app_controller.php and app_model.php), something like this:
class AppHelper extends Helper {
function url($url = null, $full = false) {
if(!isset($url['language']) && isset($this->params['language'])) {
$url['language'] = $this->params['language'];
}
return parent::url($url, $full);
}
}
Basically we check if ‘language’ param is already in the URL if it is, we don’t need to worry about it.
If not, and $this->params['language'] is available we pre-pend the required language to the URL.
The rest of the site, and all standard links will now include that ‘language’ param at the front of the URL (again, good for SEO).
And that’s pretty much it, even though the post was a bit long-winded (and beer to you, if you’ve made through the whole thing) it is quite nice to be able to do i18n & l10n in just about 15 lines of code.
A little disclaimer: even though the code seems to work fine, it is still experimental… so if you find some problems I haven’t yet encountered, please be sure to let me know.
P.S. Here’s a sampe test view, from which you can generate your .po files (easily done with cake i18n console command, but this is a topic for another tutorial and there are plenty of them “out there”).
Source :
http://teknoid.wordpress.com/2008/11/28/cakephp-url-based-language-switching-for-i18n-and-l10n-internationalization-and-localization/
Once this is done, we need to make sure the character set is proper.
We need to find the corresponding characterset of every language that we are going to translate and use the charsets accordingly.
The bootstrap file can detect the language or condition and then set the character set like this.
Configure::write('App.encoding', 'ISO-8859-1');
The database setting in the database.php in app/config should have the config element
encoding with proper character set.
'encoding' => "UTF-8"
If all of the above steps are followed, hopefully the internationalization should work.
Clear SVN Lock error
When we have a script in place to run the SVN update commands and they give a svn lock error, then the issue could be mainly because of the directory permissions.
When some one ssh to the server box and edit something over there directly, the file permission get changed from apache to root. So when we execute the SVN update command through the script, the svn shows a lock error.
If the lock error specifies a folder then we can ssh to the server and then browse to the corresponding directory and then change the file user to apache again.
For eg cd /var/www/html
chown -R apache:apache app/
This should work.
When some one ssh to the server box and edit something over there directly, the file permission get changed from apache to root. So when we execute the SVN update command through the script, the svn shows a lock error.
If the lock error specifies a folder then we can ssh to the server and then browse to the corresponding directory and then change the file user to apache again.
For eg cd /var/www/html
chown -R apache:apache app/
This should work.
Subscribe to:
Posts (Atom)