Meertalige websites

Door Elger Mensonides
zaterdag 10 januari 2009

Meertalige websites in ASP.NET en url-rewriting.

Stel je wilt een meertalige website met engels en nederlands, hoe pak je dit aan? Hoe zorg ik ervoor dat al mijn paginas in alle talen worden geindexeerd door google? Is mijn website nog wel te beheren nadat ik 'm meertalig heb gemaakt? Dit artikel laat zien hoe je een meertalige website kan bouwen in ASP.NET dat ook nog eens heel erg eenvoudig te maken en te beheren is.

Kies een techniek

Cookies

Je zou ervoor kunnen kiezen om de taal in een cookie of session op te slaan en op basis hiervan de verschillende taal-content te tonen. Echter werkt dit niet met zoekmachines, deze werken namelijk niet met cookies en sessions en zullen dus de eerst beschikbare taal indexeren.

Querystring

Al een stuk dichter in de buurt kom je met querystrings. Een voorbeeld:

    http://www.example.com/contact.html?language=en
    http://www.example.com/contact.html?language=nl

Op deze manier heb je voor een zoekmachine 2 pagina's om te tonen. Echter is het maar de vraag of een zoekmachine als google beide urls zal bezoeken, en, mocht de content ondanks de taalverschillen veel op elkaar lijken dan wordt er meestal maar 1 geindexeerd.

Domeinen

Zoekmachines als google herkennen tegenwoordig meertalige websites, volgens google is het gebruik van domeinen het meest ideaal. Zo kun je een site maken die gebruik maakt van 2 domeinen:

    voorbeeld.nl
    voorbeeld.com

Waarbij de 2e de engelse website is. Deze oplossing is het lastigst de beheren omdat je 2 domeinen nodig hebt en ook het duurste. Verder kan het voor de eindgebruiker verwarrend zijn doordat voorbeeld.nl de indruk geeft een andere website te zijn dan voorbeeld.com.

Subdomeinen

Een stuk gemakkelijker te beheren en nummer 2 op onze ranglijst zijn subdomeinen:

    nl.voorbeeld.com
    en.voorbeeld.com

Een bekende website is wikipedia die een dergelijk systeem implementeert. Deze structuur is het meest duidelijk voor de eindgebruiker. Toch kleeft hier weer een nadeel aan, stel je wilt een blog toevoegen aan je site of een bestel gedeelte. Het zou mooi zijn om dan blog.voorbeeld.com of bestel.voorbeeld.com te kunnen gebruiken. Dit kan dus niet in geval van de taal opdelen in subdomeinen.

Sub mappen

Veruit het meest gebruikt en nog steeds herkenbaar door zoekmachines zijn submappen:

    voorbeeld.com/nl/
    voorbeeld.com/en/

Met deze techniek is er geen extra domeinbeheer nodig, is redelijk duidelijk voor de eindgebruiker en gemakkelijk te beheren. Dit artikel zal zich verder richten op submappen.

Waar te beginnen?

In ASP.NET kan ervoor gekozen worden om de ingebouwde Localization structuur te gebruiken echter hebben wij gekozen voor een eigen systeem omdat er nogal wat nadelen kleven aan Localization, zoals het gebruik maken van resource files, deze worden meegecompileerd in de .dll en dus bij een textuele aanpassing moet het project opnieuw gecompileerd worden.

We zullen beginnen met seach engine friendly urls, daarna kiezen we een url rewriter en vervolgens gaan we in ASP.NET aan de slag om deze urls te interpreteren en content naar de browser te sturen.

friendly url -> url rewriter -> server side processing

Friendly urls

Er moeten zinvolle url's bedacht worden. Als je een pagina hebt met gitaar bladmuziek dan wil je de urls bijvoorbeeld:

    voorbeeld.com/nl/gitaar/bladmuziek.html
    voorbeeld.com/en/guitar/tablature.html

Deze structuur zorgt ervoor dat belangrijke keywords in de url te vinden zijn, echter kan de taal niet meer eenvoudig veranderd worden door bijvoorbeeld de 'en' naar 'nl' te veranderen. Hiervoor hebben we een eenvoudige oplossing bedacht dmv de language file ook te gebruiken voor de niet-dynamische urls in je website.

Tip:
Friendly url:
http://www.nu.nl/internet/1895883/dure-gadgets-verliezen-glans.html
Sites als nu.nl zetten de titels van hun nieuwsartikelen in hun url. In diezelfde url staat altijd een id-nummer, welke gebruikt wordt om het daadwerklijke artikel uit de database te halen. De titel van het artikel is puur zoekmachine optimalisatie.

Url rewriter   

Er zijn talloze artikelen op internet te vinden over url rewriting, in dit artikel gaan we uit van een IIS webserver met ASP.NET. Er zijn twee verschillende soorten rewriters beschikbaar, als ISAPI filter of als .NET component. Performance-wise is een ISAPI filter sneller maar een project met een .NET component als rewriter is weer gemakkelijker te deployen. Echter is het installeren van een ISAPI filter vrij eenvoudig. Wij hebben gekozen voor ISAPI rewrite www.isapirewrite.com welke nu ook een gratis lite versie beschikbaar heeft. De syntax is vrijwel identiek aan die van de populaire apache mod-rewrite en daarnaast biedt het bedrijf Helicontech uitstekende support. Ook ondersteunt deze rewriter UTF-8, wat betekent dat vrijwel alle tekens in een url geplaatst kunnen worden. Denk maar aan de Duitse umlaut of een site dat ook Chinees of Thais moet ondersteunen, die tekens kunnen dan ook in de url geplaatst worden.

Rewrite code

We gebruiken 4 rewrite rules om een meertalige website met subdirs te kunnen neerzetten:

RewriteRule ^/$ /nl/ [R=301, L]

www.example.com wordt www.example.com/nl. Dit is een permanente link (301). Er kan voor gekozen worden om de gebruiker de taal te laten selecteren zodra www.example.com wordt ingetikt, in dit geval wordt er dus default naar de nederlandse versie van de site ge-redirect. Door de 301 zal google de nl versie indexeren als www.example.com en de engelse versie als www.example.com/en.

RewriteRule /(en|nl)/(.+) /$2?language=$1 [NC, QSA]

Deze regel 'stript' de nl en en van de url en stopt deze in de querystring language. De modifier QSA (append query string) zorgt ervoor dat je eventuele bestaande querystrings heel blijven.

RewriteRule /(en|nl)/$ /index.aspx?language=$1 [NC, QSA, L]

De index page voor de adressen www.example.com/en en www.example.com/nl wordt index.aspx met de language als querystring.

Server side processing

Wij gebruiken ASP.NET om de server side scripting onder handen te nemen. Om meertaligheid te implementeren gebruiken we een XML language file en hebben we een simpele language class geschreven die de XML parsed m.b.v. LINQ.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Xml;

using System.Xml.Linq;

 

public class Text

{

    private string XML;

    private Text()

    {

        System.IO.StreamReader sr = new System.IO.StreamReader(HttpContext.Current.Request.
PhysicalApplicationPath + "language/LanguageFile.xml");

        try

        {

            XML = sr.ReadToEnd();

        }

        finally

        {

            sr.Close();

        }

    }

 

    private string _GetText(string name)

    {

        // haal de language code op uit de querystring:

        string LanguageCode = HttpContext.Current.Request.QueryString.Get("language");

 

        // query de XML op basis van taal-element en languagecode:

        var text = from t in XElement.Parse(XML).Elements(name)

                   where t.Attribute("lang").Value == LanguageCode

                   select t;

 

        // indien geen resultaat, throw exception, dit kan beter veranderd worden in een productie website:

        if (text.Count() == 0)

            throw new Exception("Textelement '" + name + "' for language '" + LanguageCode + "' does not exist!");

 

        return text.First().Value;

    }

private static Text _Instance;

    public static string GetText(string name)

    {

        // instance checking: uit commenten zodra je klaar bent met ontwikkeling en testen:

        // if (_Instance == null)

        //    _Instance = new Text();

 

        return _Instance._GetText(name);

    }

}

Deze class kan aangesproken worden met:

Text.GetText("naam_van_xml_element");

Dit zal de file LanguageFile.xml openen en de value van 'naam_van_xml_element' teruggeven. De class is een singleton dus de languagefile wordt maar 1x geopend. De instance checking is hier uitgecomment zodat we de text kunnen aanpassen en gelijk veranderingen zien optreden.

Er zijn natuurlijk veel aanpassingen en verbeteringen te bedenken voor deze class maar dat valt buiten de scope van dit artikel.

Language file

Hier een voorbeeld hoe de file LanguageFile.xml eruit komt te zien:

<?xml version="1.0" encoding="utf-8" ?>
    <languagefile>
        <frontpage_header lang="nl">Welkom bij example.com!</frontpage_header>
        <frontpage_header lang="en">Welcome to example.com!</frontpage_header>
        <link_tablature lang="nl">http://voorbeeld.com/nl/gitaar/bladmuziek.html</link_tablature >
        <link_tablature lang="en">http://voorbeeld.com/en/guitar/tablature.html</link_tablature >
    </languagefile>

De code:

Text.GetText("frontpage_header");

Zal nu zodra er nl in de querystring language voorkomt de text "Welkom bij example.com" ophalen.

Zoals je ziet is dit allemaal erg eenvoudig te implementeren, je kan op deze manier dus ook meertalige links eenvoudig onderhouden. Het grootste voordeel is hoe eenvoudig het is om een extra taal toe te voegen. Dit is een kwestie van de xml file aanpassen en voor elk element de derde taal toe te voegen.




Internet bureau blog

Meertalige websites
Web design

Other languages


Copyright © 2008 Deevelop. Algemene voorwaarden