better multilanguage

125 views
Skip to first unread message

noXTRAs

unread,
Mar 27, 2019, 4:59:04 AM3/27/19
to Fat-Free Framework

I think the multi-language feature could be better, if it also worked like this:

Yes, the idea is to have the Fallback string directly in the template. I'm working on a large project and having to map all the text on the site to variables is really time consuming. Having the string in whatever default language you have directly in the template was a huge time saver for me.


in the template: {{ __('my text here with spaces') }}


DICT/en.php is the same, but supports spaces (or one could use _en.php for backwards compatibility)


Then, I have this in index.php

$f3->LANGUAGE = $f3->ml->current; //previously loaded the Multilang::instance()
$f3->TEXT = include($f3->LOCALES."_".$f3->LANGUAGE.".php");

function __( $text) {	
	global $f3;
	if (isset($f3->TEXT[$text])) { //for simplicity, the default language file has an empty value
		if ($f3->TEXT[$text]) {
			return $f3->TEXT[$text];
		} else {
			return $text;//display the original text
		}
	} else {
		return '_'.$text.'_';//default is whatever is in the template, but add underscores to show that a translation is missing
	}
}

xfra35

unread,
Mar 27, 2019, 5:59:49 AM3/27/19
to Fat-Free Framework
The framework provides all the tools to implement this strategy:

$f3->PREFIX = 'DICT.';

$f3
->DICT = [];

Template::instance()->filter('dict', function($str) use($f3) {
 
return isset($f3->DICT[ $str ]) ? $f3->DICT[ $str ] : $str;
});


And then inside your templates:

<strong>{{ 'Welcome home!' | dict }}</strong>


Now if you need to handle dynamic placeholders, you'll have to improve a bit the filter.

noXTRAs

unread,
Mar 27, 2019, 7:11:23 AM3/27/19
to Fat-Free Framework
Hi, thx for the prompt reply. 
I think I'm doing something bad, as $f3->DICT still doesn't accept spaces in the standard dictionary file...

xfra35

unread,
Mar 27, 2019, 10:18:21 AM3/27/19
to Fat-Free Framework
Hi,

My example was a bit buggy. Here's a full working example:

index.php

<?php

$f3
= require('base.php');

$f3
->DEBUG = 5;
$f3
->UI = './';
$f3
->DICT = [];
$f3
->PREFIX = 'DICT.';
$f3
->LANGUAGE = 'fr-FR,fr';
$f3
->LOCALES = 'dict/';

$tpl
= Template::instance();
$tpl
->filter('dict', function($str) use($f3) {
   
return $f3->get('DICT.'.$str) ?: $str;
});
echo
$tpl->render('foo.html');


foo.html

<!DOCTYPE html>

<meta charset="{{ @ENCODING }}"/>

<ul>
   
<li>Key not translated: {{ 'Welcome home!' | dict }}</li>
   
<li>Key translated: {{ 'Be careful!' | dict }}</li>
</ul>


dict/fr.php

<?php
return [
   
'Be careful!' => 'Faites attention !',
];



noXTRAs

unread,
Mar 27, 2019, 4:57:43 PM3/27/19
to Fat-Free Framework
Hi,
I was about to write back that I still get the hive key error, when (after 4 hours) I found my problem:

PREFIX                     = DICT.
LOCALES                    = "../f3/app/dict/"

PREFIX needs to be set before LOCALES

For the life of me, I can't find why this is. It's the same if loading ini, as is if setting them directly in code.

Also, what does "$f3->DICT = []" do? I can't find it anywhere in the code and it doesn't seem to do anything.

By the way, 1000x thanks for the answer.

ikkez

unread,
Mar 27, 2019, 4:59:14 PM3/27/19
to Fat-Free Framework

Yes, the idea is to have the Fallback string directly in the template. I'm working on a large project and having to map all the text on the site to variables is really time consuming. Having the string in whatever default language you have directly in the template was a huge time saver for me.


 Well yes it might be a time saver for you now and the framework has tools to allow your multilang-strategy, but I just want to mention that this pratice could lead to more problems down the road. I think the time invested here is worth the work, otherwise some things I have in mind right now:
  • when you change a default string, you need to touch all translation files and templates
  • you don't have a reference of which translation keys actually exist and are maybe not translated yet at all... you need to look at all templates and/or controllers for that
  • it does not offer any multi-level fallback dictionaries
  • what if you want to change the default fallback language.. then you/or anyone else need to touch all templates instead of changing 1 config option
  • it does not support some of the framework's language formating core features like pluralism, variable tokens and value formatting (number, currency, date, etc)
but yeah just my opinion

noXTRAs

unread,
Mar 27, 2019, 5:38:24 PM3/27/19
to f3-fra...@googlegroups.com
Regarding your feedback, it's highly appreciated. I have some unnecessary replies bellow:), if anyone has similar dilemmas:
  • I do that automatically anyway, I just put the default string {{ 'my language' | DICT }} in the template, and, when I navigate to the page and 'my language' is not defined, I just add it to the dictionary file.
  • That's why,  if it's not found, I'm putting underscores before and after the original string...so I only have to look at the site... it's not perfect, but works (stolen from WP)
  • I don't quite understand this one; but the FALLBACK language works like a charm, as it should, you coded it... I've tested it extensively and I couldn't fault it.
  • yes, but in 20 years, I never had a project when I had to change the fallback language mid project from English to something else.
  • I've optimized my code from this morning and borrowed from your format function ...and now it kinda does; Now I only have {{ 'test string ' | DICT }} and the filter logic loads $f3->DICT, so it works correctly all the time.
My main problem was (see above) that I defined PREFIX after LOCALES and it didn't work with strings with spaces.

noXTRAs

unread,
Mar 29, 2019, 11:41:45 AM3/29/19
to Fat-Free Framework
Hi,
Did you have a chance to look at why PREFIX needs to be declared before LOCALES, even in the ini files?
Also can you please explain me what $f3->DICT = [] does.
Thank you.

Paul Herring

unread,
Mar 29, 2019, 11:51:38 AM3/29/19
to noXTRAs via Fat-Free Framework, Fat-Free Framework
On Fri, Mar 29, 2019 at 3:41 PM noXTRAs via Fat-Free Framework <f3-framework+APn2wQchdfPOerE0t7f...@googlegroups.com> wrote:
 
Also can you please explain me what $f3->DICT = [] does.

Sets it to an empty array. Same as

$f3->DICT = array();

Introduced in 5.4. Google for 'php array short syntax' if you need more information on it.

ikkez

unread,
Mar 29, 2019, 2:03:13 PM3/29/19
to Fat-Free Framework
PREFIX is the key name where the language strings are imported to. So if you set it afterwards, it wont effect the already imported lanuage dictionaries, that are loaded when LOCALES is set.

noXTRAs

unread,
Mar 30, 2019, 9:18:10 AM3/30/19
to Fat-Free Framework
That makes sense if defined in code, What I'm very curious about is why is the config ini file loaded/parsed line by line? Is it faster this way? Is this the only way? I always assume the php ini parser loads parses everything first than spits back the variables. I know that you made your own ini parser.. so just curious.

ikkez

unread,
Mar 31, 2019, 6:37:36 AM3/31/19
to Fat-Free Framework
Yes it’s currently imported line by line. Probably because you can do things like this:

foo = World
bar = Hello {{foo}}
Reply all
Reply to author
Forward
0 new messages