As far as i understand, you can only put www.mysite.com on one of the rootnodes, and thereby be restricted to that rootnode, and have to have a second domain assigned to the other rootnode to change culture.
Best regards,
Robin.
PS: Im not sure this is the right place to put this question.
Hi Zen I suppose my question is there any reason for not having different domains/subdomains? Surely you could just have en.mysite.com and da.mysite.com if you only have access to one domain?
If you using two domains/subdomains then to be honest I am not sure how I would go about this at the minute (need some cafine first!)
@ Roel Are you sure it works like this? Becaus I tried this: I coppied the root and gave them hostnames like in your example. problem was that all links still go to the root of the site www.mysite.com!
I didn't really look into this so maybe I'm doing something wrong!
I have 2 nodes already DA and EN, but how would I associate "danish" culture to the DA node, and the "english" culture to the EN node.
Warren: the reason for not using subdomains, is more in the line of "thats how the customer wants it", :p
I read something about changing something in the web.config and the umbracoConfig files, to allow it to handle multiple cultures on same domain, but different root nodes.
But as this is the first time I have come across this, I have no clue on how to proceed.
I have an idea, just wanna share it with you guys, and get some feed back on it.
I would create a new Rootnode, and assign www.mysite.com to this rootnode.
Then I would take the DA node and assing www.mysite.com/da to it, and set the culture to danish, and repeat this for the EN node, just with the english culture
And then I would do a serverside redirect on the new rootnode, that would sent it to the www.mysite.com/en.
Would this be possible ?,
Would I later be able to do serverside redirect via xslt, due to the fact, that the users must be able to choose what site to be directed into, after first visit.
I think I read on the forum thats someone made a .NET control that reads the browser language and redirect to the proper root! unfortunately I can't find the post :-(
Is this the sort of thing you are looking for: http://www.barclay.ie/ which is a multi-lingual site we developed recently, it has multiple languages and cultures running off of a single domain name.
We just set the site up as if it had sub-domains i.e. uk.barclay.ie but just don't use them, this means that Umbraco just works out the culture from where you are in the content tree.
If this is the sort of thing you are after I can post more detail.
Sorry for the delay in me adding more info on how we achieved the multi-lingual effect on Barclay. Paid work takes priority!
To get the multi lingual capabilities to work we set up the site as follows:
Global HomepageUKUKPages etcGermanyGerman pages etcSwedenSwedish pages etc.
In hindsight I should have called the county pages by their country code i.e. en for english, de for german. Ahh well next time!
Each country was then given a fake sub-domain in the manage hostnames dialog box. The sub-domain was associated with the correct language for the country. i.e. uk.barclay.ie. These subdomains are never actually used.
Now here's the important bit. The global homepage must not be mapped to the main domain i.e. www.barclay.ie otherwise Umbraco just uses the language setting for that domain on all sub sites. So again on the global homepage you set up a fake subdomain i.e. global.barclay.ie
In regards to the IP mapping, as others have said you can do this using a user control. What you will need however is a way of determining the country by IP address.
I have been working recently on a project whcih involves heavy use of geo-location both by IP and address etc. So have been researching free/cheap DBs of IP to geo-location mappings.
I think your experiences in setting up multilingual sites are truly wiki worth pages, would you mind adding the setup you've been using on a wiki page for everyone to read?
for instance, new users don't understand this: "The global homepage must not be mapped to the main domain i.e. www.barclay.ie otherwise Umbraco just uses the language setting for that domain on all sub sites. So again on the global homepage you set up a fake subdomain i.e. global.barclay.ie"
This rises the questions:
* How do I change the mapping of the global homepage?
* what if i don't want a global homepage? I prefer using the browser locale (the country a user is in doesn't reflect a users language accurately)
I've created a global homepage with two subsites (EN / NL) and have assigend a bogus subdomain with the language setting defined for each.
Should the global hompage have a bogus domain name assigned too? if so then i also need to define a language for it right?
I think you're right on the step by step, I'll edit the post what I get 5 mins to make it more accessible.
You don't need to set up a bogus sub-domain for the global page (although I did because I wanted to ensure I could set the language on the global page as well), but it's important that the main site URL is not added as a hostname for the global page.
As for loading the sub-site based on the users locale...
Off the top of my head the only (easy and quick) way I can think to do it is to create UserControl which re-directs the user to the correct sub-site based on their UserLangauges settings:
//Get the culture name - and make sure it's in the RFC 1766 standard <languagecode2>-<country/regioncode2> //i.e. en-GB, so it's easier to check for
if (language.Length < 3) language += "-" + language.ToUpper();
//Redirect to the correct page based on language, default to english switch(language) { case "en-GB": Response.Redirect("/en.aspx"); break; case "nl-NL": Response.Redirect("/nl.aspx"); break; default: Response.Redirect("/en.aspx"); break; } } } }
That's un-tested code I've written straight out, so no guarantees that it'll run first time! It could probably do with a tidy as well as it's a bit nested, but should point you in the right direction.
Again when I get a bit of time I'll add a proper code sample to the Wiki page.
i'm looking for the best way to adopt this way of creating a multi lingual site for our needs. We don't have a global homepage. Our structure looks like this:
The extra node mentioned in the other posts is for a setup where there is one main page, and language sites under it. Your setup is a multilanguage site without a general 'main page', each language has its own 'main page'.
I noticed that you want en as a default page to redirect. Umbraco makes this easy. Whenever you browse to your site without a specific language, umbraco will select the first node in your structure. In your case 'EN'. You don't have to do anything special, just put the default language on top.
What we do is create a "variationroot" documenttype/masterpage, that contains only a macro that holds a usercontrol that checks the language of the visitors browser settings and redirects the user to the subsite of his preferred language
public System.Collections.Generic.IList<string> Languages { get; set; }
protected override void OnInit(EventArgs e) { base.OnInit(e); var preferredLanguage = ""; if (Page.Request.Cookies["preferredLanguage"] != null) { preferredLanguage = Page.Request.Cookies["preferredLanguage"].Value; if (!String.IsNullOrEmpty(preferredLanguage)) { Response.Redirect("/" + preferredLanguage); } } var cookie = new HttpCookie("preferredLnguage"); cookie.Expires = DateTime.Now.AddMonths(1); var redirectLanguage = ""; if (Page.Request.UserLanguages != null) { foreach (string language in Page.Request.UserLanguages) { if (language.Substring(0, 2).Equals("nl")) { redirectLanguage = "nl"; break; } if (language.Substring(0, 2).Equals("en")) { redirectLanguage = "en"; break; } else if (language.Substring(0, 2).Equals("fr")) { redirectLanguage = "fr"; break; } } } if (!string.IsNullOrEmpty(redirectLanguage)) { cookie.Value = redirectLanguage; Response.Cookies.Add(cookie); Response.Redirect("/" + redirectLanguage); }
var defaultLanguage = System.Configuration.ConfigurationSettings.AppSettings["DefaultLanguageRedirect"]; if (!String.IsNullOrEmpty(defaultLanguage)) { Response.Redirect(defaultLanguage); } Response.Redirect("/nl"); }
</script>
The code above also checks if a cookie exists with a user language choice, should he be a returning visitor, it's possible to save the language preference of the visitor should he prefer a different language as his browser preference. This does require additional code for the " language switch" button that you use.
In the content section, we create this structure:
Where we set the locale for the NL and FR pages. All other content is created below these pages (except mayby a custom 404 error, and googlesitemap.xml file for SEO)
For the NL and FR (and other languages) i also set the locale using the "manage hostnames" menu in the context menu of the page:
Detail of the hostname configuration for the dutch version of the website:
The benifit of setting the language this way, is that you can start using dictionary items in your templates and xslt files etc, I also recommend creating a dictionary item "language" with the short keys "en;fr;nl;" in them, so you can test against these columns in xslt in choice statements, to run different queries depening on language
Very informative example - my question though .. after having made the files etc .. even created the template, macro (and doctype) .. do I call this from anyplace or? (if so how/from where)? ;)
Oh sorry .. when those files are done and the respective macro, doctype + templates are made - do I need to "put in a bit of code" anywhere to "activate / call" the Variationroot functionality? ;)
The variationroot should be in the top of your tree, so it gets loaded as the first page, and it'll then automatically redirect to /nl or /fr or /en depening on how you modified the ascx file.
You shoudn't need to do anything else yourself.
A live working example is www.recytyre.be -> you never see the variationroot page, you just get redirected to your language (or the default setting in the ascx file)
When you write "top of the tree" what exactly do you mean ? - What I did was to copy your example and make the relevant files (with a few modifications da,en,ru) - then I made the macro (pointing it to the ascx i modified slightly) .. Made the template (Variationroot.master) and the document types (with nothing marked in the structure pane or elsewhere) ..
I guess what you mean is to sort the Variationroot template as the first? ;)
I disable the .aspx in my config file, this way you have less different url's and it appears clearer to the visitor
in web.config change this to true:
ofcourse, doing this on a production site is bad, as all your url's change to the version without .aspx (the pages still work, but i think google might see them as new pages, losing the page rank they might have already obtained.
in case of a production site you might want to change the usercontrol to redirect to /lang.Aspx instead of /lang
I have followed your setup and made a variationroot which redirects to subnodes da, de, en depending on language. I've setup hostnames for the subnodes like mydomain.tld/da, mydomain.tld/de and mydomain.tld/en.
I've also changed the entry usedomainprefixes in umbracoconfig to true. However, when i'm accessing my site i'm being redirected as expected but then the funny thing starts: Respone from mydomain.tld/da and the others are "An error occurred when processing your request."
Any idea what i'm doing wrong? I'm new to Umbraco, but definitely not new to asp.net.
Problem solved. It turned out that i had a deleted node i recycle bin set with hostnames mydomain.tld. After deleting this node completely site works like a charm!
Thanks to Rik Helsen for his nice language redirector script!
I haven't created a multi-lingual site yet, but reading over the forum posts etc it seems a little counter-intuitive to me to have 3 different versions of the site tree.
Has anybody thought of creating a site structure like this:
Home - Page 1 - en - nl - de - Page 2 - en - nl - de
Then, the overall site structure can be driven by the actual page nodes, and the content for each language in the language nodes within the current page. In the templates, instead of inserting the page content item directly, we could insert a macro which accepts the content item name as a parameter, and that macro then determine's which language the user is currently viewing, and pulls the content from the named element under in the appropriate language sub-node.
While writing this, i've discovered that sub pages might be an issue, so perhaps a tree structure like this would be better:
Home - Page 1 - _copy - en - nl - de - Page 1a - _copy - en - nl - de - Page 1b
Provided the name of the _copy and language nodes are always the same, our macros can refer to those nodes by name. And provided the elements within each language node are named identically, the macro can easily find the correct element to insert.
Has anybody gone down this path before? Are there any discussions around this as I'm sure there are things I haven't thought of yet (and don't really want to go down the path of reinventing a solution that turned out to be more trouble than it was worth for the last person that tried it)
- what will actual url's look like? you'd have urls that are not lanuage-specific if i'm right?
- what if something is called the same in 2 languages? (url conflict) how could you prevent the content editor to enter the same information (URL) for 3 languages)
- does it make it easier for content managers if you have 20 pages below a site with each having 3 subitems for languages?
-what if you have a content editor for each language, how would you give them access?
the only benefit you have over a 1:1 multilingual setup would be different node-names (URL's) for all languages, but i don't see how you'd realise this (getting it to work), compared toa 1:1 setup it's also a lot more complex.
Are there benefits to your approach that i'm not seeing? please tell me what you think they would be!
Hey Rik... some good suggestions there... read below to my answers:
Greg: some thoughts when i see your structure:
- what will actual url's look like? you'd have urls that are not lanuage-specific if i'm right?
No, i intend for all languages to have the same urls. The URL will only be taken from the actual pages (with a name).. the languages will have a specific doc type, which i'll set to umbracoNaviHide. So the actual page node that gets the url, will have a template with macros to pull the information from the children language nodes' content items, and render them on the page. I can set some rules here, like "If current user is german, and if german language node exists, display german, otherwise display english" - that way not every page needs to be translated.
- what if something is called the same in 2 languages? (url conflict) how could you prevent the content editor to enter the same information (URL) for 3 languages)
as above, the url is created by the actual page node, not the language nodes
- does it make it easier for content managers if you have 20 pages below a site with each having 3 subitems for languages?
I think it'd be easier to maintain the site structure this way, as moving pages around etc will keep the languages all in sync (the 1:1 method requires this to be done in each language, resulting in sites structures not matching between languages). I could setup an event trigger to create all the language subnodes automatically when a new page is created, so all the user has to do is populate the content in the page and language nodes. I think creation effort would be similar between the 2 approaches, the saving would be in the maintenance.
-what if you have a content editor for each language, how would you give them access?
Now THAT is something I hadn't thought of before. I couldn't. Not without doing some fancy event trigger code to only display language nodes relevant to the currently logged in user. Wouldn't be easy, and i'd probably shy away from this approach should this be a requirement... however it isn't for this site, and probably never will be.
the only benefit you have over a 1:1 multilingual setup would be different node-names (URL's) for all languages, but i don't see how you'd realise this (getting it to work), compared toa 1:1 setup it's also a lot more complex.
actually no, the node names would be the same, regardless of which language you're viewing.. wouldn't the 1:1 approach provide different node names?
I'd like to read more about the recommended method of setting up a 1:1 multi-lingual site, but it seems all the links i can find are broken (our.umbraco.org keeps changing its structure and breaking links)... i found this forum post on stack overflow, which seems to link to all the relevant wiki pages, but they're all broken: http://stackoverflow.com/questions/3573563/creating-a-multilingual-site-in-umbraco
Anybody got the actual links, or know of good resources i can read?
Also any other issues with my approach that i haven't thought of? I'm still not sure which way i'll go.... still weighing up the pros and cons. :)
Greg: you're mixing 2 concepts, a 1:1 site is where you have a doctype with a content (tinymce) for each language, it's quite identical to your setup in result, but a lot easier to setup, you just add the page title and content for each language as property to the "page" document type, and in the page template use xslt macro and a language parameter to determine what language to output.
I don't see much difference (if there is, please point it out to me) between this approach ( properties for each language) and having nested doctypes (more elaborate to create new content compared the the properties approach) in the way a visitor or searchengine experiences the website
in both cases, my concept of having a unique tree for each language will outperform your website from an SEO point of view, having a relevant url for every language version. This alone was enough for me to promote this way of working.
keep that feedback/opinions coming :) maybe we'll work out somethinge even better :p
ahhhhhh... okay, now i understand the 1:1 idea. that makes perfect sense.
I dont like giving editors just a RTE.. i prefer to break stuff up into small components as much as possible.. and to use tabs to separate and group items.. i guess i could have separate tabs for each language.. .that would be even better than my idea i think.. but lots of items on a single tab can be a bit messy. hmmmm
But yeah... i think i'm swaying towards the separate trees approach. Can then have different URLs for each language, and ability to split up editors between languages. definitely advantages there.
i'll take another look at your appraoch Rik, and let u know what i go for in the end.
I have my site in production for almost a year now. The site is in english.So for SEO reasons then I really don't want to change the structure of the website.
But now we want to incorporate a Danish and Dutch sub-site in the form that we will have:
yoursite.com (English main site)
yoursite.com/da (Danish sub site)
yoorsite.com/nl (Dutch sub site)
Can anyone tell me if this could cause problems of if I can't do the multi language setup. I also noticed when I did this, then my top navigation macro's for the da site included the top navigation of the main site. And here it naturally only should be the sub pages for the da site.
Sounds like you need to update your macro to get navigation links only for pages under the current page, instead of starting at the site root.
You'll probably also need to add conditions in to not generate links for items in the new language nodes, otherwise your english language site will have links to all the others too.. i'd make the /da or /nl folders have a specific doc type (language folder for example), and then add a condition in the xslt to not dig deeper if the doc type of the node is one of those.
Can post code if you're having problems with this, or post what you have and i'll help fix it.. shouldn't be hard ;)
Yes, but if I do that, then when I'm on a subpage to the main site, then it will also only show the sub pages for this page. That's why I think it could be a problem.
Or is it possible to put in a conditional check in the navigation, so that when the page is beneth a language page (ex. DA or NL) then it will only take for this site?
If yes, how can this kind of conditional check be done in XSLT?
Just add a property (something like 'isSiteRoot' - true/false) to each site header page... so your site root would have the property, and each language container would too... then test against that property in your navigation xslt and use the node that contains that as your site root.
Erik: just a thought but maybe you can use the 301 redirect module, then move all the english content to a new subsite (all page requests will be redirected to the content in the new location) This should prevent you from loosing page-rank and usability for frequent users of your website, and give you a clean start for the multilanguage approach.
everytime you delete or move a page, it'll ad a "rewrite rule" to the 404 handler. This'll trigger only if no new page is found for the current url, and if so redirect the user to the new location of the content with a nice and clean seo-friendly redirect.
That would be a neater option.. that 301 url tracker module is excellent... if your site isn't too big, i'd recommend doing this...there's some overhead in setting it up, but in the long run it'll be much easier to maintain the site if its setup properly from the start.
<li> <!-- Add the class selected if the root node ID matches our current node ID in the for each loop --> <xsl:if test="$rootNode/@id = $currentPage/@id"> <xsl:attribute name="class"> <xsl:text>first</xsl:text> </xsl:attribute> </xsl:if>
<xsl:for-each select="$currentPage/ancestor-or-self::node/node [@level = 2 and string(data[@alias='umbracoNaviHide']) != '1']"> <li> <!-- Add the class selected if the currentpage or parent nodes (up the tree to the root) ID matches our current node ID in the for each loop --> <xsl:if test="$currentPage/ancestor-or-self::node/@id = current()/@id"> <xsl:attribute name="class"> <xsl:text>first</xsl:text> </xsl:attribute> </xsl:if>
And if you have a property called isRootNode set on each of the roots, it'll select that node as your root.
Seems too simple, but i think that's all you'll need :)
I"m guessing you're getting that error cos the xpath is failing - for level 1 nodes there will be no ancestor or self with level of 2, so it wont get a rootNode, and it'll fail when it calls that variable.
Like many of the people here I also got problems with my navigation menu. My current code shows all the languages and their childnodes. How can I only show the childnodes of the current language node?
I'm using Rik's configuration (which works great btw!!)
<!-- update this variable on how deep your site map should be --> <xsl:variable name="maxLevelForSitemap" select="6"/> <xsl:template match="/"> <div id="myslidemenu" class="jqueryslidemenu"> <ul> <li><a href="/" class="firstlink">Home</a></li> </ul> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::* [@isDoc and @level=1]"/> </xsl:call-template> </div> </xsl:template>
<xsl:template name="drawNodes"> <xsl:param name="parent"/> <xsl:if test="umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1 and umbraco.library:IsLoggedOn() = 1)"> <ul> <xsl:for-each select="$parent/* [@isDoc and string(umbracoNaviHide) != '1' and @level <= $maxLevelForSitemap and string(@template) != '0' and name() != 'HomeImage']"> <li> <a href="{umbraco.library:NiceUrl(@id)}"> <xsl:value-of select="@nodeName"/></a> <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1' and @level <= $maxLevelForSitemap and string(@template) != '0' and name() != 'HomeImage']) > 0"> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="."/> </xsl:call-template> </xsl:if> </li> </xsl:for-each> </ul> </xsl:if> </xsl:template> </xsl:stylesheet>
MultiLanguage same Domain ?
How would I go by showing content depending on what language the user/browser is using, on the same domainname?
How to do this, and still be able to have culture features, like dictionary and such.
The idea is as following:
www.mysite.com/da/rootnode.aspx for the danish users, and www.mysite.com/en/rootnode.aspx for the english users, this is easy, just not put any specific domainnames on any of the root nodes, but then I loose the culture.
As far as i understand, you can only put www.mysite.com on one of the rootnodes, and thereby be restricted to that rootnode, and have to have a second domain assigned to the other rootnode to change culture.
Best regards,
Robin.
PS: Im not sure this is the right place to put this question.
Hi Zen I suppose my question is there any reason for not having different domains/subdomains?
Surely you could just have en.mysite.com and da.mysite.com if you only have access to one domain?
If you using two domains/subdomains then to be honest I am not sure how I would go about this at the minute (need some cafine first!)
Warren
Moved topic here as it didn't really fit in other category (this category isn't a perfect fit as well, but much closer...)
You can actually also create hostnames within Umbraco like this: and /en/da
damn formatting :) www.mysite.com/en and www.mysite.com/da
@ Roel Are you sure it works like this?
Becaus I tried this: I coppied the root and gave them hostnames like in your example. problem was that all links still go to the root of the site www.mysite.com!
I didn't really look into this so maybe I'm doing something wrong!
Is your site set up as followed?
Content
- DA home
--- you DA site items
--- ...
--- more DA items
- EN home
--- you EN site items
--- ...
--- more EN items
and also I think it's not good for SEO if you use: da.mysite.com!
I have 2 nodes already DA and EN, but how would I associate "danish" culture to the DA node, and the "english" culture to the EN node.
Warren: the reason for not using subdomains, is more in the line of "thats how the customer wants it", :p
I read something about changing something in the web.config and the umbracoConfig files, to allow it to handle multiple cultures on same domain, but different root nodes.
But as this is the first time I have come across this, I have no clue on how to proceed.
Bert: Yes exactly like that
I am no SEO expert, far from it !
Sounds like you need to speak to Roel as he seems like he has done this before.
I have an idea, just wanna share it with you guys, and get some feed back on it.
I would create a new Rootnode, and assign www.mysite.com to this rootnode.
Then I would take the DA node and assing www.mysite.com/da to it, and set the culture to danish,
and repeat this for the EN node, just with the english culture
And then I would do a serverside redirect on the new rootnode, that would sent it to the www.mysite.com/en.
Would this be possible ?,
Would I later be able to do serverside redirect via xslt, due to the fact, that the users must be able to choose what site to be directed into, after first visit.
Serverside redirect isn't possible in xslt, but you can add <script runat="server"> with logic to template and handle redirect here.
No need for a server side redirect, just use the wonderful umbracoInternalRedirectId as described here and here
Cheers,
Dirk
I'm also no SEO expert :-)
I think I read on the forum thats someone made a .NET control that reads the browser language and redirect to the proper root!
unfortunately I can't find the post :-(
Is this the sort of thing you are looking for: http://www.barclay.ie/ which is a multi-lingual site we developed recently, it has multiple languages and cultures running off of a single domain name.
We just set the site up as if it had sub-domains i.e. uk.barclay.ie but just don't use them, this means that Umbraco just works out the culture from where you are in the content tree.
If this is the sort of thing you are after I can post more detail.
Tim
Here's a post about getting a browsers language/culture: http://madskristensen.net/post/Get-language-and-country-from-a-browser-in-ASPNET.aspx
It's not Umbraco specific but shouldn't be too hard to create a user control based on it which would re-direct the users to the correct page.
Tim
Great Tim, very nice site btw!!
I think that's what we are looking for, right Zen?
I think detecting browser settings is just an extra step so I would appriciate if you could give us some more information!
Hey yes, that is about right, but my client has a somewhat unique ideƩr, they want the danish part shown when it is machines with an ip in denmark that surfs into the site, and the english content shown when its not an danish ip, this is something I am not even sure is dooable in umbraco.
Try add this into your homepage
<script runat="server">
protected void Page_Load(object sender, EventArgs e) {
if (IsDenmarkIP(Request.UserHostAddress()) Response.Redirect("http://example.com/denmark/")
Response.Redirect("http://example.com/english/")
}
private bool IsDenmarkIP(String IP) {
// your code to determine if user is in denmark
}
</script>
Petr
Into homepage template of course.
(I don't know how to edit previous post)
okay thank you I will, if it does not mess with SEO stuff. thank you :)
Sorry for the delay in me adding more info on how we achieved the multi-lingual effect on Barclay. Paid work takes priority!
To get the multi lingual capabilities to work we set up the site as follows:
Global HomepageUKUKPages etcGermanyGerman pages etcSwedenSwedish pages etc.
In hindsight I should have called the county pages by their country code i.e. en for english, de for german. Ahh well next time!
Each country was then given a fake sub-domain in the manage hostnames dialog box. The sub-domain was associated with the correct language for the country. i.e. uk.barclay.ie. These subdomains are never actually used.
Now here's the important bit. The global homepage must not be mapped to the main domain i.e. www.barclay.ie otherwise Umbraco just uses the language setting for that domain on all sub sites. So again on the global homepage you set up a fake subdomain i.e. global.barclay.ie
In regards to the IP mapping, as others have said you can do this using a user control. What you will need however is a way of determining the country by IP address.
I have been working recently on a project whcih involves heavy use of geo-location both by IP and address etc. So have been researching free/cheap DBs of IP to geo-location mappings.
Here's one that I found:
http://www.maxmind.com/app/geolitecity
Not tried it but it seems fairly comprehensive.
Rats!
The editor has spooned my post!
The bit it removed was this:
Which was the example site structure!
Tim,
I think your experiences in setting up multilingual sites are truly wiki worth pages, would you mind adding the setup you've been using on a wiki page for everyone to read?
Cheers,
/Dirk
A step by step guide could be usefull...
for instance, new users don't understand this: "The global homepage must not be mapped to the main domain i.e. www.barclay.ie otherwise Umbraco just uses the language setting for that domain on all sub sites. So again on the global homepage you set up a fake subdomain i.e. global.barclay.ie"
This rises the questions:
* How do I change the mapping of the global homepage?
* what if i don't want a global homepage? I prefer using the browser locale (the country a user is in doesn't reflect a users language accurately)
I've created a global homepage with two subsites (EN / NL) and have assigend a bogus subdomain with the language setting defined for each.
Should the global hompage have a bogus domain name assigned too? if so then i also need to define a language for it right?
also: any suggestions on how I get umbraco to automaticall load the subsite with the same locale as the visitors browser locale?
I think you're right on the step by step, I'll edit the post what I get 5 mins to make it more accessible.
You don't need to set up a bogus sub-domain for the global page (although I did because I wanted to ensure I could set the language on the global page as well), but it's important that the main site URL is not added as a hostname for the global page.
As for loading the sub-site based on the users locale...
Off the top of my head the only (easy and quick) way I can think to do it is to create UserControl which re-directs the user to the correct sub-site based on their UserLangauges settings:
for example:
That's un-tested code I've written straight out, so no guarantees that it'll run first time! It could probably do with a tidy as well as it's a bit nested, but should point you in the right direction.
Again when I get a bit of time I'll add a proper code sample to the Wiki page.
Also, not sure you've seen the Wiki version of this post: http://our.umbraco.org/wiki/how-tos/running-multi-lingual-sites-under-a-single-domain
Which may be clearer?
Yes I did find the wiki page, but found it to be a pretty much identical copy from the forum discussion in this topic...
I'm going to have to ask one of our developers to take a look at making your code snippet into a control i can use to create a module.
Hi,
i'm looking for the best way to adopt this way of creating a multi lingual site for our needs.
We don't have a global homepage. Our structure looks like this:
Content
--en
----englisch content tree...
--de
----german content tree...
Do i have to implement it like this:
Content
--Start
----en
------englisch content tree...
----de
------german content tree...
where Start redirects to the english Home (default)?
Thanks
Matthias
Matthias, you don't have to have a Start node. Your structure is fine as it is.
Once set up add right click the en, de ... nodes --> manage hostnames --> add www.yoursite.com/de (language german)
Repeat for other languages.
I always add 3 hostnames for each language: yoursite.com/de, www.yoursite.com/de and de.yoursite.com
I got no idea if this final step is necessary, maybe other could elaborate on that?
The extra node mentioned in the other posts is for a setup where there is one main page, and language sites under it. Your setup is a multilanguage site without a general 'main page', each language has its own 'main page'.
I noticed that you want en as a default page to redirect. Umbraco makes this easy. Whenever you browse to your site without a specific language, umbraco will select the first node in your structure. In your case 'EN'. You don't have to do anything special, just put the default language on top.
Hi Bert,
many thanks for your help. Works as suggested :-)
Hi. Sorry for saying this, but I don't understand anything. I've read the wiki, and same thing,
I'm new to Umbraco, but not to asp.net nor web development. Will apreciate a real step by step guide.
Thanks
What we do is create a "variationroot" documenttype/masterpage, that contains only a macro that holds a usercontrol that checks the language of the visitors browser settings and redirects the user to the subsite of his preferred language
Variationroot.master:
languageredirectcontrol.ascx:
The code above also checks if a cookie exists with a user language choice, should he be a returning visitor, it's possible to save the language preference of the visitor should he prefer a different language as his browser preference. This does require additional code for the " language switch" button that you use.
In the content section, we create this structure:
Where we set the locale for the NL and FR pages. All other content is created below these pages (except mayby a custom 404 error, and googlesitemap.xml file for SEO)
For the NL and FR (and other languages) i also set the locale using the "manage hostnames" menu in the context menu of the page:
Detail of the hostname configuration for the dutch version of the website:
The benifit of setting the language this way, is that you can start using dictionary items in your templates and xslt files etc, I also recommend creating a dictionary item "language" with the short keys "en;fr;nl;" in them, so you can test against these columns in xslt in choice statements, to run different queries depening on language
@Rik Helsen
Very informative example - my question though .. after having made the files etc .. even created the template, macro (and doctype) .. do I call this from anyplace or? (if so how/from where)? ;)
Call what exactly? your question isn't completely clear
Oh sorry .. when those files are done and the respective macro, doctype + templates are made - do I need to "put in a bit of code" anywhere to "activate / call" the Variationroot functionality? ;)
The variationroot should be in the top of your tree, so it gets loaded as the first page, and it'll then automatically redirect to /nl or /fr or /en depening on how you modified the ascx file.
You shoudn't need to do anything else yourself.
A live working example is www.recytyre.be -> you never see the variationroot page, you just get redirected to your language (or the default setting in the ascx file)
Hi Rik,
When you write "top of the tree" what exactly do you mean ? - What I did was to copy your example and make the relevant files (with a few modifications da,en,ru) - then I made the macro (pointing it to the ascx i modified slightly) .. Made the template (Variationroot.master) and the document types (with nothing marked in the structure pane or elsewhere) ..
I guess what you mean is to sort the Variationroot template as the first? ;)
in the content section, make sure variationroot is the top-first item (www in this screenshot)
Then it should automatically execute whenever someone loads your website using the plain www.something.com url
Hello and thanks in advice
I've followed all the step and all is almost working.
But the redirection target http://site/lang end in 404 error, it can't find
http://site/lang
but http://site/lang.aspx is working.
am i missing something?
Fabio
I disable the .aspx in my config file, this way you have less different url's and it appears clearer to the visitor
in web.config change this to true:
ofcourse, doing this on a production site is bad, as all your url's change to the version without .aspx (the pages still work, but i think google might see them as new pages, losing the page rank they might have already obtained.
in case of a production site you might want to change the usercontrol to redirect to /lang.Aspx instead of /lang
great !!
simple ideas rock.
On my site i'm using RunawayTopNavigation.xslt
i'm looping through child pages of http://site/lang with
<xsl:for-each select="$currentPage/ancestor-or-self::node[@level=$currentPage/@level]/node [string(data [@alias='umbracoNaviHide']) != '1']">
this is working fine on the lang page
but is not working anymore on the childpage of the lang.
Onestly i'm not a ninja with xslt, does someone know what i'm doing wrong ?
Fabio
Does it have a maximum depth defined? post the entire xslt please
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library"
exclude-result-prefixes="msxml umbraco.library">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<!-- Input the documenttype you want here -->
<xsl:variable name="level" select="1"/>
<xsl:template match="/">
<!-- The fun starts here -->
<ul id="topnavigation">
<xsl:for-each select="$currentPage/ancestor-or-self::node[@level=$currentPage/@level]/node [string(data [@alias='umbracoNaviHide']) != '1']">
<li>
<a href="{umbraco.library:NiceUrl(@id)}"> <xsl:value-of select="@nodeName"/> </a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
Try changing
to
This is a navigation that only shows items from a fixed level in your content tree, all the rest isn't returned because of this piece in the xslt:
with level=2 i can't get it working,
i'm obtaining bettere results with
now my menu for lang1 is
[lang1] - [lang1 page1] - [lang1 page2]
[lang1] should not be there, how can i change the foreach to remove lang?
Fabio
I've solved altering the document type of runaway home page, adding the HIde from Navigation property.
if someone know a better way to do that, feel free to tell.
Fabio
Hi Rik,
Ahh - ok .. my site looks like this:
Content
da
en
de
fr
ru
Is it safe to put in Variationroot on that setup? ;)
Chief:
You can use it anywhere as long as you have a page (to put the control on) above all your languagespecific homepages you can use this control
@Rik Helsen.
I tried your sugestion
"disable the .aspx in my config file, this way you have less different url's and it appears clearer to the visitor in web.config change this to true"
But the pages still need the .aspx extension to work. Is there something I need to do after modifiying the web.config?
Thanks for any help.
@Rik Helsen and other wiz's!
I have followed your setup and made a variationroot which redirects to subnodes da, de, en depending on language. I've setup hostnames for the subnodes like mydomain.tld/da, mydomain.tld/de and mydomain.tld/en.
I've also changed the entry usedomainprefixes in umbracoconfig to true. However, when i'm accessing my site i'm being redirected as expected but then the funny thing starts: Respone from mydomain.tld/da and the others are "An error occurred when processing your request."
Any idea what i'm doing wrong? I'm new to Umbraco, but definitely not new to asp.net.
Problem solved. It turned out that i had a deleted node i recycle bin set with hostnames mydomain.tld. After deleting this node completely site works like a charm!
Thanks to Rik Helsen for his nice language redirector script!
Hey all,
I haven't created a multi-lingual site yet, but reading over the forum posts etc it seems a little counter-intuitive to me to have 3 different versions of the site tree.
Has anybody thought of creating a site structure like this:
Home
- Page 1
- en
- nl
- de
- Page 2
- en
- nl
- de
Then, the overall site structure can be driven by the actual page nodes, and the content for each language in the language nodes within the current page. In the templates, instead of inserting the page content item directly, we could insert a macro which accepts the content item name as a parameter, and that macro then determine's which language the user is currently viewing, and pulls the content from the named element under in the appropriate language sub-node.
While writing this, i've discovered that sub pages might be an issue, so perhaps a tree structure like this would be better:
Home
- Page 1
- _copy
- en
- nl
- de
- Page 1a
- _copy
- en
- nl
- de
- Page 1b
Provided the name of the _copy and language nodes are always the same, our macros can refer to those nodes by name. And provided the elements within each language node are named identically, the macro can easily find the correct element to insert.
Has anybody gone down this path before? Are there any discussions around this as I'm sure there are things I haven't thought of yet (and don't really want to go down the path of reinventing a solution that turned out to be more trouble than it was worth for the last person that tried it)
Thanks heaps
Greg
Greg: some thoughts when i see your structure:
- what will actual url's look like? you'd have urls that are not lanuage-specific if i'm right?
- what if something is called the same in 2 languages? (url conflict) how could you prevent the content editor to enter the same information (URL) for 3 languages)
- does it make it easier for content managers if you have 20 pages below a site with each having 3 subitems for languages?
-what if you have a content editor for each language, how would you give them access?
the only benefit you have over a 1:1 multilingual setup would be different node-names (URL's) for all languages, but i don't see how you'd realise this (getting it to work), compared toa 1:1 setup it's also a lot more complex.
Are there benefits to your approach that i'm not seeing? please tell me what you think they would be!
Hey Rik... some good suggestions there... read below to my answers:
Greg: some thoughts when i see your structure:
- what will actual url's look like? you'd have urls that are not lanuage-specific if i'm right?
No, i intend for all languages to have the same urls. The URL will only be taken from the actual pages (with a name).. the languages will have a specific doc type, which i'll set to umbracoNaviHide. So the actual page node that gets the url, will have a template with macros to pull the information from the children language nodes' content items, and render them on the page. I can set some rules here, like "If current user is german, and if german language node exists, display german, otherwise display english" - that way not every page needs to be translated.
- what if something is called the same in 2 languages? (url conflict) how could you prevent the content editor to enter the same information (URL) for 3 languages)
as above, the url is created by the actual page node, not the language nodes
- does it make it easier for content managers if you have 20 pages below a site with each having 3 subitems for languages?
I think it'd be easier to maintain the site structure this way, as moving pages around etc will keep the languages all in sync (the 1:1 method requires this to be done in each language, resulting in sites structures not matching between languages). I could setup an event trigger to create all the language subnodes automatically when a new page is created, so all the user has to do is populate the content in the page and language nodes. I think creation effort would be similar between the 2 approaches, the saving would be in the maintenance.
-what if you have a content editor for each language, how would you give them access?
Now THAT is something I hadn't thought of before. I couldn't. Not without doing some fancy event trigger code to only display language nodes relevant to the currently logged in user. Wouldn't be easy, and i'd probably shy away from this approach should this be a requirement... however it isn't for this site, and probably never will be.
the only benefit you have over a 1:1 multilingual setup would be different node-names (URL's) for all languages, but i don't see how you'd realise this (getting it to work), compared toa 1:1 setup it's also a lot more complex.
actually no, the node names would be the same, regardless of which language you're viewing.. wouldn't the 1:1 approach provide different node names?
I'd like to read more about the recommended method of setting up a 1:1 multi-lingual site, but it seems all the links i can find are broken (our.umbraco.org keeps changing its structure and breaking links)... i found this forum post on stack overflow, which seems to link to all the relevant wiki pages, but they're all broken: http://stackoverflow.com/questions/3573563/creating-a-multilingual-site-in-umbraco
Anybody got the actual links, or know of good resources i can read?
Also any other issues with my approach that i haven't thought of? I'm still not sure which way i'll go.... still weighing up the pros and cons. :)
Greg: you're mixing 2 concepts, a 1:1 site is where you have a doctype with a content (tinymce) for each language, it's quite identical to your setup in result, but a lot easier to setup, you just add the page title and content for each language as property to the "page" document type, and in the page template use xslt macro and a language parameter to determine what language to output.
I don't see much difference (if there is, please point it out to me) between this approach ( properties for each language) and having nested doctypes (more elaborate to create new content compared the the properties approach) in the way a visitor or searchengine experiences the website
in both cases, my concept of having a unique tree for each language will outperform your website from an SEO point of view, having a relevant url for every language version. This alone was enough for me to promote this way of working.
keep that feedback/opinions coming :) maybe we'll work out somethinge even better :p
ahhhhhh... okay, now i understand the 1:1 idea. that makes perfect sense.
I dont like giving editors just a RTE.. i prefer to break stuff up into small components as much as possible.. and to use tabs to separate and group items.. i guess i could have separate tabs for each language.. .that would be even better than my idea i think.. but lots of items on a single tab can be a bit messy. hmmmm
But yeah... i think i'm swaying towards the separate trees approach. Can then have different URLs for each language, and ability to split up editors between languages. definitely advantages there.
i'll take another look at your appraoch Rik, and let u know what i go for in the end.
thanks heaps
Good luck :)
A little additional question to this subject.
I have my site in production for almost a year now. The site is in english.So for SEO reasons then I really don't want to change the structure of the website.
But now we want to incorporate a Danish and Dutch sub-site in the form that we will have:
Can anyone tell me if this could cause problems of if I can't do the multi language setup. I also noticed when I did this, then my top navigation macro's for the da site included the top navigation of the main site. And here it naturally only should be the sub pages for the da site.
Rgds,
Erik
Sounds like you need to update your macro to get navigation links only for pages under the current page, instead of starting at the site root.
You'll probably also need to add conditions in to not generate links for items in the new language nodes, otherwise your english language site will have links to all the others too.. i'd make the /da or /nl folders have a specific doc type (language folder for example), and then add a condition in the xslt to not dig deeper if the doc type of the node is one of those.
Can post code if you're having problems with this, or post what you have and i'll help fix it.. shouldn't be hard ;)
Hi Greg,
Yes, but if I do that, then when I'm on a subpage to the main site, then it will also only show the sub pages for this page. That's why I think it could be a problem.
Or is it possible to put in a conditional check in the navigation, so that when the page is beneth a language page (ex. DA or NL) then it will only take for this site?
If yes, how can this kind of conditional check be done in XSLT?
Erik
Just add a property (something like 'isSiteRoot' - true/false) to each site header page... so your site root would have the property, and each language container would too... then test against that property in your navigation xslt and use the node that contains that as your site root.
Erik: just a thought but maybe you can use the 301 redirect module, then move all the english content to a new subsite (all page requests will be redirected to the content in the new location) This should prevent you from loosing page-rank and usability for frequent users of your website, and give you a clean start for the multilanguage approach.
More info about the project:
http://our.umbraco.org/projects/developer-tools/301-url-tracker
everytime you delete or move a page, it'll ad a "rewrite rule" to the 404 handler. This'll trigger only if no new page is found for the current url, and if so redirect the user to the new location of the content with a nice and clean seo-friendly redirect.
That would be a neater option.. that 301 url tracker module is excellent... if your site isn't too big, i'd recommend doing this...there's some overhead in setting it up, but in the long run it'll be much easier to maintain the site if its setup properly from the start.
Thanks Rik, this sounds like a much easier and more future-proof way to do it.
The only problem is that I cannot get this URL tracker to work (I have posted a bug post)...
Erik
it doesn't support 4.5 (yet) i believe
@Greg: My top navigation currently looks like this:
@Greg:
If I change
<xsl:variable name="rootNode" select="$currentPage/ancestor-or-self::node [@level = 1]" />
to
<xsl:variable name="rootNode" select="$currentPage/ancestor-or-self::node [@level = 2]" />
then I'm getting a debug error...
I reckon you can just replace the xpath to the root node, currenlty:
<xsl:variable name="rootNode" select="$currentPage/ancestor-or-self::node [@level = 1]" />
with this:
<xsl:variable name="rootNode" select="$currentPage/ancestor-or-self::node [@isRootNode = 1]" />
And if you have a property called isRootNode set on each of the roots, it'll select that node as your root.
Seems too simple, but i think that's all you'll need :)
I"m guessing you're getting that error cos the xpath is failing - for level 1 nodes there will be no ancestor or self with level of 2, so it wont get a rootNode, and it'll fail when it calls that variable.
Thanks. I actually went and downloaded the COQNavigation package, and with a very little change, then this does it for me.
Hi guys,
Like many of the people here I also got problems with my navigation menu. My current code shows all the languages and their childnodes. How can I only show the childnodes of the current language node?
I'm using Rik's configuration (which works great btw!!)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
exclude-result-prefixes="msxml
umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes
Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings
Exslt.ExsltSets ">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<!-- update this variable on how deep your site map should be -->
<xsl:variable name="maxLevelForSitemap" select="6"/>
<xsl:template match="/">
<div id="myslidemenu" class="jqueryslidemenu">
<ul>
<li><a href="/" class="firstlink">Home</a></li>
</ul>
<xsl:call-template name="drawNodes">
<xsl:with-param name="parent" select="$currentPage/ancestor-or-self::* [@isDoc and @level=1]"/>
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="drawNodes">
<xsl:param name="parent"/>
<xsl:if test="umbraco.library:IsProtected($parent/@id,
$parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id,
$parent/@path) = 1 and umbraco.library:IsLoggedOn() = 1)">
<ul>
<xsl:for-each select="$parent/*
[@isDoc and string(umbracoNaviHide) != '1' and @level <=
$maxLevelForSitemap and string(@template) != '0' and name() !=
'HomeImage']">
<li>
<a href="{umbraco.library:NiceUrl(@id)}">
<xsl:value-of select="@nodeName"/></a>
<xsl:if test="count(./*
[@isDoc and string(umbracoNaviHide) != '1' and @level <=
$maxLevelForSitemap and string(@template) != '0' and name() !=
'HomeImage']) > 0">
<xsl:call-template name="drawNodes">
<xsl:with-param name="parent" select="."/>
</xsl:call-template>
</xsl:if>
</li>
</xsl:for-each>
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Joel in my case the homepage node is of the homepage doctype, to select the starting node of my navigation I use xpath to select that node
So this would look something like this (4.5 and higher)
You could have a look at this package here that I have created.
http://our.umbraco.org/projects/developer-tools/ip2location-integration
It can be used along with a free IP Location database to do the trick for you.
is working on a reply...