We're developing a multi-language website and in case of changes to the original text (English) they shouldn't appear on the site until all of the localized entries are changed accordingly. I don't think that's possible to do with gettext/POEdit alone (?). Another thing is concurrency of translation. If a bunch of people would edit the same gettext files on their PCs and then upload the changes to SVN, the situation when some translations were done by many people is inevitable.
Therefore it seems to be a good idea to store changed phrases in the database and once every language has its translation, make changes to po/mo files so that there is at every moment just actual information on the site.
Is it possible to make changes to gettext translation files with PHP? If not, should we forsake gettext in lieu of storing everything in the database?
Thanks
Well, I've tried a bunch of stuff and it seems that PEAR File/Gettext is the way to go. I seems to be kind of abandoned and files, created by POEdit and File/Gettext aren't binary similar, but I've checked the differences and they are mostly in metadata (which isn't needed for the proper functioning either way), except the hashtable, which isn't handled in the PHP package, but the docs for the mo state that the hashtable isn't required either and it's questionable whether is must be contained in those files :)
Related
I have a multi language website written in CakePHP 1.3 and I'm currently in the process of adding a new language. I have the original .pot file and I generated a new .po file for the given language. So far so good, it's all working, however, now someone has to do the actual translation. I've send them the relevant .po file with explanations what to do but they seem to have problems dealing with plain text file. Is there a user friendly tool or piece of code that would actually allow them to translate the phrases one by one, without having to deal with text files?
You need a po editor. There are many out there for various platforms. Some free, some not. They usually provide a simple interface for viewing all the available translation strings and adding the translation next to them without need for viewing the po file in a text editor. My understanding is that many translators are familiar with this type of software so may already have one installed.
Check out this Stack Overflow question and answers for suggestions:-
What good alternatives to poEdit are there?
I knew that PHP is able to read file content by different ways, for example: fread, file_get_contents, file, readfile, etc.
Currently, I am looking for an API that can read real index of files and folders in specific partition or folder, for example:
drive d:\ in windows contains three folders (folder1, folder2, folder3), and each folder contains some files, we can get these directory structure using PHP (opendir, scandir, readdir, etc) and list them as I want, however, windows saved file and folder names inside hard-disk with their attributes (size, last modified, created on, etc).
How I can read hard-disc using PHP and retrieving all file and folder attributes for a specific path?
for instance, if we consider last modified time we can use (filemtime()) function, but this attribute not saved inside the file, its saved some where else inside hard-drive, other attributes also saved in other location not inside the file.
When windows user copying file from flash-drive to local hard, windows will copy all file and folder attributes and saves them inside local hard drive. When using PHP for copying file, it depends on OS to handle this job, its not native support (as I think) for file and folder operations.
Do you have any idea?
There are many recovery program that uses this technology for reading hard-drive indexes, however, for PHP: I cant find any source for this problem.
Applications if I get correct answer:
I can check if such file securely deleted from my hard-drive? I can create secure delete application using PHP, or clearing hard-drive indexes for a given file.
Your help appreciated.
Problems with the proposition
The attributes of files, such as timestamps, permission flags etc, are stored in the file system (FAT, NTFS, Ext3 etc). As you say some of them can be read using PHPs different file and directory methods, but they all act through the OS file system abstraction and cant have access to block level information on the disk, such as what precise byte on disk stores the archive flag for file X. The whole point of the OS and FS is to abstract away this information from the user/client programs.
As suggested there are external tools, written in c or similar, that does have this access and that you can call from inside PHP. If you want a 'native' PHP way of doing this you'll have to compile a c extension for PHP that exposes these low level functions to you.
I'd say external tools is the way to go if you want to stick with PHP but for the task at hand, as far as we can see from your description, I'd go with another language that has more low level access. Like C or C++. PHP is a high level language for HTML pre processing and as such is a poor choice for low level system programming.
Practical advice
After looking through the PHP documentation and assorted third party libraries:
An of the shelf solution for reading file system information on a file allocation table level doesn't exist for PHP. The lowest level you get is the fstat() function, and that is not very far for what you want.
External tools
No mater exactly what you want to do there is probably a small binary that does it. PHP can be integrated with these programs, as suggested elsewhere, via the exec() function. This is probably the easiest approach for you unless you have serious amounts of time and/or development resources to devote to this problem.
Wrapping a library
There are libraries that solves this problem for you, written in low level languages. An open source library can be wrapped with SWIG to expose it to PHP. This will give you access to the low level methods you need, but it's a non trivial task. These kind of libraries also often require sole access to the device while they work on it, something that is difficult to achieve in most normal operating environments.
Note also that you will probably need a library per file system. Microsofts VFAT extension to FAT12/16/32 requiers a licens to use. So if you want to work with FAT and have files with long names (not 8.3 format) you'll have to fork up some dough to be legit.
Low level implementation
A last middle ground would be to write your own CLI tool that uses an external library to access the low level FS functions. You can then use exec() from inside PHP to interact with your own implementation.
This might be a reasonable path if you cant find an existing tool that solves your problem and you are not willing to spend the time to wrap a library.
In closing
You give a very narrow problem description with little to go on as for what the application is about. A broader discussion (in another forum) might yield better results since the problem might be better solved in another way entirely.
I found something on PHP.net which appears to do what you want:
http://php.net/manual/en/function.readdir.php#103418
Edit: I mis-understood the question. Attributes such as the last modified time, last accessed date and the like are stored in the file systems master file table. As far as I can tell, this isn't accessible with PHP, and if you were to write your own method to do this then you'd also have to account for different file systems as they all handle the storage of these attributes in their own unique way.
It could be that to get all of the information you're looking for is not possible with PHP without writing some form of extension to PHP itself.
Edit 2: Upon researching a little more...
http://php.net/manual/en/function.fileinode.php
This function could be an interesting one to look at.
Well if I understand correctly you just want to securely delete a file. You can just call [shred][1]
[1]: http://linux.die.net/man/1/shred via system or exec if you are on linux and you are good to go
Setting up the multi language site I now need to decide which option I need to use for static text on the site. Let me explain my site setup and then if you can help me decide which solution to use.
The site is a CMS system that allows multiple domains to point to the same directory and serves content based on the domain name. So all domains share the same code. On the site I created blocks of code, called modules, that do specific jobs. So I might have a module that all it does is display the latest news from the database. I then can decide what page that module can display on and what site it will display on. So my question is, would gettext work for multiple domains that may have different modules showing up on different pages? Or should I just create a language file for each module that contains an array which has the language conversation for that specific module? So if I had 10 modules, each module would have its own language file and whatever page each module shows up it just refers to the array in the language file for that module to decide what text to show? Hope this makes sense, I read a lot about gettext and using the array version, but cant decide which one is better for this type of site setup.
A lot of CMS uses the array version. I have seen GetText as well for scalable applications. The array version is simpler especially when you want to manage the translation from a web interface.
It is a matter of preference of course.
In my opinion PHP gettext is the way to go. In all my projects I use the wordpress style for translation. http://codex.wordpress.org/Translating_WordPress and using the same functions naming convention:
__('message') // Return the translation
_e('message') // echo's the translation
_n('singular_message', 'plural_message', count ) // return singular or plural
I use poedit http://www.poedit.net/ to extract translatable strings from the PHP source and translate them to other languages. Storing and compiling the files in the required PHP gettext directory structure like this:
en_US/LC_MESSAGES/default.mo
nl_NL/LC_MESSAGES/default.mo
de_DE/LC_MESSAGES/default.mo
Note that .mo files are cached by PHP and changes in your .mo file are non existing until you restart the webserver. Pulling my hair out while developing I came across this very helpfull solution: http://blog.ghost3k.net/articles/php/11/gettext-caching-in-php
The whole gettext thing took me a while to work it out, but is was worth it. Once in place it saved me a great deal of time and allowed my clients to do the translation for their projects themselves.
If you want to activate a community for translating your project have a look at the web based translation tool Pootle.
In my experience, raw gettext isn't terribly well suited for a web site context where content changes over time and usually outside of a formal release cycle.
I'd recommend that you take a look at Zend_Translate (and Zend_Locale, if you want to localize dates, numbers, etc). Zend_Translate is a higher-level library that has adapters for various underlying methods (including gettext and arrays).
It's fairly well documented, and can be used as a standalone component.
In fact, I find gettext easier:
You can just echo / print _("your text"); and translate later
It is easy to be helped with getext editors
To generate the boostrap po file (iirc, the /source/ file), you can use etags that will make a kind of grep on your files. So you'll just have to translate tokens later.
So basically, everything works since the beginning of the project, it is then easier to start, and more convenient for upscale.
I would recommend using gettext. It's a well-established set of tools. There is a tool to automatically extract text strings from your source code (xgettext) and there are other tools that help you with translating your localization files, for example, poedit ( http://www.poedit.net/ ).
If you are running PHP 5.3 and/or have the intl extension installed, there's another option, too: messageformatter:
http://php.net/manual/en/class.messageformatter.php
This is very powerful, but it lacks -- in my opinion -- a little bit of documentation and might be overkill for your purpose. You can find some more information about this at the ICU project's page:
http://userguide.icu-project.org/formatparse/messages
A friend of mine asked me to help him edit and add content to his PHP website. It was originally created by a professional company which has now became his opponent.
I thought it would be easy to edit some texts and adding content based on an original template. I downloaded all the files from a server, but couldn't find any files that contained the text I wanted to edit.
How could I use the text search keyword in all those files: PHP & JS without opening them one by one to find it as it seems to having too many files related with one simple website?
What is the best way to check whether or not I am in need of the original files in order to finish this project?
This doesn't sound like a programming question.
Searching the files largely depends on what operating system you're using and what tools you have available. There are many tools such as grep/awk on Unix/Linux systems, and file search tools on Windows and Mac.
The text you want to edit may be stored in a database. Often, PHP sites are part of a LAMP (Linux, Apache, MySQL, PHP) stack with MySQL being the database layer. If this is the case, you would need to get the information from the database, too.
This definitely not a programming question as calvinf said .... and there are tools you can use to search keywords in all the files of your project...
Try Zend Studio and after making a project in it search for your keywords in All Files option...
Another possibility you would not be able to find files is because the text might be saved in the db and extracted at the runtime...
so in my opinion if later is the case you would have to have a look at the templates stored in your db...
But i won't mind to have a go at Zend if i were you, anyways.
I'm writing a CMS on PHP+MySQL. I want it to be self-updatable (throw one click in admin panel). What are the best practices?
How to compare current version of cms and a version of the update (application itself and database). Should it just download zip archive, upzip it and overwrite files? (but what to do with files that are no longer used). How to check if an update is downloaded correctly? Also it supports modules and I want this modules to be downloadable from the admin panel of cms.
And how should I update MySQL tables?
Keep your code in a separate location from configuration and otherwise variable files (uploaded images, cache files, etc.)
Keep the modules separate from the main code as well.
Make sure your code has file system permissions to change itself (use SuPHP for example).
If you do these, simplest would be to completely download the new version (no incremental patches), and unzip it to a directory adjacent to the one containing the current version. Because there won't be variable files inside the code directory, you can just remove or rename the old one and rename the new one to replace it.
You can keep the version number in a global constant in the code.
As for MySQL, there's no other way than making an upgrade script for every version that changes the DB layout. Even automatic solutions to change the table definition can't know how to update the existing data.
A slightly more experimental solution could be to use something like the phpsvnclient library.
With features:
List all files in a given SVN repository directory
Retrieve a given revision of a file
Retrieve the log of changes made in a repository or in a given file between two revisions
Get the repository latest revision
This way you can see if there are new files, removed files or updated files and only change those in your local application.
I recon this will be a little harder to implement, but the benefit would probably be that it is easier and quicker to add updates to your CMS.
You have two scenarios to deal with:
The web server can write to files.
The web server can not write to files.
This just dictates if you will be decompressing a ZIP file or using FTP to update the files. In ether case, your first step is to take a dump of the database and a backup of the existing files, so that the user can roll back if something goes horribly wrong. As others have said, its important to keep anything that the user will likely customize out of the scope of the update. Wordpress does this nicely. If a user has made changes to core logic code, they are likely smart enough to resolve any merge conflicts on their own (and smart enough to know that a one click upgrade is probably going to lose their modifications).
Your second step is to make sure that your script doesn't die if the browser is closed. This is a process that really should not be interrupted. You could accomplish this via ignore_user_abort(true);, or some other means. Or, if you like, allow the user to check a box that says "Keep going even if I get disconnected". I'm assuming that you'll be handling errors internally.
Now, depending on permissions, you can either:
Compress the files to be updated to the system /tmp directory
Compress the files to be updated to a temporary file in the home directory
Then you are ready to:
Download and decompress the update en situ , or in place.
Download and decompress the update to the system's /tmp directory and use FTP to update the files in the web root
You can then:
Apply any SQL changes as needed
Ask the user if everything went OK
Roll back if things went badly
Clean up your temp directory in the system /tmp directory, or any staging files in the user's web root / home directory.
The most important aspect is making sure you can roll back changes if things went bad. The other thing to ensure is that if you use /tmp, be sure to check permissions of your staging area. 0600 should do nicely.
Take a look at how Wordpress and others do it. If your choice of licenses and their's agree, you might even be able to re-use some of that code.
Good luck with your project.
There is a SQL library called SQLOO (that I created) that attempts to solve this problem. It's a little rough still, but the basic idea is that you setup the SQL schema in PHP code and then SQLOO changes the current database schema to match the code. This allows for the SQL schema and attached PHP code to be changed together and in much smaller chunks.
http://code.google.com/p/sqloo/
http://code.google.com/p/sqloo/source/browse/#svn/trunk/example <- examples
Based on experience with a number of applications, CMS and otherwise, this is a common pattern:
Upgrades are generally one-way. It's possible to take a snapshot of full system state for a restore upon failure, but to restore usually entails losing any data/content/logs added to the system since the upgrade. Performing an incremental rollback can put data at risk if something were not converted properly (e.g. database table changes, content conversions, foreign key constraints, index creation, etc.) This is especially true if you've made customizations that rollback scripts couldn't possibly account for.
Upgrade files are packaged with some means of authentication/verification, such as md5 or sha1 hashes and/or digital signature to ensure it came from a trusted source and was not tampered. This is particularly important for automated upgrade processes. Suppose a hacker exploited a vulnerability and told it to upgrade from a rogue source.
Application should be in an offline mode during the upgrade.
Application should perform a self-check after an upgrade.
I agree with Bart van Heukelom's answer, it's the most usual way of doing it.
The only other option would be to turn your CMS into a bunch of remote Web Services/scripts and external CSS/JS files that you host in one location only.
Then everyone using your CMS would connect to your central "CMS server" and all that would be on their (calling) server is a bunch of scripts to call your Web Services/scripts that do all the processing and output. If you went down this route you'd need to identify/authenticate each request so that you returned the corresponding data for the given CMS user.