.PO to .MO - Programmatic Conversion (PHP) - php

I am planning to allow users to generate .POT files/.PO files through a PHP user interface as part of CMS solution. Once these files have been generated (the easy bit) I would like to allow my system to automatically convert these files into .MO files in response to a user (POST) request.
I have seen the following question on SO:
.po to .mo convertor in php?
I understand that I could run msgfmt by using PHP's exec() function, but that seems to be a Linux only solution, if I am correct? How would I do this on other operating systems? Some example code of how this may be done in practice would also be really useful, if anybody would be kind enough to demonstrate. This is quite different from the work I usually do!
This is only a concept at the moment but I hope I'm going along the right lines. If there are any additional thoughts/suggestions you have regarding this method, I'd be glad to hear them. Background information follows.
Additional Background Information - Not required:
I am retrieving the original English text by parsing simple template files that consist of nothing more than basic HTML and calls to <?php _('the gettext method'); ?>. These templates are parsed when edited/saved and the language entries are retrieved. The .POT file will then be generated. The user would now have to edit translations manually (through a simple interface, not directly) to update/prepare all the .PO files. Once this is done, I would need to be able to convert them to .MO files, as is the title of my question.

There are also PHP-only reimplementations of msgfmt if that is what you are looking for:
php-msgfmt
php.mo/gh
As alternative there would also be the Translate/Pootle webapp, with its php2po script, but there must also be some .mo conversion functions in it... (Ooops no, it's in Python.)

Both PHP's exec and the msgfmt GNU gettext utility are not a linux only solution. They work on multiple computer systems. As with PHP you can compile for multiple platforms (as it's done naturally), so the exec command is available on mutliple systems, the same applies to msgfmt. Start on the GNU gettext homepage to obtain a version for your system.

try https://github.com/oscarotero/Gettext.git
use Gettext\Translations;
chdir('....');
$translations = Translations::fromPoFile('messages.po');
$translations->toMoFile('messages.mo');

Related

PHP as independent application ( binary, compile, pack, no php on host )

If I would like to distribute PHP application with installer(package system of OS) how should I proceed? I don't want PHP files to be there, just working application, so when I type 'app' into console, it ends up being launching application, without need to install PHP on system(no php installation on host required). I would also like the application to have patch-able byte-code, so it's in parts, loaded when needed and only part needs to be replaced on update.
What I would do now is following:
->Compile PHP with extensions for specific platform.
->Make binary application which launches '/full/php app' when app is launched.
->Pack it in installer in a way, that there would be binary added to path when added, launching specific installation of PHP which is alongside the app with argument of start point->App would be running.
Problem is:
Maybe I don't want my PHP files to be exposed(in application, there will be available source anyway) is there some ready made stuff to do this? Is there some better way than I proposed?
Alternative: Modifying OP Cache to work with "packing" application to deliver byte codes to modified OP Cache which just reads the cache.
My suggestion would be a tiny tool I just finished, for almost exactly the same problem. (Oh yes I tried all the others but they're old and rusty, sometimes they're stuck with 4.x syntax, have no support, have no proper documentation, etc)
So here's RapidEXE:
http://deneskellner.com/sw/rapidexe
In the classical way, it's not a really-real compiler, just a glorified packer, but does exactly what you need: the output exe will be standalone, carrying everything with it and transparently building an ad-hoc runtime environment. Don't worry, it all happens very fast.
It uses PHP 7.2 / Win64 by default but has 5.x too, for XP compatibility.
It's freeware, obviously. (MIT License.)
(Just telling this because I don't want anyone to think I'm advertising or something. I just took a few minutes to read the guidelines about own-product answers and I'm trying to stay within the Code of the Jedi here.)
However...
I would also like the application to have patch-able byte-code, so it's in parts, loaded when needed and only part needs to be replaced on update.
It's easier to recompile the exe. You can extract the payload pieces of course but the source pack is one big zip; there seems to be no real advantage of handling it separately. Recompiling a project is just one command.
Maybe I don't want my PHP files to be exposed(in application, there will be available source anyway)
In this case, the exe contains your source compressed but eventually they get extracted into a temp folder. They're deleted immediately after run but, well, this is no protection whatsoever. Obfuscation seems to be the only viable option.
If something goes wrong, feel free to comment or drop me a line on developer-at-deneskellner-dot-com. (I mean, I just finished it, it's brand new, it may misbehave so consider it something like a beta for now.)
Happy compiling!
PHP doesn't do that natively, but here are a few ideas:
Self-extracting archive
Many archival programs allow you to create a self-extracting archive and some even allow to run a program after extraction. Configure it so that it extracts php.exe and all your code to a temp folder and then runs ir from there; deleting after the script has complete.
Transpilers/compilers
There's the old HPHC which translates PHP code to C++, and its wikipedia age also contains links to other, similar projects. Perhaps you can take advantage of those.
Modified PHP
PHP itself is opensource. You should be able to modify it withot too much difficulty to take the source code from another location, like some resource compiled directly inside the php.exe.
Use Zend Guard tool that compiles and converts the plain-text PHP scripts into a platform-independent binary format known as a 'Zend Intermediate Code' file. These encoded binary files can then be distributed instead of the plain text PHP. Zend Guard loaders are available for Windows and Linux platform that enables PHP to run the scripts encoded by Zend Guard.
Refer to http://www.zend.com/en/products/zend-guard
I would like to add another answer for anyone who might be Googling for answers.
Peach Pie compiler/runtime
There is an alternative method to run (and build apps from) .php source codes, without using the standard php.exe runtime. The solution is based on C#/.NET and is actually able to compile php source files to .NET bytecode.
This allows you to distribute your program without exposing its source code.
You can learn more about the project at:
https://www.peachpie.io/
You've got 3 overlapping questions.
1. Can I create a stand-alone executable from a PHP application?
Answered in this question. TL;DR: yes, but it's tricky, and many of the tools you might use are semi-abandoned.
2. Can I package my executable for distribution on client machines?
Yes, though it depends on how you answer question 1. If you use the .Net compiler, your options are different to the C++ option.
3. Can I protect my source code once I've created the application?
Again, depends on how you answer question 1. Many compilers include an "obfuscator" option which makes it hard to make sense of any information you get from decompiling the app. However, a determined attacker can probably get through that (this is why software piracy is possible).

PHP Localization - gettext or array?

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

Is it possible to change gettext files from PHP?

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 :)

Translating php app with gettext

From my previous questions about gettext, one of the biggest benefits of using PHP's gettext extension instead of other methods of language translation was that it is super easy to have other people make translation files with a program called Poedit.
Now I have gettext working in my app but I have not made any translation files yet, I found a demo file on the net and tested with it to conform my app works with gettext though.
Now I played around with poedit a little bit and I might be wrong, hopefully someone can clarify some issues.
As far as I can tell poedit reads through your php code and finds all availabale spots to do a translation, is this correct?
If the above is correct, then how do you have a human translator translate with poedit without having access to your app?
Or in simple terms is it possible to make a translation file with poedit without it having access to your php code?
Note that I have never used poedit myself, so this might not be totally accurate...
An interesting article that you might first read, for some information : Localizing a WordPress Plugin Using poEdit. It's WordPress, which means PHP -- so the basic ideas should be OK for your application.
Basically:
you first extract all the strings from the PHP source code
by telling poedit how your translation function is called
this should answer your 1)
then, you do translation
working with/on the .po file
And I'm guessing you can distribute this .po file to your translators, who can then translate the strings it contains
and, finally, you use the .po file to generate the .mo file that will be used in your application.
This other article, about WordPress too, seems to indicate that I'm guessing right : User:Skippy/Creating POT Files -- especially, this sentence :
Make the .po file available for
download (or optionally include it in
the plugin archive). Translators will
use this file to construct a .mo file,
which will be used by the
load_plugin_textdomain() function.
(Obviously, the function name you'll be using in your application will not be the same as the one in WordPress -- still, the idea is there).
No, poEdit doesn't read all your sources. You use the gettext utility "xgettext" to do that.
Basically, xgettext will produce a .po file.
Your translators will use POEdit to work on that .po file.
When the translater is done, you'll compile the .po into an .mo, which you app will use to look up translations.
If you have gettext installed on some unixy system, try "info gettext" in bash.
PoEdit actually uses xgettext, which you can set up on the Settings/Parsers tab correctly.
You should distribute a .pot file by the way, which is a .po template. So translators can translate it, set the language, the translator team, etc.
Unfortunately, I cannot see an option to create .pot file from source, but poedit can read then (of course, it's the same as .po).
After creating their own .po, you can have the .mo!

xgettext vs gettext

I have a few questions:
I know what gettext is. I've read a few posts where they mentioned xgettext and was curious as to what is the difference between the two.
How can I install xgettext on Windows?
And finally, does anybody have a tutorial on how to install the library php-gettext http://savannah.nongnu.org/projects/php-gettext/ (this one usually doesn't come with PHP) I've read about it in an article but I'm not sure how to get it working in Windows. The thing is, sometimes when you make changes, you need to restart Apache to see the new data with the gettext that comes with PHP (but with the library you don't need to restart it) so I wanted to use the library for development. Thanks!
In regards to the question:
I know what gettext is. I've read a few posts where they mentioned xgettext and was curious as to what is the difference between the two.
In short, gettext() is a function and xgettext is a utility program for extracting messages from source code.
In long, SO answer to Complete C++ i18n gettext() “hello world” example shows as part of the C++ source code file hellogt.cxx:
gettext("hello, world!")
The gettext() function is passed a text string that is used as an index to the message to be used at run-time. It returns the specified message for the language which is specified either in the code or at the time the program is invoked.
Then it shows:
xgettext --package-name hellogt --package-version 1.2 --default-domain hellogt --output hellogt.pot hellogt.cxx
which is a utility program used at build time to examine the source code file hellogt.cxx for text strings passed to gettext(). These are extracted and used to create the Portable Object Template file hellogt.pot.
The .pot file template is used by translators in the process of delivering the binary translated message file hellogt.mo used at run-time by gettext().
Install Cygwin and select the gettext-devel package.
This will install the xgettext.exe
The Zend Framework has a gettext Zend_Translate adapter that doesn't require the php gettext extention.
xgettext is part of gettext, it's a program that extracts translatable strings from program sources. See gettext's manual.
I don't know about its availability on Windows, Google tells me there's a port.
The online function reference reference tells me there is no xgettext.
Maybe they mean one of
ngettext dgettext dngettext dcgettext dcngettext
treating the 'x' like a wildcard

Categories