How to use gettext with Twig templates in Slim Framework? - internationalization

I'm working with Slim 4 Framework with a Twig engine for templates.
Some time ago, Twig had an extension with {% trans %} tokens and |trans filter directly linked to gettext function.
Now things seems to be more complicated, Twig is linked to a Symfony Translator... do you know how can I link Twig to gettext?
I tried to create a custom filter, and it works, but I don't know how to create a tokenparser just to call gettext() function.

The "official" way would be to use the Twig-Bridge component that provides a Twig 3 TranslationExtension to translate messages with the trans
filter. For this, you have to install the Symfony translator component.
The TranslationExtension can be configured with a custom Translator that must implement the TranslatorInterface. The Symfony Translator is able to use mo files as source. So you don't have to use the gettext extension anymore.
use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Formatter\MessageFormatter;
use Symfony\Component\Translation\IdentityTranslator;
use Symfony\Component\Translation\Loader\MoFileLoader;
use Slim\Views\Twig;
// ...
$twig = Twig::create($paths, $options);
$translator = new Translator(
'en_US',
new MessageFormatter(new IdentityTranslator())
);
$translator->addLoader('mo', new MoFileLoader());
$twig->addExtension(new TranslationExtension($translator));
If you still want to use the gettext function, you could also try to create a custom Twig function:
https://symfony.com/doc/current/templating/twig_extension.html
use Twig\TwigFunction;
$environment = $twig->getEnvironment();
$environment->addFunction(new TwigFunction('__', function ($message) {
return __($message);
}));
Usage
{{ __('Hello world') }}
The downside of the second approach is that you need a custom text parser.

I have solved adding this dependency to composer:
twig/extensions
And this extension to Twig config:
$twig = Twig::create($twigSettings['path'], $twigSettings['settings']);
$twig->addExtension(new I18nExtension());

Related

Isolate external php code in Laravel

I need to integrate Slider Revolution editor into my Laravel (5.5) app.
I've put the editor in public/revslider/ folder to be able to use the visual editor. I also created a helper class to "communicate" with it and be able to use it inside my Blade views:
namespace App\Helpers;
include( public_path('revslider/embed.php') );
class Slider{
/**
* This function is called where you want to put your slider
*/
public static function make($slider){
return \RevSliderEmbedder::putRevSlider( $slider );
}
/**
* This function is called inside <HEAD> tag to include all
* SR assets (js/css/font files)
*/
public static function head(){
return \RevSliderEmbedder::headIncludes(false);
}
}
The SR's PHP code does not use namespaces. In fact it is a strange mix of Code Igniter, Wordpress and vanilla php.
The problem is it is trying to declare a translation function __(...):
if( ! function_exists('__'))
{
function __($string = '')
{
....
}
}
and since there is already such Laravel's helper function, it does not redeclare it and tries to use Laravel's __() function. And that obviously causes errors.
I temporarily managed to fix this problem by changing the name of SR's __() function (and all references to it). But of course it is not a best way to solve this problem, since I will be unable to use SR's automatic updates or will be forced to do these changes after every update.
So my questions are:
Is there any good way of integrating such "bad" code into your project, invoking it safely without conflicts? Is there any way of isolating such code and avoid clashes? By "bad code" I mean code that does not follow strict OOP/PSR rules present in projects like Laravel.
What is the best way to include "external" PHP code? I've just used plain include() inside of my helper class' file, but is there a better/cleaner way? Like, I don't know, loading it through composer?

Extract template strings for i18n from Twig in Slim

I spend quite some time trying to figure out how to "compile" all my Twig templates in a Slim based application, to make sure all strings were ready to be picked up by xgettext for further processing and translation.
It turned out to be quite easy as soon as I had the right pieces of information put together, but I couldn't find any place on the internet telling me how to do exactly this with Twig in a Slim application.
The Twig documentation has a fine example of how to extract template strings. However, before you're able to do that, you need to pull the Twig environment out of your Slim application, as described in the Slim Knowledge Base.
So, here's a modified version of the example from Twig documentation:
// Specify where your templates are located.
$tplDir = '/path/to/your/templates';
// Get the Twig environment from your Slim app, $app.
$twig = $app->view()->getEnvironment();
// Iterate over all your templates.
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tplDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file)
{
// Force compilation.
if ($file->isFile()) {
$twig->loadTemplate(str_replace($tplDir.'/', '', $file));
}
}

CodeIgniter pagintation - appending the page number to "page" string

What I am trying to achieve is urls outputting via pagination like this:
http://www.mysite.com/users/page5
or
http://www.mysite.com/users/page-5
At present, it will be using the URI segments like this:
http://www.mysite.com/users/page/5
I can modify the routes.php config file to route the path if the first two URLs are used. So, that's not the issue.
What I am having trouble with is, how do I initialize the settings for the pagination, so that the $this->pagination->create_links() will create a pagination with items having links like in the first or the second format?
Let me know if you need more explanation or examples regarding this. I'm not much good in explaining things. :)
Thank you
This functionality already exists in the in-development version of CodeIgniter 3.0. You can view the Pagination class as it sits here.
To use this library, you can either A) use all of CI 3.0 (it's pretty stable), or B) extend (or, more realistically, replace) the Pagination library by creating application/libraries/MY_Pagination.php and filling it with the contents of the link above. (Full disclosure: it's been a while since I tinkered with CI, so I don't know if anything has changed since that may result in errors with any of this answer.)
To use the feature you want, specify your base URL minus the page-X segment, set that you want to use page numbers instead of offset in your URI segment, and then specify a prefix.
$config['base_url'] = site_url('users');
$config['use_page_numbers'] = true;
$config['prefix'] = 'page-';
Make sure to include your other obvious items as well, such as per_page, etc.
To change the functionality of the Pagination library, you can extend the library and override the create_links() function.
Create a file named MY_Pagination.php in application/libraries/
The file should have the following structure, so you can change or add additional functionality to CI's native Pagination library. (It is bad practice to directly change the Pagination library in the system directory.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Pagination extends CI_Pagination {
public function __construct()
{
parent::__construct();
}
}
You'll then need to add the create_links() function to your MY_Pagination class, allowing you to override its default functionality. Below is an explanation of what you could change to achieve your desired output (you may want to add flexibility, by adding a parameter to the function, but this is the simplest change that I could think of.)
function create_links()
{
// You can copy the exact functionality of this function from:
// system/libraries/Pagination.php
// The line you want to change is:
// $this->base_url = rtrim($this->base_url, '/') .'/';
// Changing to this: $this->base_url = rtrim($this->base_url, '/') .'';
// Will create links in this format: ../page5
// Or changing to this: $this->base_url = rtrim($this->base_url, '/') .'-';
// Will create links in this format: ../page-5
}

Organize views and controllers with the new EmberJS router

I want to organize my views in packages / folders to avoid a long list. With the (great) new router, a view is provided by default that we can change by creating a new one with a convention name. For example:
match('/').to('home');
uses:
"home" handlebars template
App.HomeView
App.HomeController
Now I want to use:
"my_package/home" handlebars template (works)
App.MyPackage.HomeView
App.MyPackage.HomeController
When I use the gem "ember-rails" (the GIT version) and the generator:
rails g ember:view my_package/home
I get:
DemoEmberRails.MyPackage::HomeView = Ember.View.extend({
});
that is not a correct javascript code (seems to be an extract for ruby code).
I tried:
DemoEmberRails.MyPackage = {};
DemoEmberRails.MyPackage.HomeView = Ember.View.extend({
});
But it's not used by the router.
How to do that?
I think you should Namespace them using Ember.Namespace. I'm still not sure if the router will automatically search namespaces but it may?
http://emberjs.com/api/classes/Ember.Namespace.html
As you've said
match('/').to('home');
expects AppName.HomeRoute, AppName.HomeView and AppName.HomeController. So if you have a template with data-template-name="home" and a view similar to
AppName.HomeView = Ember.View.extend({
teplateName: 'home'
});
then ember will automatically connect the / route with this view.
The new ember routing guides are quite helpful here.
It looks like this is currently unsupported, however, a pull request exists to add this feature.
See:
https://github.com/emberjs/ember.js/pull/1679

How to use include function in another custom function?

I am using Smarty 3.1.8
I want to include a tpl file only one time on page even if tpl file called more times.I dont know that I can do the that with Smarty without write a new custom function.So I think to write a new custom include function for this.
Can I use include function of smarty in the custom include function ?
I want to use smarty include function in my the custom include function for compile given template.
How am I do this ?
I want to use as follow :
{include_js file="script.users.tpl"}
Are you using PHP? If, so try this:
Even though it's in Smarty, use the php include_once("/dir/filename"); function.
using smarty_bc or smarty2:
{some_smarty.tpl}
<html>
<p>ex paragraph one</p>
<p>ex paragraph two</p>
{php} include_once("script.users.tpl"); {/php}
</html>
This way you can rely on having PHP monitor that the file is only being inserted once.

Resources