[i18n] Multi-languages w/ F3: How to?

846 views
Skip to first unread message

Emmanuel

unread,
Dec 26, 2013, 11:49:38 AM12/26/13
to f3-fra...@googlegroups.com
What would be the best way to setup a multi-languages app powered by F3 ?

  1. templates per language.
    1. different template per language, organized in folders /es/, /fr/, ... ?
    2. same template handling *ALL* languages with <switch expr="@lang"> ?
  2. .po GetText' like (include the GNU gettext support in the PHP build) 
  3. use the built-in F3 locales features (but not have tool to translate/handle php arrays nor ini)
the idea is to put as much as possible messages stuff at the templates level
hence i would go, at first, for option #1.1 if possible but i don't realize all the consequences (never used that solution, used to the .po way)

2. involves to handle the i18n in the controller/view and would prefer go for 1. solution 
3. requires tool to generate the translations in php array. Standard? Any tool?

Any feedback & remarks most welcomed

stu warneski

unread,
Dec 27, 2013, 8:31:32 AM12/27/13
to f3-fra...@googlegroups.com
I consider templates to be used for layout. 
therefore if you make a different template for each language, I think you are unnecessarily duplicating your workload.

bcosca

unread,
Dec 27, 2013, 10:21:38 AM12/27/13
to f3-fra...@googlegroups.com
Stu is right. One template to rule them all. It should be your language algorithm or F3's built-in that should do the hard work. Now, why use .po at all? .ini files are easier to edit. No need for an external application, just any ordinary text editor.

Emmanuel

unread,
Dec 29, 2013, 8:44:27 AM12/29/13
to f3-fra...@googlegroups.com
Hi, thanks for your reply

Stu is right. One template to rule them all.

for the layout sure. 1 layout template for front-site & 1 for backoffice
 
It should be your language algorithm or F3's built-in that should do the hard work. Now, why use .po at all? .ini files are easier to edit. No need for an external application, just any ordinary text editor.

.ini are great for small, sorry, fat-free, websites 

with fat websites, .po gettext let you load only the strings used on a given page, and, most importantly, rebuild the dictionary just by scanning the sources code/template pages. You get a list of never-used i18n strings and, cool, the list of the ones yet to translate.

with .ini, when you add new text, you must hit all your .ini files. 
and you don't see when a string is missing (at least not before you get an error), meaning we either need to mock all i18n pages or, quicker, load both original .ini and the translated one, and ask array_diff what it got

But the main concern with F3 .ini is it's not useable as it: 

With F3, the i18n strings are stored into the hive, all, and at every request, right? (not only the ones relevant to the current route) 
Not a big deal, even for fat-free web-sites (? why a page should load all the texts of the website? for the sake of simplicity ok), 

but the usability point is that, for our convenience, we must use i18n strings in templates like every another hive variable, e.g. 
@i18n_about_menu, 
@i18n_about_menu_title, 
@i18n_about_menu_title_tooltip, 
@i18n_about_menu_h1_title, 
@i18n_about_menu_text_p1, 
@i18n_about_menu_text_p2, 
@i18n_about_menu_text_p3, 
@i18n_about_menu_text_PS

by my side, it's not a fat-free solution.

Would having them in a array improve the usability? quite a bit sure


Another lighter solution than both .po GetText & .ini is to use the much welcomed 
Template->extend('<i18n>','Localization::i18nTag');

combined, for those lengthy 'static' pages such as Terms, Blabla & co, with a 

<include href="{{@lang}}/static/about.html" />

Everything's possible with such a versatile framework, very appreciable! 2e6 10x!!!

Tony PV

unread,
Dec 29, 2013, 10:49:33 AM12/29/13
to f3-fra...@googlegroups.com
Hi,
           I used a different approach. I used db to store multilingual texts. I also provided options to import and export the label texts for different languages. I used php files to retrieve the texts from the db and return an array to use as language files. This allowed me to avoid editing the .ini files. I don't know if this method is efficient or not, but would like the feedback of the experts here.

Thanks in advance.

Tony P V

stu warneski

unread,
Dec 29, 2013, 11:36:04 AM12/29/13
to f3-fra...@googlegroups.com
db works fine, and allows you to write a admin interface to allow non-technical users to edit test, instead of having them edit ini files on server which may screw something up.

did you add a data column for each language needed, and just select that column base do the session language?
or are you querying multiple rows in db to match language and page or section to be rendered at request time?

Emmanuel

unread,
Dec 29, 2013, 12:20:25 PM12/29/13
to f3-fra...@googlegroups.com
write an admin interface 

aie--.. not Fat-Free :)  

Emmanuel

unread,
Dec 29, 2013, 12:22:25 PM12/29/13
to f3-fra...@googlegroups.com
On Sunday, December 29, 2013 4:49:33 PM UTC+1, Tony PV wrote:
Hi,
           I used a different approach. I used db to store multilingual texts. I also provided options to import and export the label texts for different languages. I used php files to retrieve the texts from the db and return an array to use as language files. This allowed me to avoid editing the .ini files. I don't know if this method is efficient or not, but would like the feedback of the experts here.

Thanks in advance.

Tony P V!

Looks like a kinda Poedit app, but server-side , or GlotPress 

Emmanuel

unread,
Dec 29, 2013, 12:26:24 PM12/29/13
to f3-fra...@googlegroups.com
Hi,
           I don't know if this method is efficient or not,

how do you handle multi languages routes?  
if a spanish-speaking browser lands on the /it/about/ page for example, do you redirect it to /es/about/ ?

bcosca

unread,
Dec 29, 2013, 9:54:52 PM12/29/13
to f3-fra...@googlegroups.com
F3's multi-language support is meant only for user interface elements. It is not meant for translation of ENTIRE pages, for which a database is a natural solution. Your reference to usability IMO is subjective. Each language translation methodology has its own pros and cons, and .po files are not exempt from that. For one thing, gettext() is too verbose for some things like short phrases, and becomes just as unmanageable if we're talking about hundreds of translations. gettext also suffers from the same problem as other translation facilities when it comes to tracking down obsolete/unused entries. So the comparison is lopsided. F3 uses .ini files. It loads fast because it stuffs them all strings in memory. Of course, there's a downside to that. So we can say .po conserves memory, but it's not as performant because it has to search the filesystem for EVERY single term. Now, which will we call "fat-free"?
Message has been deleted

bcosca

unread,
Dec 29, 2013, 10:05:40 PM12/29/13
to f3-fra...@googlegroups.com
Then again you really don't have to load all F3 translations that are not relevant to the page you're displaying. Say you're displaying page X interface, you may not want to load the page Y translations. You can simply change the LOCALES path: one path for X, a different path for Y. This way you don't end up with one humongous, memory gobbling dictionary.

Tony PV

unread,
Dec 30, 2013, 3:58:38 AM12/30/13
to f3-fra...@googlegroups.com
I am not using routes for multilingual content, the routes are same for all languages, there is language selection drop down and the value is handled in session. Multilingual content for page is retrieved from db, and for labels, session value loads the relevant php file which returns the label texts of the relevant language.

bcosca

unread,
Dec 30, 2013, 6:23:50 AM12/30/13
to f3-fra...@googlegroups.com
From my personal experience, I have yet to see a multilingual site that requires more memory than 128MB per page. The argument that .po files will relieve the server (even with cached .po files) of better performance/memory consumption is moot and academic, unless you're displaying multilingual images which is absurd.

Emmanuel

unread,
Dec 30, 2013, 6:28:08 AM12/30/13
to f3-fra...@googlegroups.com

On Monday, December 30, 2013 3:54:52 AM UTC+1, bcosca wrote:
F3's multi-language support is meant only for user interface elements.

i understand. menus, footer links, aso. small but repetitive elements. ini is a good approach for those items.
 
gettext() is too verbose for some things like short phrases, and becomes just as unmanageable if we're talking about hundreds of translations.
right, it's why they made GNU tools like GlotPress and Poedit
 
gettext also suffers from the same problem as other translation facilities when it comes to tracking down obsolete/unused entries.

you can rescan your sources at anytime to spot obsolete/unused entries

one good pint with gettext is the fallback: if you don't even have a translation available, in any language, no problemo, just takes the key as the text to display. It means you start your app without even knowing if it will be multilanguages one day! 
 
F3 uses .ini files. It loads fast because it stuffs them all strings in memory.

sure! can't find a fastest way. Gettext is fat, and especially SLOW!!! benchmarks with and without gettext show an impressive difference regarding page load time. Like 200 ms lost due to gettext! You have a page that loads in 35 ms and all of a sudden, with Gettext, it loads in 250 ms. 5x slower....  

So in our last project, we still used Gettext for convenience, but once translated, all generated pages are cached.
 
Of course, there's a downside to that. So we can say .po conserves memory, but it's not as performant because it has to search the filesystem for EVERY single term.

sure? i thought it load the compiled/zipped/indexed .mo file in memory, but right, the whole fat file!
 
Now, which will we call "fat-free"?

F3 indeed :)


Emmanuel

unread,
Dec 30, 2013, 6:30:09 AM12/30/13
to f3-fra...@googlegroups.com

On Monday, December 30, 2013 4:05:40 AM UTC+1, bcosca wrote:
Then again you really don't have to load all F3 translations that are not relevant to the page you're displaying. Say you're displaying page X interface, you may not want to load the page Y translations. You can simply change the LOCALES path: one path for X, a different path for Y. This way you don't end up with one humongous, memory gobbling dictionary

right, i thought about that later after i posted here. instead of setting the locales globally, why not set it for each route! it's the solution i gonna adopt. Now you confirm it. Thanks! 

Emmanuel

unread,
Dec 30, 2013, 6:35:55 AM12/30/13
to f3-fra...@googlegroups.com
the routes are same for all languages,

as an ex SEO, i worry about your site structure:

"The same content in different languages is not considered duplicate content"

ok, good for you

but what about your Content organization ?

rules are, yes, Google rules ;(, "Put the content of every language in a different subdomain" or "Put the content of every language in a different subdirectory"

unless you're speaking about an Intranet i guess

bcosca

unread,
Dec 30, 2013, 6:36:20 AM12/30/13
to f3-fra...@googlegroups.com
one good pint with gettext is the fallback: if you don't even have a translation available, in any language, no problemo, just takes the key as the text to display. It means you start your app without even knowing if it will be multilanguages one day! 

F3 follows the same fallback mechanism. That's the reason why the FALLBACK variable (en by default) is there. If there is no translation for the term, the system automatically falls back to this. More than anything else, this fallback language should have every single translation for every term in your app, meaning it should be complete.

ikkez

unread,
Dec 30, 2013, 7:16:33 AM12/30/13
to f3-fra...@googlegroups.com
F3 provides the tools,.. just be a bit creative with them and you will find more than just one way to achieve what you need ;)
That's the cool thing of this versatile framework.

Emmanuel

unread,
Dec 30, 2013, 8:35:41 AM12/30/13
to f3-fra...@googlegroups.com
that's the point. while with gettext you don't even need a fallback dictionary. no duplicate work. 

with .ini you have twice the work: define the @i18n_texts in the templates, taking care they are relevant, a valid unique variable name and still meaningful enough for the translator; and now you need to extract'em all and save'em in the ini file. 2 files to maintain.
with gettext, if you have say 2 languages, you have 1 file to maintain. Actually, the fallback strings are straight into the templates.

Anyway, are we speaking about the same concern? can we compare the php extension gettext with plain vanilla ini files? One is for big slow websites while the other is for fat-free websites.

And this thread is getting too long, i don't like that coz i started it ;(

Thank you for your comments and feedback

matt smith

unread,
Jan 1, 2014, 11:02:56 PM1/1/14
to f3-fra...@googlegroups.com
Just to put a "I second that" - The real nice thing about the po file method is it will use whatever is defined in the variable in your script as the fallback - no fallback file needed. That was always very nice in wordpress, and would love something like that here.

So, for example, instead of...
$f3->get('today',time());
...you put...
$f3->get('Today is {0,date}',time());
...If there is no definition for 'Today is {0,date}' in the ini file, it will just use that, no need to be managing some English fallback file while you're in the middle of coding your templates.

bcosca

unread,
Jan 2, 2014, 1:51:22 AM1/2/14
to f3-fra...@googlegroups.com
Use $f3->format('Today is {0,date}',time());

matt smith

unread,
Jan 2, 2014, 8:22:18 AM1/2/14
to f3-fra...@googlegroups.com
But that doesn't provide translation, does it? I still want it to use another language if it's available. I just want it to use what's directly listed in the call if any language version isn't available.

bcosca

unread,
Jan 2, 2014, 8:36:11 AM1/2/14
to f3-fra...@googlegroups.com
It won't happen. Modifying the code base to accommodate that get() argument sequence will break a lot of code.

ikkez

unread,
Dec 30, 2013, 4:26:07 PM12/30/13
to f3-fra...@googlegroups.com
well i think the F3 implementation and gettext - free method is already nice as it is. With some create thought around it, i think it is also pretty good usable for bigger sites with some more languages.
Like almost any other part for the framework, it does not dictate you how to build your site, it just offers some well thought-through fat-free tools you can use but don't need. If you are more happy with gettext usage, or Twig templating, or RedBean ORM.. so please.. it's up to your choice.
Reply all
Reply to author
Forward
0 new messages