A new Extension, “Field: Language” is now available for download. Comments and feedback can be left here but if you discover any issues, please post it on the issue tracker.

Field: Language extension provides field with language select box.

It also adds "browser-languages" parameter to list of parameters available for data-sources and XSLT to use.

When sorting by language field, it can take browser language settings into account, so entries are sorted in the same order as browser languages.


This is a very interesting extension!

However, I am missing Deutsch/Deutschland (de-de) in the language list. Shouldn't it be there?

Deutsch is default (de - language name is based on it's origin country name after all :). Browsers using specific version of language should fall back to default anyway, so their setting looks like: de-de,de;q=0.8,en.

I thought that adding 'de-de' or 'fr-fr', etc... doesn't make much sense. Field is for language selection (not country), and multinational sites rarely use variations of the same language. If they do, it's always (at least i have never seen anything else) "additional", with default being "original" version of language. I didn't want to make authors select every possible variation of language just to make it "basically Deutsch", also having both de-de and de (for the same language) can be confusing for authors.

Same for English ('en' is the same as 'en-gb'), Portuguese ('pt' is the same as 'pt-pt'), etc...

Thanks, this seems useful for datasources. Currently I am working on a Dutch/English website, and instead of making separate entries for different languages I am having one entry which uses section links employing the dutch term as a foreign key linking to the english term (or any other language that may need to be added in the future).

carsten, i'm working on site where i used very similar trick :). But i also use separate entries (it's a site with 3 languages).

Dynamic content data is entry-based (i mean things like news, awards, messages, etc...), while static content (names of agencies and work types) is translated through separate section which keeps terms (also one entry per term/phrase and language).

I used Enhanced Tag List for static translation because i know there will not be many of words/phrases to translate, it should be easier to use in XSLT and have lighter SQL queries (but i may be wrong about this one :). It should be ok. If there will be too many words/phrases in database (list of tags when editing translation will be too long :) i'll try to implement some sort of auto complete JavaScript for it and maybe will have to think about optimizing data source or moving to section links (right now i simply get list of all translations in selected language - it's small enough :).

ahwayakchih, could you clarify how and why u used the enhanced tag list for translation?

newnomad i simply created “Dictionary” section with three fields:

  1. Enhanced Tag List “Source”
  2. Text field “Translation”
  3. Language field “Language”

I could use regular text field for “Source”, but i wanted to make process of adding translations easier for translator(s) by letting them just click on phrase to translate (after it was translated at least once, of course :). I knew that “source” phrases will always be in the same language, so using Enhanced Tag List worked ok.

Data source filters “Language” field by “{$ds-language:en}” (whole thing is a bit more complicated, because there is also “Language” data source which selects which language to use by selecting from “Pages” section and sorting by another Language field… but You could sort Dictionary data source by it’s Language field).

I wrote XSLT helper template (i changed names of fields, templates, etc… to keep whole example in English, but they still should work ok :)

<xsl:template name="dictionary">
  <xsl:param name="src" select="''"/>
    <xsl:when test="not($src) or $src = ''">
    <xsl:when test="/data/dictionary/entry[source/item/.=$src]/translation">
      <xsl:value-of select="/data/dictionary/entry[source/item/.=$src]/translation"/>
      <xsl:value-of select="$src"/>

And call it like this:

<xsl:call-template name="dictionary">
    <xsl:with-param name="src" select="/data/some-source/error" />

or this:

<xsl:call-template name="dictionary">
    <xsl:with-param name="src" select="'read more'" />

Dictionary was used only for small, static text. Articles, Pages, etc… are translated different way (they simply have Language and “Translated versions” select fields to make them connected with each other, so reader can click on flag, and get to the same page but in different language).

Of course, such configuration is for very simple use only. For bigger dictionaries or more advanced usage, it probably would be better to have “Source” and “Translations” sections (with selection list of “Source” phrases) and then add something similar to what Mediathek does to allow in-line creation of “Source” entries.

aha, thanks. So the enhanced tag list magically indexes all used short phrases/words in textfields I assume.

I wonder if it wouldn’t be easier for a translator to present him/her with a textarea containing all these words, together with the long texts in that section. Marked up as markdown. And then upon saving recreating the textfields based on the markdown. Does that make sense?

Does anyone here has experience with other CMSes and how they handle multi-language? Reading about drupal transl now

So the enhanced tag list magically indexes all used short phrases/words in textfields I assume.

Well… yes it does for itself, but i used it purely for UI (to not have to implement yet another extension :) and not because of it’s index (dictionary doesn’t use it, or uses it exactly the same way as it would use data from simple text field :).

Does that make sense?

Yes it does, but then You would either have to implement special extension for that (which would separate phrases for data source use), use string manipulations in XSLT (to get translations from text blob) or find some other way to make sure entered translations are in proper format (for example, if You knew that every “source” phrase is inside bold tag, translation is inside italic tag and each pair is new paragraph, You could select them in XSLT without string manipulations).

some ideas:

identification through position in relation to header titles

I have done something like this, but it bypassed the use of textfields entirely, since the structure of the entire site was contained in 1 text(in a textarea) per language;
I splitted up the flat text in nodes with a hierchy depth and title based on the header titles above each textblock (header 1 to 6).

identification by pairing source and translation

I like your idea of pairing paragraphs with source and translation by means of bold/italic.
Maybe it could be as simple as to pair each paragraph or line with translation, without marking up.
The translator could start by coloring the flat text, and then continue in another color for the overview. then upload as flat again.

identification by ID

Maybe each string could just get an [id] to be left by the translator, instead of keeping the sourcetext.

use PO

Or maybe we shoudl use a PO editor, borrow ideas from desktop application translation?

Maybe it could be as simple as to pair each paragraph or line with translation, without marking up.

It could, but with additional markup it is easier to use in XSLT (at least for me :).

Maybe each string could just get an [id] to be left by the translator, instead of keeping the sourcetext.

It could - that’s what i meant by source and translations sections. I think it all depends on situation and i like Symphony for that i can implement it different ways (selecting whatever suits site best :).

Or maybe we should use a PO editor, borrow ideas from desktop application translation?

Well… if You’re talking about extension which would handle translations, then i guess PO could be a way… but i think XLIFF is closer to Symphony ideals (XML :), and i’ve read that it’s going to replace PO sooner or later anyway.

Still, i think that extension for translating fronted/content is not needed really. You can implement translations (using different ways) with current Symphony. Sure, some helper extensions could be useful (i really hope Mediathek will turn into generic “create connected section entries in-line” extension :), but strictly “content translation” extensions will require single way of implementing a site, which not always may be a best way.

edit: a short summary, safari only sends one accept-language header and not in the short form of ‘en’ rather ‘en-us’ or worse ‘fr-fr’ so this extension would be even greater if smart to work with before the hyphen languages; short language lsist and compatibel with webkit (iphone safari chrome,…)
The gust of the problem can be read here they dumbed the safari accept language down to sending only one language, OK, but they shoudl have gone further to also get rid of the locale after the hyphen, so it would be compatible with all websites buold to use the ‘standard notation’ with many languages including the short ‘fr’ but not the ‘fr-fr’.
Practical disadvantages could be problems viewing ebay content and such

OK, back on topic.

How to make sure this works consistantly across browsers

The official recommendation below is for users to set a single tag as first choice in their browser. Indeed firefox and others can set multiple language-with-locale tags (ea: en-us, en-ca) in order of preference.

Important. Some of the server-side language selection mechanisms will not match a long language tag in an Accept-Language header with a shorter tag associated with a document. If a document on the server is tagged as fr (French) then a request for a document matching fr-CH (French as spoken in Switzerland) will fail.

To ensure success you should configure your browser to request both fr-CH and fr, in that order. (See the example in the picture above.) This will cause the server to look for a Swiss French version first, but failing that, look for a French version.

However, few users would know about this, and most likely it is just set to default, the language of their browser. Likely ‘en-us’

What about Safari?

With Safari on macosx, the tag is set to the OS language. While you can change loaction and language, it insists in ONLY putting 1 language-with-locale tag in the accept header, no second or third choices.
There is NO way to specify a general language tag without locale, as advised above, like just ‘en’ AND… it even sets its tag in the form of the originating locale like ‘nl-nl’ for Netherlands.

Including the ‘basic language’ in this extension

While I agree with the author to keeps things simple, I think beacuse of safari this extension should have the basic language tags included like ; ‘de-de’ and ‘nl-nl’

Since the extensions omits ‘nl-nl’, only has ‘nl’ or ‘nl-be’, and despite being in belgium and settign my macosx OS to dutch language and location belgium, safari insists on one acceptheader tag; ‘nl-nl’

So what will happen when filtered by exact the string the param supplies> a 404

I have no idea about how it works in Safari for windows, but heard they had a menu to select languages?

avoid 404, fallback language?

maybe a setting in the extension to choose a fallback language if no other is available, english. Or better just in template?

catch all DS selection? smart filter instead of exact filter?

i might just mis the working of the extension here…. consider that filter by languages is independant of the languages that will appear in the param….

Content will rarely be offered in different versions of languages based on locale like ; ‘en-us’, ‘en-uk’, ‘en-ca’, and to make it easier on the authors I only selected the ‘basic’ languages in settings.

However, in order for it to work in case a user has not set ‘en’ as first preference, but ‘en-uk’ the author SHOULD include all variants.

So… could we simplify all this by having the possibility to filter the DS with a catch all tag?
So filter by ‘en’ would suffice.

Once the DSes are filtered by the set languages, by means of exact matching of the comma separted strings, maybe we can create a catch all by hacking a substring before the hyphen in our template ? But this should be done before the filtering, so in php?

ahwayakchih, since I would like to use this extension to output 1 nodeset only based on the first prefered language (not multiple nodes in order of lamguage prefered, just one in the main language, or if not available, a default language) and to circumvent the safari issues this is my setup for now:

select my languages to use; ‘nl’,’fr’,’de’,’en’ (aka just short tags) and then modify your param pulling the accept header so it only returns the short tag of the main language;

not: "en-us,en;q=0.7,nl;q=0.3"

which woudl in fact output all my languages, albeit by ordere of importancy

but: "en"

I think many serverscripts migth use this short tag, because you never know what kind of variation you will get. Your approach needs specific inclusion of all the variations you could encounter. (and safari always say en-us, even if in uk)

Only I cant find where you create the param in your code, is it here?:

        // Return value to be used as XSLT parameter
    public function getParameterPoolValue($data) {
        if (is_array($data['lang'])) return implode(', ', $data['lang']);
        return $data['lang'];

Or rather in the extension driver;

        public function __pageParamsResolve($ctx) {
        // context array contains: &$params
        $languages = Lang::getBrowserLanguages();
        $ctx['params']['browser-languages'] = implode(',', $languages);

I could also use the globael param loader extension and:

return(substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2));

to limit to the first 2 letters…. but would like to contain it in your extention

Something else, If understand correct filtering a DS by the string en-us,en;q=0.7,nl;q=0.3 would return all the nodes with a handle that is either en-us, en or nl, correct? Is this what you mean with:

        // Generate groups which will be used by Datasource to when generating XML.
    // Entries with the same value of this field will be wrapped field tag
    // (so it is not grouping in the same sense as SQL grouping! :).

Also I am curious about your implementations -its only as described above?- I personally don’t see a need to order fields by prefered languages, only to filter them by the first prefered language, just 1.

Field: Language updated to version 1.1 on 15th of March 2011

@ahwayakchih: You are back? We haven't seen you here for a long time!

michael-e: Hi :). I was busy with a lot of things, none of which was Symphony related :(. But i am working on Symphony based website now so i will at least update extensions that will be used with this project.

Good to hear, ahwayakchih! And welcome back! :-)

Thanks :).

Field: Language updated to version 1.2 on 25th of April 2011

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details