language switcher in 3.10

Author Message

Matthew Carroll

Tuesday 30 October 2007 6:52:39 pm

I had the following simple code for a language switcher on a 3.9 site that I just upgraded to 3.10:

<div id="language-switcher">
<a href="{concat('http://www.example.org/', $DesignKeys:used.url_alias)}">English</a> | 
<a href="{concat('http://es.example.org/', $DesignKeys:used.url_alias)}">Espa&ntilde;ol</a> | 
<a href="{concat('http://fr.example.org/', $DesignKeys:used.url_alias)}">Fran&ccedil;ais</a>
</div>

Which used to produce, e.g.:

<div id="language-switcher">
<a href="{concat('http://www.example.org/contact">English</a> | 
<a href="{concat('http://es.example.org/contact">Espa&ntilde;ol</a> | 
<a href="{concat('http://fr.example.org/contact">Fran&ccedil;ais</a>
</div>

This now produces (on the English site):

<div id="language-switcher">
<a href="{concat('http://www.example.org/Contact">English</a> | 
<a href="{concat('http://es.example.org/Contact">Espa&ntilde;ol</a> | 
<a href="{concat('http://fr.example.org/Contact">Fran&ccedil;ais</a>
</div>

Which of course does not work, because the url_alias on the English site is different to the aliases for the other language sites. What it needs to produce is this:

<div id="language-switcher">
<a href="{concat('http://www.example.org/Contact">English</a> | 
<a href="{concat('http://es.example.org/Contactarnos">Espa&ntilde;ol</a> | 
<a href="{concat('http://fr.example.org/Contactez_Nous">Fran&ccedil;ais</a>
</div>

However, I can't work out any way to extract the other languages' url_alias from ezpublish.

I've done this as a temporary fix, but it's not ideal:

<div id="language-switcher">
<a href="{concat('http://www.example.org/', $uri_string)}">English</a> | 
<a href="{concat('http://es.example.org/', $uri_string)}">Espa&ntilde;ol</a> | 
<a href="{concat('http://fr.example.org/', $uri_string)}">Fran&ccedil;ais</a>
</div>

From looking at the 3.9 webin extension it seems to me this problem would affect the language switcher there too. I can't seem to find a 3.10 webin though to compare.

Any ideas?

Thanks
Matthew

http://carroll.org.uk

Xavier Dutoit

Saturday 17 November 2007 1:29:48 am

Ok, the new url system is magic, it has only a little tiny missing feature: you can't make a link between two languages of the same content ;)

The previous system was already ugly, as you had to code by hand the relation between each language and their siteaccess, but at least it worked.

To make it short, what I'd like to do (from any full.tpl):

$translation=fetch("translations")
{foreach $transations=fetch("content","translation",$node.node_id}
<li><a href="$translation.full_uri">$translation.name</...

In the full uri, I want the full uri of the right language
if domain name based
http://fr.example.com/Chocolat
http://en.example.com/Chocolate

if url based
http://example.com/fr/Chocolat
http://example.com/en/Chocolate

I want it to know like a big boy what siteaccess config is the one to use for each language, and I want it to exclude from the list the current language that it's displaying.

I want it to work like it's expected to.

Quite frankly, I'm stunned that this feature that's been planned for addition since 3.7 or so, has been that missing the point.

oh, and while we are at it (I spread it already elsewhere in the forums):
an alias should return a 301 permanent redirect to the real url alias (not display the page), as should /content/view/full

last but not the least, if someone could point me on a simple example on how to shorten() the urls (url_alias is fine, but a more than 80 char url is simply not practicable, we should be able to easily limit the length of any url alias.

end of the rant

X+

http://www.sydesy.com

Kristof Coomans

Saturday 17 November 2007 1:41:12 am

Hi Xavier

I think putting a shorten on the url aliases is possible by creating a custom transformation command. See http://ez.no/doc/ez_publish/technical_manual/3_10/features/multi_language_support_for_url_aliases/custom_transformation_commands for more information. By the way, there will follow more docs about the transformation system.

independent eZ Publish developer and service provider | http://blog.coomanskristof.be | http://ezpedia.org

Xavier Dutoit

Saturday 17 November 2007 1:50:40 am

Hi,

thanks, I'll give it a shot.

X+

http://www.sydesy.com

luis muñoz

Monday 19 November 2007 1:45:12 am

Hi,

I'm having also problems making a language switcher. I found it is done in the admin, in the template design/admin/templates/content/urlalias.tpl. That template uses a variable wich has all the alias in all the languages for a given node. It's $elements, on line 206, an array.

I cannot find in what template that array is created but i'm prety sure there is the answer to the multilingual url alias.

If you wanna see how it works in the admin it's in the left menu, click on any icon --> Advanced --> Manage url alias ( my admin is in spanish so maybe not exactly that ).

There you can see how the admin is fetching from somewhere the alias for every language of that node.

Any one can find how to replicate this in our templates??

Thanks,

Luis Muñoz

Tobias Vogel

Monday 26 November 2007 7:43:12 am

Thanks Luis for this detail, it headed me to a method on how to write a custom template operator, to fetch the url_alias by node-id and locale. Maybe it's of use for some of you struggling with your language switchers.

Example usage:

<a href={fetch_url_alias($node.node_id, 'ger-DE')|ezurl()}>Read it in german</a>
<a href={fetch_url_alias($node.node_id, 'eng-US')|ezurl()}>Read it in english</a>

I attached the operator source to the related issue at the ez bugtracker as a workaround:
http://issues.ez.no/IssueView.php?Id=11791

Tobias Vogel

Monday 26 November 2007 9:18:08 am

Additionally, here's the relevant part of the navigation. It will default to the parent node, if the current node is not translated into the target language. Same goes for the parent node and so on.

lang_navi.html

{* list with node-id's on the way to the main node *}
{def $node_path=array()}

{* unavailable locales on each level *}
{def $na_locales=array()}

{* path not necessary if we're already at the main page *}
{if $node.node_id|ne(2)}

	{* start with current node *}
	{def $curr_node=$node}
	
	{* traverse the path to the top *}
	{for $pagedepth to 2 as $i}
	
		{* remember all node-ids on the way *}
		{set $node_path=$node_path|append($curr_node.node_id)}
		
		{* fetch unavailable translations *}
		{def $node_na_locales=fetch('content', 'non_translation_list',
										hash('object_id', $curr_node.contentobject_id,
											 'version', $curr_node.contentobject_version) )}
		
		{* pack unavailable locale codes into an array *}
		{def $node_na_lcodes=array()}
		{foreach $node_na_locales as $node_na_locale}
			{set $node_na_lcodes=$node_na_lcodes|append($node_na_locale.locale_code)}
		{/foreach}
		
		{* save the unavailable locale code-array to the parent array *}
		{set $na_locales=$na_locales|append($node_na_lcodes)}
		{undef $node_na_lcodes}
		{undef $node_na_locales}
		
		{* continue with the parent node *}
		{set $curr_node=fetch('content', 'node', hash('node_id', $curr_node.parent_node_id))}
	{/for}
{/if}

The functionality for choosing the right node and generating a localized link is in an external template that get's called like this:

    <div id="language_chooser">
[...]
      {include uri='design:menu/lang_item.tpl' node_path=$node_path na_locales=$na_locales
      											domain='www.foo.de' locale_code='ger-DE' locale_desc='Deutsch'}
      {include uri='design:menu/lang_item.tpl' node_path=$node_path na_locales=$na_locales
      											domain='www.foo.com' locale_code='eng-US' locale_desc='English'}
[...]
    </div>

And here follows the final link logic in lang_item.tpl:

{* traverse through all nodes and check, if they're available in the desired language *}
{foreach $node_path as $index => $node_id}
	{if not($na_locales[$index]|contains($locale_code))}
		{def $final_node=$node_id}
		{break}
	{/if}
{/foreach}

{* If no translated node has been found, point to the index page *}
{if not(is_set($final_node))}
	{def $url_alias=concat('/')|ezurl('no')}
{else}
	{def $alias_path=fetch_url_alias($final_node, $locale_code)}
	{def $url_alias=concat('/', $alias_path)|ezurl('no')}
{/if}

<div class="lang_item">
	<a href="http://{$domain}{$url_alias}">
		<img alt="{$locale_desc|wash()}" src={concat("menu/", $locale_code , "/flag.gif")|ezimage('double')}/>
		&nbsp;{$locale_desc|wash()}
	</a>
</div>

{undef $final_node}

Hope it helps anyone ;-)

Xavier Dutoit

Wednesday 28 November 2007 1:04:04 am

Hi Tobias,

Have you already created it as an extension ?

If it's not the case, could you please (please, please) do it so it would quickly go to the top of the "must have extension list"

X+

http://www.sydesy.com

Tobias Vogel

Wednesday 28 November 2007 4:03:37 am

Here you are:
http://ez.no/developer/contribs/hacks/fetch_multilingual_url_alias_by_locale

Have fun :-)

Edit: I just realized, you might have meant the language switcher... I'll see what I can do, as it needs some testing first and I have a stack of work in front of me. Just track the changes of this thread, I'll reply here, when it's done.

Xavier Dutoit

Thursday 29 November 2007 12:04:44 am

Way cool !

Thanks, and shouldn't take too long to add a design/standard/templates/part/language_switcher.tpl in the extension, or do the same without ;)

X+

http://www.sydesy.com

Tobias Vogel

Thursday 29 November 2007 1:20:10 am

No, I just need to reorganize it, as we have hardcoded our domain names and locales in the switcher (because of host matching). I think I'll put that part into an ini-file.

Powered by eZ Publish™ CMS Open Source Web Content Management. Copyright © 1999-2014 eZ Systems AS (except where otherwise noted). All rights reserved.