KTH NADA Språkteknologi 2D1418 Internationalisering/lokalisering på webben Benny Ferander, 711119-0455 [email protected] Stefan Westlund, 681206-0157 [email protected] Sammanfattning Idag läggs en allt större vikt på internationalisering och lokalisering vid utveckling av programvara. Detsamma gäller för applikationer konstruerade för webben. Det är viktigt att nå en alltmer internationell marknad. Med hjälp av internationalisering och lokalisering skapas ett flexibelt designmönster där komponenter kan adderas utan ingrepp i källkod. Det låter komplicerat men är inte svårt att implementera. Innehåll 1 Syfte 3 2 Metod 3 3 Grundläggande begrepp 3.1 Internationalisering . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Lokalisering . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 4 4 Två olika exempel i Java 4 5 Klassen Locale 5 6 Klassen ResourceBundle 6.1 .properties-filer . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6 7 Internationalisering/Lokalisering på webben 7.1 Webbserver . . . . . . . . . . . . . . . . . . . 7.2 Java Servlets . . . . . . . . . . . . . . . . . . 7.3 PageBeans och JSP . . . . . . . . . . . . . . . 7.4 Möjlig tillämpning . . . . . . . . . . . . . . . 8 8 8 8 9 8 Slutsatser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2 1 Syfte Vi fick i uppdrag att skriva en rapport om internationalisering och lokalisering i kursen Språkteknologi. Syftet med denna rapport är att klargöra vad detta innebär. Vi kommer också att visa hur detta kan användas i en webbapplikation. 2 Metod Vi har läst igenom kursens material angående internationalisering och lokalisering. För att kunna realisera projektet har vi ingående studerat Javas API. Våra egna erfarenheter från webbserverprogrammering har också kommit väl till pass. Vi började med att skriva några enkla program i Java för att påvisa skillnaden mellan en internationaliserad och en icke internationaliserad applikation. Sedan skissade vi på en mer avancerad modell designad för webbändamål. 3 Grundläggande begrepp 3.1 Internationalisering Internationalisering innebär att applikationer designas på ett sådant sätt att de kan anpassas till varierande språk, region och kultur. Detta utan att ändringar i källkod behövs göras. I en internationaliserad applikation är källkod och lokalberoende data separerat. Internationalisering kallas ofta för i18n, på grund av att det på engelska heter internationalization, där det är 18 bokstäver mellan det första i:et och det sista n:et. En internationaliserad applikation har följande egenskaper: • Om lokaliserat data adderas, ska samma applikation kunna köras i hela världen. • Textelement, som statusmeddelanden och komponenter i ett GUI är inte hårdkodade. Istället lagras de utanför källkoden och återfås dynamiskt. • Tillägg av nya språk kräver inte omkompilering. • Kulturberoende data, som datum och valuta, återges på det format som användaren är van vid i sin region och i sitt språk. • Det är lätt att lägga till nya regioner och språk. 3 3.2 Lokalisering Lokalisering innebär att mjukvara anpassas till en specifik region eller ett specifikt språk. Detta görs genom att addera lokalspecifika komponenter, bland annat texter översatta till olika språk. Lokalisering kallas ibland l10n av samma skäl som internationalisering kallas i18n. 4 Två olika exempel i Java Följande kod kan endast presentera utdata på svenska: public class InteInternationaliserat { public static void main(String[] args) { System.out.println("Hej."); System.out.println("Hur mår du?"); System.out.println("Hejdå."); } } Antag att vi nu vill att programmet ska visa olika meddelanden beroende på om det är en engelsman eller en tysk som använder programmet. Meddelandena bör då flyttas ut från källkoden och in i textfiler som översättare kan editera. Programmet behöver internationaliseras. En internationaliserad version av programmet skulle se ut ungefär som följer: import java.util.*; public class Internationaliserat { public static void main(String[] args) { String language; String country; if (args.length != 2){ language = new String("sv"); country = new String("SE"); } else{ language = new String(args[0]); country = new String(args[1]); 4 } Locale currentLocale; ResourceBundle messages; currentLocale = new Locale(language, country); messages = ResourceBundle.getBundle("MessagesBundle", currentLocale); System.out.println(messages.getString("greetings")); System.out.println(messages.getString("inquiry")); System.out.println(messages.getString("farewell")); } } Om programmet skulle köras av exempelvis en engelsman skulle körningen få följande utseende: > java Internationaliserat en UK Hello. How are you? Goodbye. Om en tysk körde programmet skulle körningen se ut så här: > java Internationaliserat de DE Hallo. Wie geht’s? Tschüs. Okej. Nu har vi ett program som är internationaliserat. Det återstår dock att förklara koden ovan. 5 Klassen Locale En instans av klassen Locale representerar en specifik grafisk, politisk eller kulturell region. I Java skapar du en Locale genom att använda en av de två konstruktörerna: Locale(String language, String country) Locale(String language, String country, String variant) Det första argumentet till båda konstruktorerna är språkkoden enligt ISO639. Dessa hittas på webbadressen: http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt 5 Det andra argumentet till de båda konstruktörerna är landskoden enligt ISO-3166. Dessa hittas på webbadressen http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html Den andra konstruktören kräver ytterligare ett argument: variant. Denna tänker vi inte presentera ytterligare utan hänvisar till Javas API. Då man en gång instansierat ett Locale-objekt kan man få information från den. Många av de klasser som används i Java för internationalisering och lokalisering använder sig av Locale. 6 Klassen ResourceBundle En instans av klassen ResourceBundle innehåller lokalspecifika objekt. Om ditt program behöver lokalspecifika objekt, till exempel av typen String, så kan programmet hämta det från en ResourceBundle som passar den tillfällige användarens lokalitet. Detta hjälper dig att skriva program som: • är lätt lokaliserade eller översatta till olika språk • hanterar multipla lokaliteter samtidigt • lätt kan modifieras I det tidigare exemplet använde vi en ResourceBundle: ResourceBundle messages; ... messages = ResourceBundle.getBundle("MessagesBundle", currentLocale); Argumentet MessagesBundle är prefix på en fil med suffixet .properties. Dessa förklaras mer nedan. Det som görs i ovanstående kod är helt enkelt att det skapas en ResourceBundle som arbetar med en fil som har suffixet .properties. Prefix på denna fil bestäms av aktuell locale och namnet MessagesBundle. 6.1 .properties-filer Ovan nämnda .properties-filer behöver förklaras utförligt. Det är i dessa filer de olika textmeddelandena skrivs in. Deras namn ska vara på en viss form: baseclass + "_" + language + "_" + country + "_" + ".properties" baseclass + "_" + language + ".properties" baseclass + ".properties" 6 För att förklara detta lite bättre kan vi tänkas att vi vill kunna hantera två språk i vårt program, till exempel svenska och engelska. Antag vidare att vi vill att svenska ska vara det språk som används som default. “Baseclass” skulle t.ex. kunna vara “textfil”. Då skulle vi ha följande två filer: textfil.properties textfil_en_UK.properties Om användaren nu anger att han är engelsman kan han få text presenterad från filen textfil_en_UK.properties. Om inget anges hämtas text från filen textfil.properties. I vår exempelkod har vi följande rader av kod: System.out.println(messages.getString("greetings")); System.out.println(messages.getString("inquiry")); System.out.println(messages.getString("farewell")); Det som händer här är att programmet först hämtar en textsträng från vald propertyfil genom att ange nyckeln greetings och sedan skriver ut den hämtade textsträngen på standard output. Sedan görs samma sak för de andra nycklarna. I vårt exempel ville vi att en engelsman, en tysk och en svensk skulle kunna använda programmet på sitt eget språk. Om vi låter svenska vara default behövs följande filer: MessagesBundle.properties MessagesBundle_en_UK.properties MessagesBundle_de_DE.properties Filen MessagesBundle.properties skulle se ut så här: greetings = Hej inquiry = Hur mår du? farewell = Hejdå. Filen MessagesBundle_en_UK.properties skulle se ut så här: greetings = Hello inquiry = How are you? farewell = Goodbye. och filen MessagesBundle_de_DE.properties skulle se ut så här greetings = Hallo inquiry = Wie geht’s? farewell = Tschüs. 7 7 Internationalisering/Lokalisering på webben Nu har vi visat grunderna i hur applikationer kan internationaliseras. En bra tillämpning för detta är webben. Det är lätt att förstå att till exempel en webbplats som syftar till att sälja en produkt på en internationell marknad har ett starkt behov av internationalisering. 7.1 Webbserver En bra lösning då man jobbar med Java och webbapplikationer är att använda sig av den så kallade MVC-modellen1 . Med hjälp av en webbserver som hanterar Java kan man bland annat använda sig av en kombination av JSP2 och Java Servlets. Tomcat är en populär webbserver som uppfyller dessa krav. Den kan hämtas från följande URL: http://jakarta.apache.org/site/sourceindex.html 7.2 Java Servlets En Java Servlet är en server-side-komponent skriven i Java och är tillhandahållen av en webbserver. En servlet instansieras av ett anrop från en browser. Denna servlet sköter logiken, och instansierar i sin tur en s.k. PageBean, vilken utgör modellen i systemet. 7.3 PageBeans och JSP PageBeans är enkla javaklasser som endast bör ha metoder av typen set och get. Dessa instansieras av till exempel en servlet, som skickar med bönan i anropet till JSP-sidan. Bönan innehåller information från exempelvis en databas. Viktigt att poängtera är att bönorna inte ska kunna kasta Exceptions eftersom hantering av detta skulle kräva Javakod i JSP-sidan. Så skulle vara fallet om vi skickade med hela ResourceBundle-objektet i anropet istället för denna PageBean. Detta eftersom ResourceBundle kastar ett otal Exceptions som måste hanteras på något sätt. JSP är en sorts utökning av HTML, där det går att inkludera Java. Men man bör undvika att skriva Javakod direkt i en JSP-sida. Tanken med separeration mellan JSP och Java Servlets är att Java- och HTML-utvecklare ska kunna jobba parallellt med olika uppdrag inom samma projekt. En av de grundläggande orsakerna är att det inte går att använda sig av Javadoc3 i JSP. 1 Designmönstret Model-View-Controller JavaServer Pages 3 Javas standardiserade dokumentationsverktyg 2 8 I JSP-sidan går det att addera egna taggar, vilket till exempel möjliggör iteration genom en objektvektor. Bönans get-metoder används av JSP-sidan till att visa specifik information. JSP-sidan kompileras av webbservern till en servlet. Detta är dock ingenting som utvecklaren behöver tänka på. 7.4 Möjlig tillämpning Då en användare ansluter till systemet finns tre möjligheter till lokalisering. Det ena är att användaren varje gång väljer språk genom att till exempel klicka på en flagga. Den andra möjligheten är att uppgifter om språkval lagras i användarens dator i form av en cookie4 . Den tredje möjligheten är att uppgifter om användarens språk sparas i en databas och hämtas vid inloggningen. Att välja språk varje gång är den enklaste lösningen, men kan vara enerverande för användaren om han frekvent återkommer till sidan. Att använda cookies är bra så länge användarens browser accepterar dem. Men cookies har nackdelen att de lagras lokalt, vilket inte fungerar om användaren byter dator. Den lösning som förefaller mest professionell är att uppgifterna lagras i en databas kopplad mot webbservern. Då spelar det ingen roll om användaren har bytt dator. Dessutom kan han ändra inställningar i efterhand om utvecklaren implementerar detta. En användarprofil är skapad. Till användarnamnet hör nu lokalisering. Så här designar vi modellen; Ett anrop till en webbserver passerar en kontroller, vilken skickar anropet till rätt Java Servlet. Servleten tar hand om anropet och exekverar nödvändig kod utifrån information i anropets header. Denna kod skulle till exempel kunna genomföra en säkerhetskontroll och helt sonika vägra utföra anrop från en icke inloggad användare. Logiken instansierar en eller flera PageBeans som skickas med till JSP-sidan. En av dessa PageBeans skulle kunna innehålla språkinformationen. 4 En cookie är en beständig informationsteckensträng som browsern skickar med vid anropet 9 Vår JSP-sida använder sig av dessa PageBeans. Språkinformationen liksom användarinformationen i bönorna används i sidan med hjälp av getmetoderna. Hela webbapplikationen har nu blivit internationaliserad. 10 8 Slutsatser Användningen av internationalisering och lokalisering kommer att öka markant. Detta grundar vi på att elektronisk handel ökat på Internet. Dessutom har marknaden blivit alltmer internationell. Det finns mycket pengar att tjäna genom internationalisering och lokalisering av webbapplikationer. 11 Referenser [1] The Java Tutorial http://java.sun.com/docs/books/tutorial/i18n/index.html [2] Allaramaju, Subrahmanyam Professional Java Server Programming J2EE: 1.3 Edition 12