asp.net - bygg in språkberoende på din site
Förord
När man bygger en hemsida är det inte så vanligt att man gör den i flera språk men ibland kan det behövas. Jag har nu tittat på något mellanting av färdiga rutiner och egen konstruktion för att använda mig av det som i termer kallas resourcefiler som sedan kan konverteras till sattelite assemblies.Innehåll
»»
»
»
Relaterade artiklar
» Använd XML för språkoberoende hemsidor
Förord
Innan jag började så gjorde jag tvärt emot vad man skall göra - testa först och läsa sen. Egentligen är detta nog någon form av halvlösning så en revidering i framtiden - eller att någon annan skriver en bättre artikel kommer säkert, men jag är våghalsig av naturen och berättar gärna de erfarenheter jag i alla fall fick av att titta på detta.Jag ville kontrollera vad som fanns att tillgå i .net och började från början. Om du har ett .net projekt igång och vill testa detta så började jag med att addera en ny fil. Denna filen heter "Assembly Resource File". När du lägger till denna och klickar på den så får du upp ett rutnät där du har fält för name och value. Nu förstår du givetvis vad du skall skriva in i dessa fält.
Om du döper denna fil till exempelvis lang_se, skapar en till och döper den till lang_en så har du något att börja med. Default heter den första filen resource1.rsd och är egentligen en vanlig xmlfil. om du nu i name fältet på de båda filerna skriver message samt på den svenska i value anger hej, och den engelska hello så är vi igång.
Nu skall vi göra om dessa filer som tyvärr måste göras varje gång du gör ändringar i dessa för att kunna nå de som resources. Via command-prompten i den katalog där filerna ligger skriver du:
resgen lang_sv.resx
resgen lang_en.resx
Det som nu skapas är två resourcefiler som vi kan börja använda oss av i vårt asp.net projekt. Jag började titta på hur det skulle kunna ske automatiskt men hittade inget. Så skapa en .batfil som du kan köra varje gång du ändrar eller pillar i dina två filer, annars syns inte ändringarna på din hemsida. Se dessa två källfiler som ren källa och för att se resultatet så måste de köras igenom med resgen.
Byta språk
Det nästa momentet är faktiskt att på hemsidan kunna switcha mellan svenska och engelska och det är ju trevligt om det är en flagga eller något som man trycker på. För att hålla reda på vilket lands språk jag vill visa så använder jag mig av något så enkelt som ett sessionsobjekt.
Private Sub ImageButton1_Click(ByVal sender As System.Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles Imagebutton1.Click
If Session("UserCurrentLanguage") = 2 Then
Session("UserCurrentLanguage") = 1
Else
Session("UserCurrentLanguage") = 2
End If
' laddar om sidan igen för att visa ändringarna
Response.Redirect(Request.Url.ToString, True)
End Sub
På sidan default.aspx har jag lagt till en imageknapp och innehållet på den är en svensk respektive engelsk flagga som jag switchar beroende på vad man trycker. Default är det svenska när användaren kommer till sidan. Nu när vi kommit så långt är det dags för den tekniska biten och det är just att via kod peka på rätt assembly och därefter hämta ut vad det står i fältet value för "message".
Eftersom jag inte använder den förbestämda tekniken med culture så behövs inte så speciella funktioner här förutom en referens till System.Resources. Detta skriver du på översta raden i din codebehindfil på default.aspx.vb. Därefter är det enklast att lägga till en ny classfil som vi skall skriva en funktion i. Skapa en ny class där vi börjar med att först definiera upp:
Imports System.Resources
Bygg arbetsklasserna
En referens som ger oss tillträde till de objekt vi behöver men vi behöver även ta reda på vad sessionsobjektet CurrentLanguage innehåller och därför måste vi även ha en till referens och det är för att nå sessionsobjektet via klassen vi skapar nedan. Den ser ut som följer:
Imports System.Resources
Namespace Site
Public Class Language
Shared Function GetMessage(Byval Key As String) As String
' -- mer kod kommer --
End Function
End Class
End Namespace
Om vi tittar lite på koden så börjar vi med två referenser, ett för att kunna nyttja två objekt. Vi har även skapat ett namespace som bör heta något som berör sajten. Därefter är det dags att skapa en funktion där du skickar in en sträng och får tillbaks detsamma. Så det vi nu skall göra är att fylla denna funktion med lite programkod för att dels ta reda på vilket land man valt och sen hämta rätt värde ur sattelitfilen.
Innan vi går vidare skall vi skriva en funktion som hämtar sessionsobjektet för att få reda på vilket land vi har valt. Sen returnerar vi en textkod beroende på vad sessionens objekt innehåller. Om ingen session har skapats så är det svenska som gäller. Att ha något default brukar kallas fall-back.
Shared Function GetLanguage() As String
' har en egen hantering av språk då vi bara lagrar en integer
' i sessionen. rutinen hämtar vilket språk som är aktuellt att
' visa på sajten genom valet av sessionen
Select Case System.Web.HttpContext.Current.Session("UserCurrentLanguage")
Case 2 : GetLanguage = "en"
Case Else : GetLanguage = "sv"
End Select
End Function
Nu tittar vi på den kompletta koden för GetMessage
Shared Function GetMessage(Byval Key As String) As String
' Hämtar rätt fil för landspecifik data
Dim rm As ResourceManager = ResourceManager.CreateFileBasedResourceManager("Lang_" & Site.Language.GetLanguage, "c:\inetpub\wwwroot\pellesoft\bin", Nothing)
' returnerar datat som finns i lang-xx.resources
GetMessage = rm.GetString(value)
rm = Nothing
Sen är det dags att peka på rätt sattelitfil, därefter fråga efter det data du eftersöker. Som du ser här så har jag skrivit en absolut sökväg. Jag hade stora problem med denna rutinen och har faktiskt inte förstått än om man kan använda en relativ sökväg men de tester jag gjorde så slutade jag i alla fall på detta sätt.
Jag läste även att varje fält kan innehålla både bilder, film, text och annat upp till 2 gb data. Så det är rätt mycket som kan få plats. Du kan exempelvis ha htmlkod och annat för att kanske presentera en hel sida med design i olika språk. Varianterna är med andra ord oändliga.
Jag har dock inte tittat på något om att cacha just dessa assemblies för ökad prestanda. Men jag är övertygad om att man kan göra det för att öka farten ytterligare.
Testa applikationen
Nu är våra sattelitfiler klara. Vi har även byggt en funktion som hämtar ut det värde vi vill ha och nu skall vi avsluta med att använda oss av den nya tekniken. Sagt å gjort så lägger vi till en label på vår aspx sida som vi kallar lblMessage. I vår codebehind fyller vi värdet på denna med vår funktion.
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
lblMessage.Text = Site.Language.GetMessage("message")
End Sub
Som returnerar "Hej" eller "Hello" beroende på vad sessionsobjektet innehåller
Om du nu kör applikationen (F5) så kommer du att först få "hej", du klickar sedan på flaggan för engelska och då skall "hello" uppenbara sig på sidan istället. Hoppas detta har gett dig en liten inblick på hur man kan använda sig av sattelite assemblies för att språkstyra sin applikation.
Om du skall ge dig in på lite mer avancerad hantering så skall du börja titta på det jag nämnde i början, nämligen Culture som hjälper dig hålla reda på alla de språk som du kan välja mellan. Lycka till och kontra gärna med att bygga vidare på denna rutin, ännu hellre - skriv en artikel för ytterligare varianter. Det går att fortsätta att använda dessa ressources och kompilera in det till en dll som man kan använda sig av.
Läste ni ända hit kanske ni orkar gå längst upp och rösta på artikeln också. Det sporrar mig att skriva mer (oavsett om ni röstar positivt eller negativt) samt att jag får en fingervisning på om detta är sån typ av information som ger dig något mervärde eller ej. Det här gäller givetvis alla artiklar som finns här. Då det tar timmar att skriva artikeln kanske ni tar er tiden att rösta.
Här har ni 2 flaggor ni kan använda till er imagebutton:
För att ändra bilden på din imagebutton när du klickar på den kan du använda följande kod:
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
If Session("UserCurrentLanguage") = 2 Then
Imagebutton1.ImageUrl = "/bilder/page/lang_sv.gif"
Else
Imagebutton1.ImageUrl = "/bilder/page/lang_en.gif"
End If
End Sub
Ronny Thörnvall
Nu var det en gammal kommentar ser jag, men jag tänkte att jag skulle svara på den i alla fall. ResGen finns i mappen "C:\Program\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin" om du har gjort en standardinstallation på en dator med svenskt OS. Föreslår att du lägger till den sökvägen i Path så datorn söker efter filer där med. Bra artikel Pelle, även om jag sett flera sätt att lösa detta på, men det är väl som med all programmering - bara välja en av metoderna och köra på!? :-)
Håkan Olsson
Citerar: "Egentligen är detta nog någon form av halvlösning så en revidering i framtiden - eller att någon annan skriver en bättre artikel kommer säkert..." Artikeln är skriven 2003 så nu undrar jag om du hittat något bättre sätt att bygga in språkstöd eller om du tycker detta är ett bra sätt fortfarande? Annars tycker jag artikeln är utmärkt!