As of version 3.6.0, BEdita is distributed with an improved system to serve content translations in a URL-friendly way. This new feature is fully backwards-compatible, though it may need some minor changes in your frontend PHP code to actually gain advantage of it.

Routing

The first change that will need to be made in your frontend is about routes. To achieve URL consistency in a easy and reliable way, as well as leaving developers some flexibility on how internationalized URLs are shown to end-users, a change needs to be made in your frontend's config/routes.php:

/***** FROM *****/
Router::connect('/*', array('controller' => 'pages', 'action' => 'route'));
/****** TO ******/
Router::connect('/lang/:lang/*', array('controller' => 'pages', 'action' => 'route'), array('lang' => '[a-z]{2,3}', 'persist' => array('lang')));
Router::connect('/*', array('controller' => 'pages', 'action' => 'route'));

Of course, you can change /lang/:lang/* to whatever you want (you could choose to leave just /:lang/*, for instance), as long as the :lang placeholder appears somewhere in your route. You should take care of avoiding conflicts with existing routes and/or other URLs of any kind.

Linking to translated content

To provide consistent links to translated content, a further update in your code will likely be needed.

If you took advantage of CakePHP's HtmlHelper::url() and HtmlHelper::link() methods by passing them an array of routing elements as argument, then you are already done.

On the other hand, if you used pre-built strings to generate links within your frontend (i.e. $html->url('/my-section/my-document')), you might want to use BeHtmlHelper::url() and BeHtmlHelper::link() to achieve URL consistency without having to rewrite all internal links. Please be aware and always keep in mind that this is not the preferred method: you should always pass an array to those function to link internal resources, so consider this as your last resort.

Using BeHtmlHelper

First of all, your frontend's PagesController must declare BeHtmlHelper in the list of used helpers:

public $helpers = array('BeHtml' => array(), 'BeFront');

Please note that it should be added before BeFrontHelper and with an empty array of options. This is due to the way CakePHP handles helpers' instances.

Now BeHtmlHelper is loaded and can be used in your view templates. All you have to do is mass-replace any instance of $html->url('/some/url') and $html->link('title', '/some/url') with $beHtml->url('/some/url') and $beHtml->link('title', '/some/url') respectively in your templates to fully achieve URL consistency within and across translations.

Generating meta-tags

Last of all, you should provide spiders and bots a list of translations available for the current resource. This can easily be achieved with BeFrontHelper::metaAlternate() function:

echo $beFront->metaAlternate();  // To generate meta-tags for all languages in `$conf['frontendLangs']`.
echo $beFront->metaAlternate(['en', 'it', 'fr']);  // To generate meta-tags for a list of languages.
echo $beFront->metaAlternate(false);  // For contents with no translation available.