{"id":410,"date":"2011-11-03T14:52:08","date_gmt":"2011-11-03T12:52:08","guid":{"rendered":"http:\/\/www.kristiansborg.dk\/bibliotek\/?page_id=410"},"modified":"2011-11-03T14:53:10","modified_gmt":"2011-11-03T12:53:10","slug":"kapitel-8-internationale-programmer","status":"publish","type":"page","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/","title":{"rendered":"Kapitel 8 Internationale programmer"},"content":{"rendered":"<p>En af Javas store fordele er, at de kompilerede filer er platformsuafh\u00e6ngige. Det ville v\u00e6re rart, hvis de ogs\u00e5 var sproguafh\u00e6ngige \u2013 og her t\u00e6nkes ikke p\u00e5 programmeringssprog, men p\u00e5 de sprog som brugerne taler.<\/p>\n<div style=\"border: 1px solid red; color: red\">\n<b>Du l\u00e6ser en gammel bog<\/b><br \/>\nDen bog, du l\u00e6ser her, er fra 1998, og mange ting kan have \u00e6ndret sig siden da.<br \/>\nVi h\u00e5ber, at du stadig kan finde relevant information i den.<br \/>\nHvis du vil l\u00e6se aktuelle oplysninger om de avancerede dele af Java, anbefaler vi<br \/>\nbogen <a href=\"http:\/\/clk.tradedoubler.com\/click?p(197229)a(2029446)g(19172914)url(http:\/\/www.adlibris.com\/dk\/product.aspx?isbn=0132354799)\"  target=\"_blank\">Core Java &#8211; Advanced Features<\/a><img decoding=\"async\" src=\"http:\/\/impdk.tradedoubler.com\/imp?type(inv)g(19172914)a(2029446)\" \/>\n<\/div>\n<p>Der er mange grunde til at \u00f8nske sproguafh\u00e6ngighed. For eksempel er det globale marked et s\u00e6rdeles stort marked med mange potentielle kunder. For at opn\u00e5 succes p\u00e5 det globale marked er det n\u00f8dvendigt, at ens produkt kan tilpasses de lokale forhold. Eksempelvis foretr\u00e6kker danskerne at se datoer som dd\/mm-\u00e5\u00e5 og se forkortelsen kr. foran bel\u00f8b, mens en amerikaner vil foretr\u00e6kke, at datoer pr\u00e6senteres som mm\/dd\/\u00e5\u00e5, og at bel\u00f8b har et dollar-tegn foran.<\/p>\n<p>&nbsp;<\/p>\n<p>Internationale produkter kan naturligvis opn\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\u00e5 kan man lade hver version af programmet underst\u00f8tte et specielt sprog. Dette kr\u00e6ver en rekompilering af applikationen, hver gang man vil underst\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \u00e6ndring eller en opdatering af programmet, skal den samme \u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres.<\/p>\n<p>&nbsp;<\/p>\n<p>Der er to processer, der skal gennemf\u00f8res, for at et program succesfuldt kan overf\u00f8res fra et omr\u00e5de til et andet:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>Internationalization<\/li>\n<li>Localization<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Internationalization er den proces, hvor man tager et program og g\u00f8r det nemt at flytte programmet fra et sprogm\u00e6ssigt og geografisk omr\u00e5de til et andet.<\/p>\n<p>&nbsp;<\/p>\n<p>Efter et program har gennemg\u00e5et internationalization-processen kan det blive localized. Det vil sige, at man foretager de \u00e6ndringer, der tilpasser produktet til en specifik m\u00e5lgruppe.<\/p>\n<p>&nbsp;<\/p>\n<p>Dette kapitel vil beskrive s\u00e5vel internationalization- som localizationprocessen.<\/p>\n<p>&nbsp;<\/p>\n<h1>Internationalization<\/h1>\n<p>&nbsp;<\/p>\n<p>Et program, der er blevet internationalized, har f\u00f8lgende kendetegn:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>Ved kun at tilf\u00f8je localization-data, kan det samme program k\u00f8res hvor som helst.<\/li>\n<li><\/li>\n<li>Den tekst, der vises p\u00e5 brugergr\u00e6nsefladen, vises i brugerens sprog.<\/li>\n<li>Tekstelementer \u2013 for eksempel labels p\u00e5 brugergr\u00e6nsefladen \u2013 er ikke kodet direkte ind i programmet. I stedet er de gemt udenfor kildeteksten.<\/li>\n<li>Underst\u00f8ttelse af nye sprog medf\u00f8rer ikke et behov for rekompilering af hele applikationen.<\/li>\n<li>Datoer, bel\u00f8b og lignede pr\u00e6senteres i et format, der passer til brugerens \u00f8nske.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>For at skrive et program, der opfylder disse krav, kan man med fordel bruge Javas Internationalization API. Dette API giver mulighed for at anvende klasser til at gemme og indl\u00e6se sprogafh\u00e6ngige objekter og stiller metoder til r\u00e5dighed til formatering af beskeder, datoer, tidspunkter og tal. Det stiller ogs\u00e5 services til r\u00e5dighed, s\u00e5 man kan sammenligne tekst og foretage s\u00f8gninger. Endeligt g\u00f8r API\u2019et det muligt at vise, indl\u00e6se og arbejde med Unicode-tegn.<\/p>\n<p>&nbsp;<\/p>\n<h1>Lokale indstillinger<\/h1>\n<p>&nbsp;<\/p>\n<p>En central del af Javas Internationalization API er java.util.Locale-klassen. Denne klasse indeholder ikke bare en r\u00e6kke konstanter, der g\u00f8r det muligt at angive sprog og lande, men ogs\u00e5 metoder til angivelse af det nuv\u00e6rende land og sprogomr\u00e5de.<\/p>\n<p>&nbsp;<\/p>\n<p>I Java-terminologi kaldes operationer, der skal tilpasses fra omr\u00e5de til omr\u00e5de, for lokalafh\u00e6ngige. At vise en dato er s\u00e5ledes en lokalafh\u00e6ngig operation, idet det g\u00f8res forskelligt alt efter, hvilket omr\u00e5de programmet afvikles i.<\/p>\n<p>&nbsp;<\/p>\n<p>For at programmet kan tilpasse de lokalafh\u00e6ngige operationer korrekt, er det n\u00f8dt til at vide, hvilket omr\u00e5de det afvikles i. Det nytter jo ikke meget, at man er n\u00f8dt til at inkludere denne information i kildeteksten \u2013 s\u00e5 vil det alligevel kr\u00e6ve en rekompilering af flytte produktet fra et omr\u00e5de til et andet. En m\u00e5de at finde ud af, hvordan brugeren foretr\u00e6kker sin informationer vist, er ved at sp\u00f8rge. Under installationen eller f\u00f8rste gang programmet startes, kan brugeren blive m\u00f8dt med en r\u00e6kke sp\u00f8rgsm\u00e5l, der skal bruges til at definere formateringen af programmets beskeder. For at brugeren ikke skal v\u00e6re n\u00f8dt til at komme med de samme svar p\u00e5 de samme sp\u00f8rgsm\u00e5l, hver gang et nyt program tages i brug, opbevarer de fleste operativsystemer denne information. I Windows 95 kan man \u00e6ndre denne information i Kontrolpanelet.<\/p>\n<p>&nbsp;<\/p>\n<p>For at opretholde Javas platformsuafh\u00e6ngighed kan man ikke bare bruge de metoder, Windows 95 stiller til r\u00e5dighed til at hente Kontrolpanelets information. I stedet skal man bruge nogle af de metoder, Locale stiller til r\u00e5dighed. Det er herefter op til den virtuelle Java-maskine at foretage de platformsafh\u00e6ngige kald, der henter informationerne. Locale-klassen er defineret s\u00e5ledes:<\/p>\n<p>&nbsp;<\/p>\n<p>public class Locale extends Object<\/p>\n<p>{<\/p>\n<p>public static java.util.Locale[]getAvailableLocales ();<\/p>\n<p>public static java.util.Locale getDefault ();<\/p>\n<p>public static java.lang.String[] getISOCountries ();<\/p>\n<p>public static java.lang.String[] getISOLanguages ();<\/p>\n<p>public static synchronized void setDefault (java.util.Locale);<\/p>\n<p>&nbsp;<\/p>\n<p>public java.lang.String getCountry ();<\/p>\n<p>public final java.lang.String getDisplayCountry ();<\/p>\n<p>public java.lang.String getDisplayCountry (java.util.Locale);<\/p>\n<p>public final java.lang.String getDisplayLanguage ();<\/p>\n<p>public java.lang.String getDisplayLanguage (java.util.Locale);<\/p>\n<p>public final java.lang.String getDisplayName ();<\/p>\n<p>public java.lang.String getDisplayName (java.util.Locale);<\/p>\n<p>public final java.lang.String getDisplayVariant ();<\/p>\n<p>public java.lang.String getDisplayVariant (java.util.Locale);<\/p>\n<p>public java.lang.String getISO3Country () throws\u00a0\u00a0 java.util.MissingResourceException;<\/p>\n<p>public java.lang.String getISO3Language () throws java.util.MissingResourceException;<\/p>\n<p>public java.lang.String getLanguage ();<\/p>\n<p>public java.lang.String getVariant ();<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Hvis man vil hente de lokale indstillinger, kan man g\u00f8re det ved hj\u00e6lp af nedenst\u00e5ende kode:<\/p>\n<p>&nbsp;<\/p>\n<p>Locale indstillinger;<\/p>\n<p>indstillinger = Locale.getDefault();<\/p>\n<p>&nbsp;<\/p>\n<p>Det er ogs\u00e5 muligt at oprette et Locale-objekt, der er tilpasset et bestemt omr\u00e5de. Dette kan g\u00f8res ved at angive en sprogkode og landekode i Locale\u2019s constructor. I appendiks A findes en oversigt over de forskellige landekoder i henhold til ISO-standarden. Som det fremg\u00e5r af denne tabel har Danmark landekoden dk. Det betyder, at man kan oprette et Locale-objekt, der repr\u00e6senterer dansk og Danmark, ved at skrive:<\/p>\n<p>&nbsp;<\/p>\n<p>Locale indstillinger;<\/p>\n<p>indstillinger = new Locale (&#8220;da&#8221;, &#8220;DK&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>\u201dda\u201d angiver sproget, mens det andet parameter angiver landet. Grunden, til at der b\u00e5de skal angives sprog og land, er, at det ikke er alle lande, der har et f\u00e6lles sprog. For eksempel har Canada b\u00e5de en engelsksproget og fransksproget del. Hvis man vil oprette et Locale-objekt, der repr\u00e6senterer den fransksprogede del af Canada, kan det g\u00f8res med nedenst\u00e5ende kode:<\/p>\n<p>&nbsp;<\/p>\n<p>Locale indstillinger;<\/p>\n<p>indstillinger = new Locale (&#8220;fr&#8221;, &#8220;CA&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<h1>Brugergr\u00e6nsefladen<\/h1>\n<p>&nbsp;<\/p>\n<p>Det f\u00f8rste skridt mod at internationalisere sine programmer er at isolere de dele af Java-programmet, der er lokalafh\u00e6ngige. Dette vil typisk is\u00e6r v\u00e6re brugergr\u00e6nsefladen: tekster, menupunkter, genvejstaster, beskeder og s\u00e5<\/p>\n<p>&nbsp;<\/p>\n<p>videre. Det kan ogs\u00e5 dreje sig om billeder, der skal \u00e6ndres, enten fordi de indeholder tekst, der skal overs\u00e6ttes, eller fordi de kan v\u00e6re upassende eller uforst\u00e5elige i andre omr\u00e5der og kulturer. For eksempel vil en svensker nok have sv\u00e6rt ved at se det smarte i, at f\u00f8dselsdage i et kalenderprogram markeres med Dannebrog.<\/p>\n<p>&nbsp;<\/p>\n<p>Javas internationalization API indeholder en klasse, der g\u00f8r det nemt at organisere og indl\u00e6se lokalafh\u00e6ngig informationer som tekststrenge eller andre ressourcer. Denne klasse hedder ResourceBundle. Klassen er abstrakt, og der findes to klasser i API\u2019et, som nedarver fra den. Det er klasserne PropertyResourceBundle\u00a0og ListResourceBundle\u00a0\u2013 mere om dem senere.<\/p>\n<p>&nbsp;<\/p>\n<p>Man kan bruge s\u00e5 mange ResourceBundle-objekter man vil. Man kan for eksempel opdele teksterne i labels, knapper og beskeder. Hvert sprog skal herudover have sin egen ResourceBundle. Der er en t\u00e6t sammenh\u00e6ng mellem Locale-objekter og ResourceBundle-objekter. S\u00e5ledes skal man bruge et Locale-objekt for at hente en ResourceBundle. Derudover f\u00e5r hver ResourceBundle et navn, der indeholder en sprog- og landekode. Hvis man for eksempel har alle sine tekster til at ligge i en ResourceBundle, der hedder Tekster, kan de forskellige udgaver f\u00e5 f\u00f8lgende navne:<\/p>\n<p>&nbsp;<\/p>\n<p>Tekster<\/p>\n<p>Tekster_dk_DK<\/p>\n<p>Tekster_fr_CA<\/p>\n<p>&nbsp;<\/p>\n<p>Den f\u00f8rste ResourceBundle indeholder de tekster, der skal bruges, hvis der ikke kan findes tekster, der er tilpasset det p\u00e5g\u00e6ldende sprogomr\u00e5de. Dern\u00e6st findes en ResourceBundle indeholdende danske tekster til brug i Danmark, og derefter franske tekster til brug i Canada.<\/p>\n<p>&nbsp;<\/p>\n<p>Man henter den rette ResourceBundle ved at anvende den statiske metode getBundle, der findes i ResourceBundle-klassen:<\/p>\n<p>&nbsp;<\/p>\n<p>Locale indstillinger = new Locale (&#8220;da&#8221;, &#8220;DK&#8221;);<\/p>\n<p>ResourceBundle tekster = ResourceBundle.getBundle (&#8220;Tekster&#8221;, indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>Hvis der ikke findes en ResourceBundle, der passer pr\u00e6cis til sprogindstillingerne, vil der blive s\u00f8gt efter den ResourceBundle, der bedst opfylder indstillingerne. I dette tilf\u00e6lde vil s\u00f8ger\u00e6kkef\u00f8lgen se s\u00e5ledes ud:<\/p>\n<p>&nbsp;<\/p>\n<p>Tekster_da_DK<\/p>\n<p>Tekster_da<\/p>\n<p>Tekster<\/p>\n<p>&nbsp;<\/p>\n<p>Hvis getBundle ikke kan finde en ResourceBundle, der svarer til de \u00f8nskede indstillinger, opst\u00e5r en MissingResourceException. Dette kan kun ske, hvis der ikke defineres en ResourceBundle uden indstillinger \u2013 der vil s\u00e5ledes ikke opst\u00e5 nogen exception i dette tilf\u00e6lde, da s\u00f8gningen altid vil resultere i, at klassen Tekster bliver fundet.<\/p>\n<p>&nbsp;<\/p>\n<p>Som n\u00e6vnt findes der to subklasser af ResourceBundle. PropertyResourceBundle\u00a0er underst\u00f8ttet af en eller flere property-filer. Disse er almindelige tekstfiler og indeholder ikke Java-kode. Det vil sige, at de kan opdateres af en overs\u00e6tter eller indtaster uden teknisk erfaring. Der er dog<\/p>\n<p>&nbsp;<\/p>\n<p>den begr\u00e6nsning, at property-filer kun kan indeholde informationer om String-objekter. Har man brug for at opbevare mere komplekse ressourcer og objekter, skal man i stedet anvende ListResourceBundle.<\/p>\n<p>&nbsp;<\/p>\n<h1>PropertyResourceBundle<\/h1>\n<p>&nbsp;<\/p>\n<p>For at kunne bruge PropertyResourceBundle skal man som n\u00e6vnt oprette en property-fil. Denne fil skal have et brugervalgt navn efterfulgt af den sprog- og landekode, der svarer til indholdet af filen. Filen skal have typen .properties. I property-filer bruges gitter-tegnet (#) til at angive kommentarer. Bortset fra det svarer opbygningen af filerne til opbygningen af de ini-filer, man kender fra Windows. Dog er property-filer ikke inddelt i sektioner. Den generelle opbygning af en linie i en property-fil ser s\u00e5ledes ud:<\/p>\n<p>&nbsp;<\/p>\n<p><em>navn<\/em> = <em>v\u00e6rdi<\/em><\/p>\n<p><em> <\/em><\/p>\n<p>Nedenst\u00e5ende er et eksempel p\u00e5 en property-fil:<\/p>\n<p>&nbsp;<\/p>\n<p>#Denne fil indeholder de tekster, der bruges i brugergr\u00e6nsefladen<\/p>\n<p>okKnap = OK<\/p>\n<p>annullerKnap = Annull\u00e9r<\/p>\n<p>LukKnap = Luk<\/p>\n<p>&nbsp;<\/p>\n<p>Denne fil kan for eksempel kaldes Tekster_da_DK.properties. Hvis der skulle findes en tilsvarende fil til det engelske sprog, kunne den kaldes Tekster_en.properties for at angive, at den kan bruges i alle engelsktalende lande. Denne fil kunne se s\u00e5ledes ud:<\/p>\n<p>&nbsp;<\/p>\n<p>#This file contains the text used in the user interface<\/p>\n<p>okKnap = OK<\/p>\n<p>annullerKnap = Cancel<\/p>\n<p>LukKnap = Close<\/p>\n<p>&nbsp;<\/p>\n<p>Som det ses, er det kun v\u00e6rdierne, der \u00e6ndres \u2013 ikke navnene. Hvilke navne man v\u00e6lger er op til programm\u00f8ren, men n\u00e5r man \u00e9n gang har lagt sig fast p\u00e5 et navn, b\u00f8r man ikke \u00e6ndre det, da det skal bruges i programmets kildetekst.<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e5r property-filerne er genereret er teksterne klar til brug i programmet. Teksterne hentes p\u00e5 samme m\u00e5de, hvadenten der er tale om en PropertyResourceBundle eller en ListResourceBundle.<\/p>\n<p>&nbsp;<\/p>\n<h1>ListResourceBundle<\/h1>\n<p>&nbsp;<\/p>\n<p>Hvor PropertyResourceBundle\u00a0blev repr\u00e6senteret af en property-fil, bliver ListResourceBundle repr\u00e6senteret af en rigtig Java-klasse. Den f\u00f8rste opgave, n\u00e5r der bruges ListResourceBundle, er s\u00e5ledes at oprette en klasse for hvert omr\u00e5de og sprog. Klasserne skal navngives efter samme system som property-filerne \u2013 dog har de filtypen .class i stedet for .properties. Derudover er det et krav, at klasserne skal nedarve fra klassen ListResourceBundle, s\u00e5 de kan behandles abstrakt. Nedenst\u00e5ende er et eksempel p\u00e5 en<\/p>\n<p>&nbsp;<\/p>\n<p>dansk udgave af en ListResourceBundle.<\/p>\n<p>&nbsp;<\/p>\n<p>import java.util.ListResourceBundle;<\/p>\n<p>&nbsp;<\/p>\n<p>public class ListTekster_dk_DK extends ListResourceBundle<\/p>\n<p>{<\/p>\n<p>private Object[][] contents =<\/p>\n<p>{<\/p>\n<p>{&#8220;Areal&#8221;, new Integer (44413)},<\/p>\n<p>{&#8220;Indbyggere&#8221;, new Integer (5100000)}<\/p>\n<p>};<\/p>\n<p>&nbsp;<\/p>\n<p>public Object[][] getContents()<\/p>\n<p>{<\/p>\n<p>return contents;<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Den tilsvarende engelske klasse kunne se s\u00e5ledes ud:<\/p>\n<p>&nbsp;<\/p>\n<p>import java.util.ListResourceBundle;<\/p>\n<p>&nbsp;<\/p>\n<p>public class ListTekster_en_UK extends ListResourceBundle<\/p>\n<p>{<\/p>\n<p>private Object[][] contents =<\/p>\n<p>{<\/p>\n<p>{&#8220;Areal&#8221;, new Integer (245000)},<\/p>\n<p>{&#8220;Indbyggere&#8221;, new Integer (52500000)}<\/p>\n<p>};<\/p>\n<p>&nbsp;<\/p>\n<p>public Object[][] getContents()<\/p>\n<p>{<\/p>\n<p>return contents;<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Ligesom ved PropertyResourceBundle g\u00e6lder det, at de navne, der bruges til at genkende teksten (Areal og Indbyggere), m\u00e5 v\u00e6lges af programm\u00f8ren og ikke skal \u00e6ndres under overs\u00e6ttelsen.<\/p>\n<p>&nbsp;<\/p>\n<p>Fordelen ved en ListResourceBundle er, at den kan repr\u00e6sentere alle former for data. Ulempen er, at klassen skal kompileres, f\u00f8r applikationen underst\u00f8tter det p\u00e5g\u00e6ldende sprog. Derudover er det lettere for en overs\u00e6tter eller indtaster uden teknisk erfaring at lave en fejl, der g\u00f8r, at klassen ikke kan kompileres.<\/p>\n<p>&nbsp;<\/p>\n<h1>Brug af ResourceBundle<\/h1>\n<p>&nbsp;<\/p>\n<p>N\u00e5r man har defineret sin ResourceBundle \u2013 enten ved hj\u00e6lp af en PropertyResourceBundle eller en ListResourceBundle \u2013 kan man bruge den i sit program. Nedenst\u00e5ende eksempel viser, hvordan det kan g\u00f8res.<\/p>\n<p>&nbsp;<\/p>\n<p>import java.util.*;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>public class InternationalizedClass<\/p>\n<p>{<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>&nbsp;<\/p>\n<p>ResourceBundle tekster = ResourceBundle.getBundle (&#8220;Tekster&#8221;, indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>String okKnap = tekster.getString(&#8220;okKnap&#8221;);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Det f\u00f8rste, der sker i main-metoden, er, at de lokale indstillinger hentes. Det vil sige, at man sp\u00f8rger operativsystemet, hvilket sprog brugeren taler, og hvilket land computeren befinder sig i. P\u00e5 baggrund af dette, finder man en ResourceBundle, der svarer til disse indstillinger. I dette tilf\u00e6lde er det en PropertyResourceBundle ved navn Tekster, men det kunne lige s\u00e5 godt have v\u00e6ret en ListResourceBundle \u2013 fremgangsm\u00e5den er den samme. Hvis der b\u00e5de findes en class-fil og en property-fil, der passer til beskrivelsen, vil class-filen blive brugt.<\/p>\n<p>&nbsp;<\/p>\n<p>Som bekendt kan en PropertyResourceBundle kun indeholde strenge. Derfor er det naturligvis ogs\u00e5 getString, der bruges til at angive, hvilken v\u00e6rdi der skal hentes. Har man behov for at hente oplysninger i andre formater, kan man g\u00f8re det ved hj\u00e6lp af getObject-metoden.<\/p>\n<p><script type=\"text\/javascript\"><!--\ngoogle_ad_client = \"ca-pub-3400894606969585\";\n\/* Bibliotek - ajp *\/\ngoogle_ad_slot = \"3560879290\";\ngoogle_ad_width = 336;\ngoogle_ad_height = 280;\n\/\/-->\n<\/script><br \/>\n<script type=\"text\/javascript\"\nsrc=\"http:\/\/pagead2.googlesyndication.com\/pagead\/show_ads.js\">\n<\/script><br \/>\n&nbsp;<\/p>\n<h1>Formatering af tal og bel\u00f8b<\/h1>\n<p>&nbsp;<\/p>\n<p>Man skal imidlertid ikke kun v\u00e6re opm\u00e6rksom p\u00e5 overs\u00e6ttelse af tekster, n\u00e5r man skriver et internationalt produkt. Man skal ogs\u00e5 s\u00f8rge for, at tal bliver pr\u00e6senteret rigtigt. For eksempel bruger danskere komma som decimaladskiller og punktum som tusindadskiller, mens engl\u00e6ndere og amerikanere g\u00f8r det pr\u00e6cis modsatte.<\/p>\n<p>&nbsp;<\/p>\n<p>Formatering af tal kan udf\u00f8res ved hj\u00e6lp af klassen NumberFormat. Desv\u00e6rre underst\u00f8tter denne klasse ikke alle verdens lokationer, og der er s\u00e5ledes ingen garanti for, at den underst\u00f8tter det omr\u00e5de, man har brug for. Man kan f\u00e5 en oversigt over de underst\u00f8ttede omr\u00e5der, ved at kalde metoden NumberFormat.getAvailableLocales(), der returnerer et array af Locale-objekter.<\/p>\n<p>&nbsp;<\/p>\n<p>Hvis man skal have formateret et tal, sker det gennem NumberFormat\u2019s format-metode. Nedenst\u00e5ende eksempel viser fremgangsm\u00e5den.<\/p>\n<p>&nbsp;<\/p>\n<p>import java.util.*;<\/p>\n<p>import java.text.*;<\/p>\n<p>&nbsp;<\/p>\n<p>public class FormatDouble<\/p>\n<p>{<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>double tal = 3234.1238;<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>&nbsp;<\/p>\n<p>NumberFormat formatter = NumberFormat.getNumberInstance(indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (formatter.format(tal));<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Udskriften fra eksemplet vil blive<\/p>\n<p>&nbsp;<\/p>\n<p>3.234,124<\/p>\n<p>&nbsp;<\/p>\n<p>Ovenst\u00e5ende eksempel viser, hvordan en double formateres, men fremgangsm\u00e5den er den samme for alle Javas primitive typer. NumberFormat kan ogs\u00e5 formatere tal, der er repr\u00e6senteret i en wrapper-klasse.<\/p>\n<p>&nbsp;<\/p>\n<p>NumberFormat kan imidlertid andet og mere end bare at formatere tal med tusind- og decimaladskiller. Klassen kan ogs\u00e5 bruges til at formatere bel\u00f8b. I s\u00e5 fald skal man blot bruge en CurrencyInstance\u00a0i stedet for en NumberInstance. Nedenst\u00e5ende eksempel viser, hvordan et bel\u00f8b kan bliver formateret.<\/p>\n<p>&nbsp;<\/p>\n<p>import java.text.*;<\/p>\n<p>import java.util.*;<\/p>\n<p>&nbsp;<\/p>\n<p>public class FormatCurrency<\/p>\n<p>{<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>double tal = 1753.75;<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>NumberFormat formatter = NumberFormat.getCurrencyInstance (indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (formatter.format (tal));<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Udskriften af dette eksempel er<\/p>\n<p>&nbsp;<\/p>\n<p>kr 1.753,53<\/p>\n<p>&nbsp;<\/p>\n<p>Den sidste mulighed, NumberFormat stiller til r\u00e5dighed, er formatering af procentv\u00e6rdier. Det vil sige, at man tager et decimaltal og konverterer det til en procentsats. Nedenst\u00e5ende eksempel viser, hvordan det kan g\u00f8res.<\/p>\n<p>&nbsp;<\/p>\n<p>import java.text.*;<\/p>\n<p>import java.util.*;<\/p>\n<p>&nbsp;<\/p>\n<p>public class FormatPercent<\/p>\n<p>{<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>double tal = 0.753;<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>NumberFormat formatter = NumberFormat.getPercentInstance();<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (formatter.format(tal));<\/p>\n<p>&nbsp;<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Dette eksempel giver udskriften<\/p>\n<p>&nbsp;<\/p>\n<p>75%<\/p>\n<p>&nbsp;<\/p>\n<p>Som n\u00e6vnt underst\u00f8tter NumberFormat-klassen desv\u00e6rre ikke alle omr\u00e5der og sprog, og der kan v\u00e6re situationer, hvor man af den ene eller den anden grund har behov for at formatere et bel\u00f8b p\u00e5 en bestemt m\u00e5de. Dette kan man g\u00f8re ved hj\u00e6lp af det, der i Java kaldes m\u00f8nstre. Et m\u00f8nster angiver, hvor der skal s\u00e6ttes gruppeadskiller (tusindadskiller), hvor mange decimaler bel\u00f8bet skal have, og om der skal s\u00e6ttes tegn foran eller bagved. For at kunne bruge m\u00f8nstre til at formatere tal skal man bruge klasserne DecimalFormat\u00a0og DecimalFormatSymbols. I f\u00f8rste omgang er kun DecimalFormat n\u00f8dvendig. Kaldet til dennes constructor inkluderer en tekststreng, der indeholder det m\u00f8nster, der skal formateres efter. Nedenst\u00e5ende eksempel viser, hvordan man nemt kan formatere med DecimalFormat. Hvordan m\u00f8nstrene designes vil blive gennemg\u00e5et senere.<\/p>\n<p>&nbsp;<\/p>\n<p>import java.util.*;<\/p>\n<p>import java.text.*;<\/p>\n<p>&nbsp;<\/p>\n<p>public class FormatUserDefined<\/p>\n<p>{<\/p>\n<p>public static final void main (String arsg[])<\/p>\n<p>{<\/p>\n<p>double tal = 12375.714;<\/p>\n<p>String pattern = &#8220;###,###.##&#8221;;<\/p>\n<p>DecimalFormat formatter = new DecimalFormat (pattern);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (formatter.format(tal));<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Eksemplet giver f\u00f8lgende udskrift<\/p>\n<p>&nbsp;<\/p>\n<p>12.375,71<\/p>\n<p>&nbsp;<\/p>\n<p>Umiddelbart kan det se s\u00e6rt ud, at et komma i m\u00f8nstret erstattes med et punktum i udskriften, ligesom punktummet i m\u00f8nstret erstattes med et komma. Det skyldes, at et punktum i m\u00f8nstret simpelthen bare betyder, at der her skal inds\u00e6ttes den decimaladskiller, der bruges i det aktuelle omr\u00e5de. De generelle regler for design af m\u00f8nstre er som f\u00f8lger:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>Gitterl\u00e5ge (#) bruges til at repr\u00e6sentere et hvilket som helst ciffer. Hvis der er flere repr\u00e6sentationer af #, end der er cifre i tallet, ses der bort fra de overskydende gitterl\u00e5ger. Hvis der er flere cifre i tallet, end der er repr\u00e6sentationer af # i m\u00f8nstret p\u00e5 venstre side af decimaltegnet, bliver alle cifre vist alligevel. Hvis der er for f\u00e5 gitterl\u00e5ger p\u00e5 h\u00f8jre side af decimaltegnet, vil der blive foretaget afrundning.<\/li>\n<li>Nul (0) bruges til at repr\u00e6sentere et hvilket som helst ciffer. De samme regler g\u00e6lder som ved #, dog med den undtagelse, at hvis der er flere nuller, end der er cifre i tallet, vil der blive brugt enten foranstillede eller bagvedstillede nuller for at give tallet den samme l\u00e6ngde som m\u00f8nstret.<\/li>\n<li><\/li>\n<li>Komma (,) angiver, at der p\u00e5 denne plads skal inds\u00e6ttes en gruppeadskiller (tusindadskiller).<\/li>\n<li>Punktum (.) angiver, at der p\u00e5 denne plads skal inds\u00e6ttes decimaladskiller.<\/li>\n<li>E deler mantisse og eksponent.<\/li>\n<li>Semikolon (;) bruges til at adskille forskellige formater i det samme m\u00f8nster.<\/li>\n<li>Minus (-) angiver, at der normalt skal bruges negativt fortegn.<\/li>\n<li>Procent (%) angiver, at tallet skal ganges med 100 og vises som procent.<\/li>\n<li>Sp\u00f8rgsm\u00e5lstegn (?) angiver, at tallet skal ganges med 1000 og vises som promille.<\/li>\n<li>Valutategn (\u00a4) bruges til at angive, at m\u00f8ntfoden skal inds\u00e6ttes p\u00e5 det sted.<\/li>\n<li>Dobbelt-valutategn (\u00a4\u00a4) angiver, at der i stedet for den g\u00e6ngse m\u00f8ntforkortelse eller m\u00f8nttegn skal inds\u00e6ttes den internationale m\u00f8ntkode for valutaen.<\/li>\n<li>Alle andre tegn bliver indsat som de er.<\/li>\n<li>Apostrof (\u2019) kan bruges til at omkranse tegn, der skal inds\u00e6ttes som de er, men ellers ville have haft betydning for m\u00f8nstret (eksempelvis #).<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Nedenst\u00e5ende eksempel viser nogle forskellige m\u00f8nste og deres udskrifter:<\/p>\n<p>import java.text.*;<\/p>\n<p>import java.util.*;<\/p>\n<p>&nbsp;<\/p>\n<p>public class MultipleFormat<\/p>\n<p>{<\/p>\n<p>private static void print (String pattern, double tal)<\/p>\n<p>{<\/p>\n<p>DecimalFormat formatter = new DecimalFormat (pattern);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (&#8220;(&#8221; + pattern + &#8221; , &#8221; + tal + &#8220;) : &#8221; + formatter.format(tal));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>String[] patterns = {<\/p>\n<p>&#8220;\u00a4 ###,###.##&#8221;,<\/p>\n<p>&#8220;\u00a4\u00a4 ###,###.##&#8221;,<\/p>\n<p>&#8220;000,000.00&#8221;,<\/p>\n<p>&#8220;0.0000&#8221;,<\/p>\n<p>&#8220;-#&#8221;<\/p>\n<p>};<\/p>\n<p>&nbsp;<\/p>\n<p>for (int i = 0; i &lt; patterns.length; i++)<\/p>\n<p>print (patterns[i], 123456.123);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Eksemplet genererer f\u00f8lgende udskrift:<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>(\u00a4 ###,###.## , 123456.123) : kr 123.456,12<\/p>\n<p>(\u00a4\u00a4 ###,###.## , 123456.123) : DKK 123.456,12<\/p>\n<p>(000,000.00 , 123456.123) : 00.123.456,12<\/p>\n<p>(0.0000 , 123456.123) : 123456,1230<\/p>\n<p>(-# , 123456.123) : -123456<\/p>\n<p>&nbsp;<\/p>\n<p>Ovenst\u00e5ende gennemgang har imidlertid kun vist, hvordan man \u00e6ndrer formatet af udskriften, ikke hvordan man eksempelvis \u00e6ndrer decimaladskiller. Til denne opgave bruges DecimalFormatSymbols. Man kan oprette et DecimalFormatSymbols-objekt p\u00e5 to m\u00e5der. Enten kan man oprette et helt fra bunden, eller man kan tage udgangspunkt i et eksisterende objekt og foretage \u00e6ndringer p\u00e5 det. Det g\u00f8res ved at give et Locale-objekt med i DecimalFormatSymbol\u2019s constructor. Det kan for eksempel se s\u00e5ledes ud:<\/p>\n<p>&nbsp;<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>DecimalFormatSymbol symboler = new DecimalFormatSymbol(indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e5r DecimalFormatSymbol-objektet er oprettet, kan man kalde en r\u00e6kke metoder p\u00e5 det. Disse fremg\u00e5r af nedenst\u00e5ende signatur af DecimalFormatSymbol-klassen:<\/p>\n<p>&nbsp;<\/p>\n<p>public class DecimalFormatSymbols extends Object implements Cloneable, Serializable<\/p>\n<p>{<\/p>\n<p>public java.text.DecimalFormatSymbols();<\/p>\n<p>public java.text.DecimalFormatSymbols(java.util.Locale);<\/p>\n<p>&nbsp;<\/p>\n<p>public char getDecimalSeparator ();<\/p>\n<p>public char getDigit ();<\/p>\n<p>public char getGroupingSeparator ();<\/p>\n<p>public java.lang.String getInfinity ();<\/p>\n<p>public char getMinusSign ();<\/p>\n<p>public java.lang.String getNaN ();<\/p>\n<p>public char getPatternSeparator ();<\/p>\n<p>public char getPerMill ();<\/p>\n<p>public char getPercent ();<\/p>\n<p>public char getZeroDigit ();<\/p>\n<p>public void setDecimalSeparator (char);<\/p>\n<p>public void setDigit (char);<\/p>\n<p>public void setGroupingSeparator (char);<\/p>\n<p>public void setInfinity (java.lang.String);<\/p>\n<p>public void setMinusSign (char);<\/p>\n<p>public void setNaN (java.lang.String);<\/p>\n<p>public void setPatternSeparator (char);<\/p>\n<p>public void setPerMill (char);<\/p>\n<p>public void setPercent (char);<\/p>\n<p>public void setZeroDigit (char);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Som det fremg\u00e5r af signaturen, indeholder klassen metoder til b\u00e5de at s\u00e6tte og hente de forskellige oplysninger. Hvilke metoder, der foretager hvilke operationer, burde v\u00e6re indlysende.<\/p>\n<p>&nbsp;<\/p>\n<p><strong><br \/>\n<\/strong><\/p>\n<h1>Formatering af datoer og klokkesl\u00e6t<\/h1>\n<p>&nbsp;<\/p>\n<p>Ligesom tal og bel\u00f8b har behov for at blive formateret i henhold til omr\u00e5dets standarder, har datoer og klokkesl\u00e6t ogs\u00e5 behov for det. Nogle lande skriver m\u00e5ned f\u00f8r dagen, og det er forskelligt, hvilke tegn, der anvendes til at adskille dag og m\u00e5ned og m\u00e5ned\/dag og \u00e5r.<\/p>\n<p>&nbsp;<\/p>\n<p>I Javas Internationalization API h\u00e5ndteres disse formateringsfunktioner af DateFormat-klassen. Denne klasse har mange ligheder med NumberFormat-klassen, men der er ogs\u00e5 nogle forskellige. For eksempel skal NumberFormat kun tage sig af at formatere tallet \u2013 DateFormat skal ogs\u00e5 tage h\u00f8jde for, at der findes forskellige m\u00e5der at pr\u00e6sentere datoen p\u00e5. Der findes i Java fem forskellige m\u00e5der at pr\u00e6sentere en dato p\u00e5:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>DEFAULT. Pr\u00e6senterer datoen i det format, brugeren har valgt i operativsystemet.<\/li>\n<li>SHORT. Kort pr\u00e6sentation af datoen. For eksempel 24\/12\/98.<\/li>\n<li>MEDIUM. L\u00e6ngere pr\u00e6sentation af datoen. For eksempel 24. dec. 98.<\/li>\n<li>LONG. Lang pr\u00e6sentation af datoen. For eksempel 24. december 1998.<\/li>\n<li>FULL. Komplet beskrivelse af datoen. For eksempel Torsdag den 24. december 1998.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Det afh\u00e6nger af operativsystemet, hvordan de forskellige pr\u00e6sentationer er implementeret. Enkelte pr\u00e6sentationer kan v\u00e6re ens.<\/p>\n<p>&nbsp;<\/p>\n<p>Hvilken pr\u00e6sentation, man \u00f8nsker at anvende, skal angives i kaldet til getDateInstance. Hver af disse pr\u00e6sentationer er repr\u00e6senteret af en statisk variabel i DateFormat-klassen. I kaldet til getDateInstance skal ogs\u00e5 det Locale-objekt, der indeholder de indstillinger, man vil bruge til at formatere datoen, angives.<\/p>\n<p>&nbsp;<\/p>\n<p>Nedenst\u00e5ende klasse viser, hvordan man kan formatere en dato i forskellige formater:<\/p>\n<p>&nbsp;<\/p>\n<p>import java.text.*;<\/p>\n<p>import java.util.*;<\/p>\n<p>&nbsp;<\/p>\n<p>public class FormatDate<\/p>\n<p>{<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>&nbsp;<\/p>\n<p>DateFormat defaultFormat = DateFormat.getDateInstance (DateFormat.DEFAULT, indstillinger);<\/p>\n<p>DateFormat shortFormat = DateFormat.getDateInstance (DateFormat.SHORT, indstillinger);<\/p>\n<p>DateFormat mediumFormat = DateFormat.getDateInstance (DateFormat.MEDIUM, indstillinger);<\/p>\n<p>DateFormat longFormat = DateFormat.getDateInstance (DateFormat.LONG, indstillinger);<\/p>\n<p>DateFormat fullFormat = DateFormat.getDateInstance (DateFormat.FULL, indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>Date today = new Date();<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (defaultFormat.format(today));<\/p>\n<p>System.out.println (shortFormat.format(today));<\/p>\n<p>System.out.println (mediumFormat.format(today));<\/p>\n<p>System.out.println (longFormat.format(today));<\/p>\n<p>System.out.println (fullFormat.format(today));<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Hvis man vil formatere klokkesl\u00e6t i stedet for datoer, kan man stadigv\u00e6k bruge DateFormat-klassen. I stedet for at bruge en DateInstance\u00a0skal man blot bruge en TimeInstance.<\/p>\n<p>&nbsp;<\/p>\n<p>Ligesom der findes flere forskellige pr\u00e6sentationer af datoer, findes der ogs\u00e5 flere forskellige pr\u00e6sentationer af klokkesl\u00e6t. Det er de samme, statiske variabler i DateFormat-klassen, der bruges til at v\u00e6lge pr\u00e6sentationen af datoer som klokkesl\u00e6t.<\/p>\n<p>&nbsp;<\/p>\n<p>Der findes f\u00f8lgende forskellige pr\u00e6sentationer af klokkesl\u00e6t:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>DEFAULT. Den pr\u00e6sentation brugeren har valgt i operativsystemet.<\/li>\n<li>SHORT. Kort pr\u00e6sentation. For eksempel 17:30.<\/li>\n<li>MEDIUM. En l\u00e6ngere pr\u00e6sentation. For eksempel 17:30:15.<\/li>\n<li>LONG. En lang pr\u00e6sentation. For eksempel 17:30:15 GMT+02:00.<\/li>\n<li>FULL. Komplet pr\u00e6sentation. For eksempel Klokken 17:30:15 GMT+02:00.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Igen g\u00e6lder det, at det ikke er sikkert, at alle operativsystemer implementerer pr\u00e6sentationerne p\u00e5 samme m\u00e5de.<\/p>\n<p>&nbsp;<\/p>\n<p>Dette eksempel viser, hvordan man kan pr\u00e6sentere et klokkesl\u00e6t p\u00e5 forskellige m\u00e5der:<\/p>\n<p>&nbsp;<\/p>\n<p>import java.text.*;<\/p>\n<p>import java.util.*;<\/p>\n<p>&nbsp;<\/p>\n<p>public class FormatTime<\/p>\n<p>{<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>&nbsp;<\/p>\n<p>DateFormat defaultFormat = DateFormat.getTimeInstance (DateFormat.DEFAULT, indstillinger);<\/p>\n<p>DateFormat shortFormat = DateFormat.getTimeInstance (DateFormat.SHORT, indstillinger);<\/p>\n<p>DateFormat mediumFormat = DateFormat.getTimeInstance (DateFormat.MEDIUM, indstillinger);<\/p>\n<p>DateFormat longFormat = DateFormat.getTimeInstance (DateFormat.LONG, indstillinger);<\/p>\n<p>DateFormat fullFormat = DateFormat.getTimeInstance (DateFormat.FULL, indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>Date now = new Date();<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (defaultFormat.format(now));<\/p>\n<p>System.out.println (shortFormat.format(now));<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (mediumFormat.format(now));<\/p>\n<p>System.out.println (longFormat.format(now));<\/p>\n<p>System.out.println (fullFormat.format(now));<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Ligesom man kan v\u00e6lge at formatere tal efter et bestemt m\u00f8nster, kan man g\u00f8re det samme ved datoer og klokkesl\u00e6t. Til dette bruger man klassen java.text.SimpleDateFormat. Dennes constructor tager et m\u00f8nster som parameter. M\u00f8nsteret er en tekststreng, der angiver, hvordan datoen skal formateres. F\u00f8lgende regler g\u00e6lder for definition af m\u00f8nstret:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>G angiver, om datoen er f\u00f8r eller efter Kristi f\u00f8dsel.<\/li>\n<li>y angiver \u00e5ret.<\/li>\n<li>M angiver m\u00e5neden.<\/li>\n<li>d angiver datoen.<\/li>\n<li>h angiver timetallet efter 12-timerssystemet (1 \u2013 12).<\/li>\n<li>H angiver timetallet efter 24-timerssystemet (0 \u2013 23).<\/li>\n<li>m angiver antallet af minutter.<\/li>\n<li>s angiver antallet af sekunder.<\/li>\n<li>S angiver antallet af millisekunder.<\/li>\n<li>E angiver navnet p\u00e5 ugedagen.<\/li>\n<li>D angiver dagens nummer i \u00e5ret.<\/li>\n<li>F angiver dagens nummer i m\u00e5neden.<\/li>\n<li>w angiver ugens nummer i \u00e5ret.<\/li>\n<li>W angiver ugens nummer i m\u00e5neden.<\/li>\n<li>a angiver, om klokkesl\u00e6ttet er AM eller PM.<\/li>\n<li>k angiver timetallet efter 24-timerssystemet (1-24).<\/li>\n<li>K angiver timetallet efter 12-timerssystemet (0-11).<\/li>\n<li>z angiver tidszonen.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Antallet af gange, et tegn forekommer i m\u00f8nstret, afg\u00f8r hvordan informationen skal pr\u00e6senteres. Der g\u00e6lder de f\u00f8lgende regler:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>Ved information, der altid vises som tekst, vil 4 eller flere ens tegn medf\u00f8re, at det lange format benyttes. Ellers vil et kortere format blive benyttet, hvis et s\u00e5dant findes.<\/li>\n<li>Ved information, der altid vises med tal, angiver antallet af tegn, minimumsl\u00e6ngden for tallet. Hvis der er f\u00e6rre cifre i tallet, vil det blive indledt med nuller.<\/li>\n<li>Ved \u00e5rstal vil to gentagne tegn dog betyde, at \u00e5rstallet skal forkortes til to cifre (de to sidste).<\/li>\n<li>Ved informationer, der b\u00e5de kan vises som tal eller tekst, vil f\u00e6rre end tre tegn angive, at talformatet skal bruges.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Nedenst\u00e5ende klasse er et eksempel p\u00e5 brugen af et brugerdefineret m\u00f8nster.<\/p>\n<p>&nbsp;<\/p>\n<p>import java.text.*;<\/p>\n<p>import java.util.*;<\/p>\n<p>&nbsp;<\/p>\n<p>public class TimePattern<\/p>\n<p>{<\/p>\n<p>&nbsp;<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>String datePattern = &#8220;&#8216;Den&#8217; D&#8217;. dag i \u00e5ret&#8217; yyyy G &#8216;er&#8217; EEEE&#8217;, den&#8217; d&#8217;.&#8217; MMMM&#8217;. Den falder i \u00e5rets&#8217; w&#8217;. uge, og m\u00e5nedens&#8217; W&#8217;. uge'&#8221;;<\/p>\n<p>String timePattern = &#8220;&#8216;Klokken er&#8217; HH:mm:ss.SSSS &#8216;i tidszonen&#8217; z&#8221;;<\/p>\n<p>&nbsp;<\/p>\n<p>Date today = new Date();<\/p>\n<p>&nbsp;<\/p>\n<p>SimpleDateFormat dateFormatter = new SimpleDateFormat (datePattern);<\/p>\n<p>SimpleDateFormat timeFormatter = new SimpleDateFormat (timePattern);<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (dateFormatter.format (today));<\/p>\n<p>System.out.println (timeFormatter.format (today));<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>K\u00f8rslen af programmet giver denne udskrift:<\/p>\n<p>&nbsp;<\/p>\n<p>Den 174. dag i \u00e5ret 1998 AD er tirsdag, den 23. juni. Den falder i \u00e5rets 26. uge, og m\u00e5nedens 4. uge<\/p>\n<p>Klokken er 19:38:33.450 i tidszonen GMT+00:00<\/p>\n<p>&nbsp;<\/p>\n<p>Hvor man ved formatering af tal brugte klassen NumberFormatSymbols, kan man ved formatering af datoer og klokkesl\u00e6t bruge klassen DateFormatSymbols til at \u00e6ndre de symboler, der bruges i formateringen. Her skal man blot v\u00e6re opm\u00e6rksom p\u00e5, at symbolerne, man \u00e6ndrer, blandt andet er navnene p\u00e5 ugedagene og m\u00e5nederne.<\/p>\n<p>&nbsp;<\/p>\n<p>DateFormatSymbols-klassen indeholder en r\u00e6kke interessante funktioner, der alle fremg\u00e5r af dens signatur.<\/p>\n<p>&nbsp;<\/p>\n<p>public class DateFormatSymbols extends Object implements Serializable, Cloneable<\/p>\n<p>{<\/p>\n<p>public java.text.DateFormatSymbols();<\/p>\n<p>public java.text.DateFormatSymbols(java.util.Locale);<\/p>\n<p>&nbsp;<\/p>\n<p>public java.lang.String[] getAmPmStrings ();<\/p>\n<p>public java.lang.String[] getEras ();<\/p>\n<p>public java.lang.String getLocalPatternChars ();<\/p>\n<p>public java.lang.String[] getMonths ();<\/p>\n<p>public java.lang.String[] getShortMonths ();<\/p>\n<p>public java.lang.String[] getShortWeekdays ();<\/p>\n<p>public java.lang.String[] getWeekdays ();<\/p>\n<p>public java.lang.String[][] getZoneStrings ();<\/p>\n<p>public void setAmPmStrings (java.lang.String[]);<\/p>\n<p>public void setEras (java.lang.String[]);<\/p>\n<p>public void setLocalPatternChars (java.lang.String);<\/p>\n<p>public void setMonths (java.lang.String[]);<\/p>\n<p>public void setShortMonths (java.lang.String[]);<\/p>\n<p>&nbsp;<\/p>\n<p>public void setShortWeekdays (java.lang.String[]);<\/p>\n<p>public void setWeekdays (java.lang.String[]);<\/p>\n<p>public void setZoneStrings (java.lang.String[][]);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>Igen g\u00e6lder det, at klassen indeholder metoder til b\u00e5de at hente og \u00e6ndre indstillingerne. Det vil sige, at man enten kan oprette et DateFormatSymbols-objekt fra bunden eller hente et omr\u00e5des indstillinger og arbejde videre p\u00e5 disse og eventuelt modificere dem.<\/p>\n<p>&nbsp;<\/p>\n<h1>H\u00e5ndtering af beskeder<\/h1>\n<p>&nbsp;<\/p>\n<p>Tidligere i kapitlet blev det gennemg\u00e5et, hvordan man kunne gemme tekster i en ResourceBundle, s\u00e5 det var let at h\u00e5ndtere overs\u00e6ttelser uden at skulle rekompilere hele applikationen. Det l\u00f8ser imidlertid kun en del af problematikken med beskeder. Hvis en besked b\u00e5de best\u00e5r af tekst og data, l\u00f8ber man i problematikken med forskellig ordstilling p\u00e5 forskellige sprog. Hvis man vil udskrive en besked om, at en fil ikke kan l\u00e6ses, kan det p\u00e5 engelsk g\u00f8res s\u00e5ledes<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (&#8220;Unable to read the file &#8221; + filename);<\/p>\n<p>&nbsp;<\/p>\n<p>mens den tilsvarende danske tekst vil se s\u00e5ledes ud<\/p>\n<p>&nbsp;<\/p>\n<p>System.out.println (&#8220;Filen &#8221; + filename + &#8221; kunne ikke l\u00e6ses&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<p>For at l\u00f8se dette problem kan man bruge MessageFormat-klassen.<\/p>\n<p>&nbsp;<\/p>\n<p>At h\u00e5ndtere sammensatte strenge som eksemplet ovenfor er en proces, der kan deles op i fem trin:<\/p>\n<p>&nbsp;<\/p>\n<ol>\n<li>Identific\u00e9r variablerne i teksten og defin\u00e9r deres typer.<\/li>\n<li>Isol\u00e9r beskedens m\u00f8nster i en ResourceBundle.<\/li>\n<li>Angiv beskedens parametre.<\/li>\n<li>Opret et MessageFormat-objekt.<\/li>\n<li>Format\u00e9r beskeden ved brug af m\u00f8nstret og parametrene.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>At identificere variablerne og definere deres typer g\u00f8res ved at kigge p\u00e5 teksten, og se hvilke dele af den, der kan skiftes ud. Hvis teksten for eksempel er<\/p>\n<p>&nbsp;<\/p>\n<p>Klokken 8:05 stod hr. Madsen op.<\/p>\n<p>&nbsp;<\/p>\n<p>er det tydeligt, at klokkesl\u00e6ttet (8:05) er en variabel. Ligeledes er \u201dhr. Madsen\u201d en variabel, for det kunne lige s\u00e5 godt have v\u00e6ret fru Petersen, der var st\u00e5et op. Klokkesl\u00e6ttet er en variabel af typen Date, mens navnet er en variabel af typen String.<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e6ste punkt er at isolere m\u00f8nstret i en ResourceBundle. Da teksten er en streng, er det nemmest at g\u00f8re det i en PropertyResourceBundle. Hvis den overordnede ResourceBundle kaldes Besked, vil den danske udgave af filen hedde Besked_da_DK.properties. Filen kan komme til at se s\u00e5ledes ud:<\/p>\n<p>&nbsp;<\/p>\n<p>besked = Klokken {0,time,short) stod {1} op.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Som det ses, er hver variabel nu angivet i kr\u00f8llede parenteser. F\u00f8rst i hver kr\u00f8llet parentes angives nummeret p\u00e5 det parameter, der skal inds\u00e6ttes her. Her kommer parametrene i r\u00e6kkef\u00f8lge, men det er ikke en n\u00f8dvendighed.<\/p>\n<p>&nbsp;<\/p>\n<p>For den f\u00f8rste variabel er der angivet yderligere to oplysninger. Den f\u00f8rste angiver, at der skal vises et tidspunkt, mens den anden angiver, at tidspunktet skal vises i det korte format. Den anden parameter (med nummeret 1) er blot en tekststreng, der skal vises, og det er ikke n\u00f8dvendigt med yderligere informationer for at kunne vise den.<\/p>\n<p>&nbsp;<\/p>\n<p>Generelt findes der f\u00f8lgende regler for angivelse af variabler i et m\u00f8nster:<\/p>\n<ul>\n<li>F\u00f8rste parameter er altid nummeret p\u00e5 det parameter, der skal inds\u00e6ttes p\u00e5 denne plads.<\/li>\n<li>Andet parameter kan undlades eller v\u00e6re time\u00b8 date, number eller choice.\n<ul>\n<li>Hvis det andet parameter er time eller date, kan det tredje parameter v\u00e6re short, medium, long eller full eller et brugerdefineret dato- eller tidsm\u00f8nster.<\/li>\n<li>Hvis det andet parameter er number, kan det tredje parameter v\u00e6re currency, percent, integer, eller et brugerdefineret m\u00f8nster til formatering af tal.<\/li>\n<li>Hvis det andet parameter er choice, skal det tredje parameter v\u00e6re et brugerdefineret m\u00f8nster.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Hvis et parameter mangler eller ikke er af den type, der er angive, opst\u00e5r en parseException.<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e5r property-filen er defineret, er den nem at indl\u00e6se fra selve programmet:<\/p>\n<p>&nbsp;<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>ResourceBundle besked = ResourceBundle.getBundle(&#8220;Besked&#8221;, indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>Med det p\u00e5 plads kan man definere det array, der skal indeholde parametrene til teksten. Det kan se s\u00e5ledes ud:<\/p>\n<p>&nbsp;<\/p>\n<p>Object[] parametre = {<\/p>\n<p>new Date();<\/p>\n<p>&#8220;Hr. Madsen&#8221;<\/p>\n<p>};<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e5r parametrene er defineret, kan man g\u00e5 videre med at instantiere et MessageFormat-objekt.<\/p>\n<p>&nbsp;<\/p>\n<p>MessageFormat formatter = new MessageFormat(&#8220;&#8221;);<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>formatter.setLocale (indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>I mods\u00e6tning til de andre formatter-klasser (NumberFormat og DateFormat) opretter man en instans af MessageFormat ved at bruge dens constructor. Som parameter til constructoren gives en tekststreng, der indeholder det m\u00f8nster, der skal formateres efter. I dette eksempel bliver m\u00f8nstret f\u00f8rst angivet senere, og parametret er derfor en tom streng.<\/p>\n<p>&nbsp;<\/p>\n<p>For at sikre, at de variabler, der skal vises i strengen, bliver formateret<\/p>\n<p>&nbsp;<\/p>\n<p>rigtigt, informeres MessageFormat om, hvilket Locale-objekt, der skal bruges til formateringen.<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e5r MessageFormat-objektet er oprettet, kan man formatere teksten. Det g\u00f8res ved at indl\u00e6se m\u00f8nstret fra ResourceBundle\u2019n og angive dette som det m\u00f8nster, MessageFormat-objektet skal bruge. Herefter skal man blot kalde MessageFormat\u2019s format-metode:<\/p>\n<p>&nbsp;<\/p>\n<p>formatter.applyPattern (besked.getString(&#8220;besked&#8221;));<\/p>\n<p>System.out.println (formatter.format(parametre));<\/p>\n<p>&nbsp;<\/p>\n<h2>Ental og flertal<\/h2>\n<p>&nbsp;<\/p>\n<p>Problemet med beskeder er imidlertid ikke kun at f\u00e5 dem sat sammen i den rigtige r\u00e6kkef\u00f8lge. Man skal ogs\u00e5 sikre sig, at de er grammatisk korrekte. Hvis man for eksempel vil udskrive en besked om, hvor mange filer, der er blevet slettet, skal man tage h\u00f8jde for, at beskeden ikke er den samme, hvis der bliver slettet 1 eller 2 beskeder. S\u00e5 vil beskederne hedde:<\/p>\n<p>&nbsp;<\/p>\n<p>Der blev slettet 1 fil.<\/p>\n<p>Der blev slettet 2 filer.<\/p>\n<p>&nbsp;<\/p>\n<p>L\u00f8sningen p\u00e5 problemet kunne v\u00e6re, at angive flertalsformen i parentes<\/p>\n<p>&nbsp;<\/p>\n<p>Der blev slettet 2 fil(er).<\/p>\n<p>&nbsp;<\/p>\n<p>men det er ikke s\u00e6rlig p\u00e6nt. Det giver i \u00f8vrigt ogs\u00e5 et problem i bestemt form \u2013 hvis man eksempelvis vil bekr\u00e6fte, at filerne virkeligt er blevet slettet, kan man enten skrive<\/p>\n<p>&nbsp;<\/p>\n<p>Filen er blevet slettet.<\/p>\n<p>&nbsp;<\/p>\n<p>eller<\/p>\n<p>&nbsp;<\/p>\n<p>Filerne er blevet slettet.<\/p>\n<p>&nbsp;<\/p>\n<p>Her er det ikke muligt at s\u00e6tte flertalsformen i parentes.<\/p>\n<p>&nbsp;<\/p>\n<p>Javas l\u00f8sning p\u00e5 problemet er klassen ChoiceFormat. Fremgangsm\u00e5den, n\u00e5r ChoiceFormat-klassen bruges, er n\u00e6sten den samme, som ved de andre format-klasser.<\/p>\n<ol>\n<li>Defin\u00e9r m\u00f8nstret<\/li>\n<li>L\u00e6g m\u00f8nstret i en ResourceBundle<\/li>\n<li>Opret et MessageFormat-objekt<\/li>\n<li>Opret et ChoiceFormat-objekt<\/li>\n<li>Anvend m\u00f8nstret<\/li>\n<li>Anvend ChoiceFormat-objektet<\/li>\n<li>Angiv parametrene<\/li>\n<li>Format\u00e9r beskeden p\u00e5 baggrund af m\u00f8nstret og parametrene.<\/li>\n<\/ol>\n<p>I de tidligere eksempler var parametrene i teksten en af Javas typer. Det er ikke l\u00e6ngere tilf\u00e6ldet. Nu er parametrene en blanding af tekst og de egentlige variabler. Eksempelvis<\/p>\n<p>&nbsp;<\/p>\n<p>Der blev ikke slettet nogen filer.<\/p>\n<p>Der blev slettet 1 fil.<\/p>\n<p>&nbsp;<\/p>\n<p>Der blev slettet 2 filer.<\/p>\n<p>&nbsp;<\/p>\n<p>Som det ses, kan alt efter \u201dDer blev\u201d blive \u00e6ndret \u2013 det m\u00e5 derfor opfattes som variabler. Det vil sige, at m\u00f8nstret kommer til at se s\u00e5ledes ud:<\/p>\n<p>&nbsp;<\/p>\n<p>Der blev {0}<\/p>\n<p>&nbsp;<\/p>\n<p>Det parameter, der findes i m\u00f8nstret, er imidlertid v\u00e6sentligt sv\u00e6rere at h\u00e5ndtere end de, der tidligere er blevet arbejdet med i kapitlet. Dette skyldes, at antallet af filer, der er blevet slettet, p\u00e5virker teksten, hvilket medf\u00f8rer, at man skal have en m\u00e5de til at finde ud af, hvilken tekst der h\u00f8rer til hvilken talv\u00e6rdi. Derudover indg\u00e5r der et tal i teksten \u2013 det kan jo godt t\u00e6nkes, at der bliver slettet mere end 2 filer. Det betyder, at det skal v\u00e6re muligt at \u00e6ndre tallet i flertalsformen af beskeden.<\/p>\n<p>&nbsp;<\/p>\n<p>Disse problemer vil blive l\u00f8st i det f\u00f8lgende.<\/p>\n<p>&nbsp;<\/p>\n<p>F\u00f8rste skridt p\u00e5 vejen er at oprette en ResourceBundle. Igen vil der blive brugt en PropertyResourceBundle, da den kun skal h\u00e5ndtere tekststrenge. Filen kommer i dette eksempel til at hedde SletFil_da_DK.properties, og den ser s\u00e5ledes ud:<\/p>\n<p>&nbsp;<\/p>\n<p>Pattern = Der blev {0}<\/p>\n<p>IngenFiler = ikke slettet nogen filer.<\/p>\n<p>EnFil = slettet en fil.<\/p>\n<p>FlereFiler = slettet {1} filer.<\/p>\n<p>&nbsp;<\/p>\n<p>Pattern angiver det m\u00f8nster, der skal anvendes \u2013 det blev defineret tidligere. De efterf\u00f8lgende tekster er de, der kan inds\u00e6ttes p\u00e5 parameter 0\u2019s plads. Teksten kaldt FlereFiler er selv et m\u00f8nster, der g\u00f8r det muligt at inds\u00e6tte antallet af filer. N\u00e5r property-filen er oprettet, er det ikke noget problem at indl\u00e6se den som en ResourceBundle:<\/p>\n<p>&nbsp;<\/p>\n<p>Locale indstillinger = Locale.getDefault ();<\/p>\n<p>ResourceBundle tekster = ResourceBundle.getBundle (&#8220;SletFil&#8221;, indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>Ligesom i det foreg\u00e5ende tilf\u00e6lde, skal klassen MessageFormat bruges til at formatere teksten:<\/p>\n<p>&nbsp;<\/p>\n<p>MessageFormat formatter = new MessageFormat (&#8220;&#8221;);<\/p>\n<p>formatter.setLocale (indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>N\u00e5r MessageFormat-objektet er oprettet, skal der oprettes et ChoiceFormat-objekt. For at man kan lave dette, skal man f\u00f8rst lave et array, der angiver gr\u00e6nsev\u00e6rdierne for, hvorn\u00e5r en given tekst skal bruges:<\/p>\n<p>&nbsp;<\/p>\n<p>double[] limits = {0, 1, 2};<\/p>\n<p>&nbsp;<\/p>\n<p>Det vil sige, at hvis antallet af slettede filer er st\u00f8rre end eller lig med 0, bliver den f\u00f8rste tekst vist. Hvis antallet er st\u00f8rre end eller lig med 1, bliver den n\u00e6ste vist, mens tal st\u00f8rre end eller lig med 2 vil resultere i, at den sidste tekst bliver vist.<\/p>\n<p>&nbsp;<\/p>\n<p>ChoiceFormat skal imidlertid ogs\u00e5 vide, hvilke tekster det er, der skal vises. Dette g\u00f8r man objektet opm\u00e6rksom p\u00e5 ved at oprette et array af tekststrenge:<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>String beskeder[] = {<\/p>\n<p>tekster.getString (&#8220;IngenFiler&#8221;),<\/p>\n<p>tekster.getString (&#8220;EnFil&#8221;),<\/p>\n<p>tekster.getString (&#8220;FlereFiler&#8221;)<\/p>\n<p>};<\/p>\n<p>&nbsp;<\/p>\n<p>Som det ses, bliver teksterne indl\u00e6st fra den ResourceBundle, der blev defineret tidligere. N\u00e5r gr\u00e6nsev\u00e6rdierne og teksterne er defineret, kan ChoiceFormat-objektet oprettes:<\/p>\n<p>&nbsp;<\/p>\n<p>ChoiceFormat\u00a0choice = new ChoiceFormat (limits, beskeder);<\/p>\n<p>&nbsp;<\/p>\n<p>Efter at have oprettet ChoiceFormat-objektet kan man tilknytte m\u00f8nstret til MessageFormat-objektet:<\/p>\n<p>&nbsp;<\/p>\n<p>String pattern = tekster.getString (&#8220;pattern&#8221;);<\/p>\n<p>formatter.applyPattern (pattern);<\/p>\n<p>&nbsp;<\/p>\n<p>Det n\u00e6ste, der skal g\u00f8res, er at oprette et array af Format-objekter. Dette array skal indeholde referencer til de objekter, der skal bruges til at formatere de forskellige parametre i m\u00f8nstret:<\/p>\n<p>&nbsp;<\/p>\n<p>Format[] formatListe = {choice, NumberFormat.getNumberInstance()};<\/p>\n<p>formatter.setFormats (formatListe);<\/p>\n<p>&nbsp;<\/p>\n<p>Ovenst\u00e5ende angiver, at det f\u00f8rste parameter \u2013 det, der angives med {0} \u2013 skal formateres med choice. Dern\u00e6st angives det, at det andet parameter \u2013 {1} \u2013 skal formateres med et NumberFormat-objekt. Det andet parameter er som bekendt antallet af filer, der blev slettet, hvis dette er 2 eller derover.<\/p>\n<p>&nbsp;<\/p>\n<p>Tilbage er der nu kun at bruge m\u00f8nstret. Hertil skal der bruges nogle parametre. I dette tilf\u00e6lde skal det angives, hvor mange filer der er blevet slettet. Dette skal angives to gange, da det i f\u00f8rste omgang angiver, hvilken tekststreng der skal vises, og dern\u00e6st bruges til at vise antallet af slettede filer.<\/p>\n<p>&nbsp;<\/p>\n<p>For at vise, om eksemplet virker, kan man skrive f\u00f8lgende kode:<\/p>\n<p>&nbsp;<\/p>\n<p>Object[] parametre = new Object[2];<\/p>\n<p>&nbsp;<\/p>\n<p>for (int i = 0; i &lt; 4; i++)<\/p>\n<p>{<\/p>\n<p>parametre[0] = new Integer (i);<\/p>\n<p>parametre[1] = new Integer (i);<\/p>\n<p>System.out.println (formatter.format(parametre));<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>S\u00e5 genererer programmet f\u00f8lgende udskrift:<\/p>\n<p>&nbsp;<\/p>\n<p>Der blev ikke slettet nogen filer.<\/p>\n<p>Der blev slettet en fil.<\/p>\n<p>Der blev slettet 2 filer.<\/p>\n<p>Der blev slettet 3 filer.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h1>Sammenligning af tekster<\/h1>\n<p>&nbsp;<\/p>\n<p>Forskellige sprog og \u2013 is\u00e6r \u2013 forskellige tegns\u00e6t giver ogs\u00e5 problemer, n\u00e5r man skal sammenligne tekster. Sammenligning af tekster er ikke bare at se, om to tekster er ens, men ogs\u00e5 \u2013 hvis de ikke er det \u2013 at se, hvilken tekst, der kommer f\u00f8rst i alfabetet. Her er der en del ting, man skal v\u00e6re opm\u00e6rksom p\u00e5. For eksempel vil et ord, der starter med A kommer f\u00f8r et ord, der starter med B, men hvis ordet eksempelvis er Aalborg, skal det til sidst, fordi dobbelt-A fortolkes som \u00c5.<\/p>\n<p>&nbsp;<\/p>\n<p>Normalt vil sammenligning af strenge i Java foreg\u00e5 ved hj\u00e6lp af compareTo-metoden. Denne foretager en bin\u00e6r sammenligning af teksterne. Det betyder, at den sorterer efter tegnenes Unicode-v\u00e6rdi. R\u00e6kkef\u00f8lgen her er ikke n\u00f8dvendigvis den samme som r\u00e6kkef\u00f8lgen i alfabetet. Derudover tager compareTo ikke h\u00f8jde for, at to bogstaver ved siden af hinanden m\u00e5ske skal fortolkes som \u00e9t bogstav.<\/p>\n<p>&nbsp;<\/p>\n<p>For at sikre en sproguafh\u00e6ngig sammenligning skal man bruge klassen java.text.Collator.<\/p>\n<p>&nbsp;<\/p>\n<p>Man opretter en instans af denne ved at kalde metoden getInstance:<\/p>\n<p>&nbsp;<\/p>\n<p>Locale indstillinger = Locale.getdefault();<\/p>\n<p>Collator sammenligner = Collater.getInstance(indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>Herefter kan man bruges Collator-objektets compare-metode til at sammenligne tekststrenge:<\/p>\n<p>&nbsp;<\/p>\n<p>sammenligner.compare(&#8220;abe&#8221;, &#8220;delfin&#8221;);<\/p>\n<p>&nbsp;<\/p>\n<h1>Sammenfatning<\/h1>\n<p>&nbsp;<\/p>\n<p>I dette kapitel er de problemer, der kan opst\u00e5, n\u00e5r man flytter et program fra et land til et andet, blevet gennemg\u00e5et. Der er blevet set p\u00e5, hvordan man kan bruge klasser som NumberFormat og DateFormat til at formatere henholdsvis tal og datoer til den lokale standard. Det er ogs\u00e5 blevet gennemg\u00e5et, hvordan man h\u00e5ndterer tekster ved hj\u00e6lp af MessageFormat og den lidt mere komplicerede ChoiceFormat-klasse. Endeligt er det blevet forklaret, hvordan man kan bruge Collator-klassen til at sammenligne tekster p\u00e5 en mere sproguafh\u00e6ngig m\u00e5de end String\u2019s compareTo-funktion.<\/p>\n<p>&nbsp;<\/p>\n<h1>FAQ<\/h1>\n<h2>Hvordan indl\u00e6ser jeg tal og datoer, som er formateret efter de lokale standarder?<\/h2>\n<p>Normalt n\u00e5r man indl\u00e6ser tal og datoer, sker dette efter engelsk standard \u2013 det vil blandt andet sige, at punktum bruges som decimaladskiller. Hvis man vil bruge de lokale indstillinger, n\u00e5r man indl\u00e6ser, skal man indl\u00e6se tallet eller datoen i en tekststreng. Herefter skal man oprette en instans af DateFormat eller NumberFormat. P\u00e5 dette objekt skal man kalde parse-funktionen. Nedenst\u00e5ende main-metode viser, hvordan det kan g\u00f8res:<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>public static final void main (String args[])<\/p>\n<p>{<\/p>\n<p>String tal = &#8220;12.194,52&#8221;;<\/p>\n<p>&nbsp;<\/p>\n<p>Locale indstillinger = Locale.getDefault();<\/p>\n<p>NumberFormat formatter = NumberFormat.getInstance (indstillinger);<\/p>\n<p>&nbsp;<\/p>\n<p>Double d = null;<\/p>\n<p>&nbsp;<\/p>\n<p>try<\/p>\n<p>{<\/p>\n<p>d = (Double) formatter.parse (tal);<\/p>\n<p>System.out.println (d.doubleValue());<\/p>\n<p>}<\/p>\n<p>catch (ParseException pe)<\/p>\n<p>{<\/p>\n<p>System.out.println (pe.toString());<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<h2>Hvordan tager man h\u00f8jde for, at tekster i brugergr\u00e6nsefladen ikke fylder lige meget p\u00e5 alle sprog?<\/h2>\n<p>&nbsp;<\/p>\n<p>Hvis man giver labels i brugergr\u00e6nsefladen absolutte st\u00f8rrelser, kan man komme ud for, at nogle tekster ikke bliver vist i deres fulde l\u00e6ngde, hvis de fylder mere p\u00e5 et andet sprog end det originale. Den bedste m\u00e5de at afhj\u00e6lpe dette problem er at lade v\u00e6re med at angive absolutte st\u00f8rrelser og i stedet bruge en layout-manager.<\/p>\n<p>&nbsp;<\/p>\n<h2>Hvilke fordele og ulemper er der ved at anvende Unicode-tegn?<\/h2>\n<p>&nbsp;<\/p>\n<p>Fordelen ved at bruge Unicode-tegn er, at Unicode-tegntabellen indeholder alle tegn. Ulempen er, at tegnene fylder mere end de almindelige tegn, og at de er langsommere at arbejde med. Derudover skal man v\u00e6re opm\u00e6rksom p\u00e5, at det ikke er alle platforme, der underst\u00f8tter Unicode, fordi der ikke findes ret mange skrifttyper, der underst\u00f8tter alle Unicode-standardens tegn.<\/p>\n<p>&nbsp;<\/p>\n<div style=\"border: 1px solid red; color: red\">\n<b>Du l\u00e6ser en gammel bog<\/b><br \/>\nDen bog, du l\u00e6ser her, er fra 1998, og mange ting kan have \u00e6ndret sig siden da.<br \/>\nVi h\u00e5ber, at du stadig kan finde relevant information i den.<br \/>\nHvis du vil l\u00e6se aktuelle oplysninger om de avancerede dele af Java, anbefaler vi<br \/>\nbogen <a href=\"http:\/\/clk.tradedoubler.com\/click?p(197229)a(2029446)g(19172914)url(http:\/\/www.adlibris.com\/dk\/product.aspx?isbn=0132354799)\"  target=\"_blank\">Core Java &#8211; Advanced Features<\/a><img decoding=\"async\" src=\"http:\/\/impdk.tradedoubler.com\/imp?type(inv)g(19172914)a(2029446)\" \/>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>En af Javas store fordele er, at de kompilerede filer er platformsuafh\u00e6ngige. Det ville v\u00e6re rart, hvis de ogs\u00e5 var sproguafh\u00e6ngige \u2013 og her t\u00e6nkes ikke p\u00e5 programmeringssprog, men p\u00e5 de sprog som brugerne taler. Du l\u00e6ser en gammel bog Den bog, du l\u00e6ser her, er fra 1998, og mange ting kan have \u00e6ndret sig [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":332,"menu_order":80,"comment_status":"closed","ping_status":"open","template":"","meta":{"_monsterinsights_skip_tracking":false,"footnotes":""},"class_list":["post-410","page","type-page","status-publish","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Internationale produkter kan naturligvis opn\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\u00e5 kan man lade hver version af programmet underst\u00f8tte et specielt sprog. Dette kr\u00e6ver en rekompilering af applikationen, hver gang man vil underst\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \u00e6ndring eller en opdatering af programmet, skal den samme \u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"keywords\" content=\"java,internationalization,localization,l10n,i18n,overs\u00e6ttelse,datoformat,tekstformat,talformat\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Biblioteket | Samling af artikler og b\u00f8ger\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Internationale programmer | Biblioteket\" \/>\n\t\t<meta property=\"og:description\" content=\"Internationale produkter kan naturligvis opn\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\u00e5 kan man lade hver version af programmet underst\u00f8tte et specielt sprog. Dette kr\u00e6ver en rekompilering af applikationen, hver gang man vil underst\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \u00e6ndring eller en opdatering af programmet, skal den samme \u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2011-11-03T12:52:08+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2011-11-03T12:53:10+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Internationale programmer | Biblioteket\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Internationale produkter kan naturligvis opn\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\u00e5 kan man lade hver version af programmet underst\u00f8tte et specielt sprog. Dette kr\u00e6ver en rekompilering af applikationen, hver gang man vil underst\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \u00e6ndring eller en opdatering af programmet, skal den samme \u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres.\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-8-internationale-programmer\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/#listItem\",\"name\":\"B\\u00f8ger\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/#listItem\",\"position\":2,\"name\":\"B\\u00f8ger\",\"item\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/#listItem\",\"name\":\"Avanceret Java-programmering\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/#listItem\",\"position\":3,\"name\":\"Avanceret Java-programmering\",\"item\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-8-internationale-programmer\\\/#listItem\",\"name\":\"Kapitel 8 Internationale programmer\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/#listItem\",\"name\":\"B\\u00f8ger\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-8-internationale-programmer\\\/#listItem\",\"position\":4,\"name\":\"Kapitel 8 Internationale programmer\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/#listItem\",\"name\":\"Avanceret Java-programmering\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#organization\",\"name\":\"Biblioteket\",\"description\":\"Samling af artikler og b\\u00f8ger\",\"url\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-8-internationale-programmer\\\/#webpage\",\"url\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-8-internationale-programmer\\\/\",\"name\":\"Internationale programmer | Biblioteket\",\"description\":\"Internationale produkter kan naturligvis opn\\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\\u00e5 kan man lade hver version af programmet underst\\u00f8tte et specielt sprog. Dette kr\\u00e6ver en rekompilering af applikationen, hver gang man vil underst\\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \\u00e6ndring eller en opdatering af programmet, skal den samme \\u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres.\",\"inLanguage\":\"da-DK\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/avanceret-java-programmering\\\/kapitel-8-internationale-programmer\\\/#breadcrumblist\"},\"datePublished\":\"2011-11-03T14:52:08+02:00\",\"dateModified\":\"2011-11-03T14:53:10+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#website\",\"url\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/\",\"name\":\"Biblioteket\",\"description\":\"Samling af artikler og b\\u00f8ger\",\"inLanguage\":\"da-DK\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Internationale programmer | Biblioteket","description":"Internationale produkter kan naturligvis opn\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\u00e5 kan man lade hver version af programmet underst\u00f8tte et specielt sprog. Dette kr\u00e6ver en rekompilering af applikationen, hver gang man vil underst\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \u00e6ndring eller en opdatering af programmet, skal den samme \u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres.","canonical_url":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/","robots":"max-image-preview:large","keywords":"java,internationalization,localization,l10n,i18n,overs\u00e6ttelse,datoformat,tekstformat,talformat","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BreadcrumbList","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek#listItem","position":1,"name":"Home","item":"https:\/\/www.kristiansborg.dk\/bibliotek","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/#listItem","name":"B\u00f8ger"}},{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/#listItem","position":2,"name":"B\u00f8ger","item":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/#listItem","name":"Avanceret Java-programmering"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/#listItem","position":3,"name":"Avanceret Java-programmering","item":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/#listItem","name":"Kapitel 8 Internationale programmer"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/#listItem","name":"B\u00f8ger"}},{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/#listItem","position":4,"name":"Kapitel 8 Internationale programmer","previousItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/#listItem","name":"Avanceret Java-programmering"}}]},{"@type":"Organization","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#organization","name":"Biblioteket","description":"Samling af artikler og b\u00f8ger","url":"https:\/\/www.kristiansborg.dk\/bibliotek\/"},{"@type":"WebPage","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/#webpage","url":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/","name":"Internationale programmer | Biblioteket","description":"Internationale produkter kan naturligvis opn\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\u00e5 kan man lade hver version af programmet underst\u00f8tte et specielt sprog. Dette kr\u00e6ver en rekompilering af applikationen, hver gang man vil underst\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \u00e6ndring eller en opdatering af programmet, skal den samme \u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres.","inLanguage":"da-DK","isPartOf":{"@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#website"},"breadcrumb":{"@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/#breadcrumblist"},"datePublished":"2011-11-03T14:52:08+02:00","dateModified":"2011-11-03T14:53:10+02:00"},{"@type":"WebSite","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#website","url":"https:\/\/www.kristiansborg.dk\/bibliotek\/","name":"Biblioteket","description":"Samling af artikler og b\u00f8ger","inLanguage":"da-DK","publisher":{"@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#organization"}}]},"og:locale":"da_DK","og:site_name":"Biblioteket | Samling af artikler og b\u00f8ger","og:type":"article","og:title":"Internationale programmer | Biblioteket","og:description":"Internationale produkter kan naturligvis opn\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\u00e5 kan man lade hver version af programmet underst\u00f8tte et specielt sprog. Dette kr\u00e6ver en rekompilering af applikationen, hver gang man vil underst\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \u00e6ndring eller en opdatering af programmet, skal den samme \u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres.","og:url":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/","article:published_time":"2011-11-03T12:52:08+00:00","article:modified_time":"2011-11-03T12:53:10+00:00","twitter:card":"summary","twitter:title":"Internationale programmer | Biblioteket","twitter:description":"Internationale produkter kan naturligvis opn\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\u00e5 kan man lade hver version af programmet underst\u00f8tte et specielt sprog. Dette kr\u00e6ver en rekompilering af applikationen, hver gang man vil underst\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \u00e6ndring eller en opdatering af programmet, skal den samme \u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres."},"aioseo_meta_data":{"post_id":"410","title":"Internationale programmer | #site_title","description":"Internationale produkter kan naturligvis opn\u00e5s ved at have forskellige kildetekster til de forskellige versioner af programmet. S\u00e5 kan man lade hver version af programmet underst\u00f8tte et specielt sprog. Dette kr\u00e6ver en rekompilering af applikationen, hver gang man vil underst\u00f8tte et nyt sprog, men det er det mindste problem. Hvis man foretager en \u00e6ndring eller en opdatering af programmet, skal den samme \u00e6ndring foretages i samtlige versioner, og samtlige versioner skal rekompileres.","keywords":[{"label":"Java","value":"Java"},{"label":"internationalization","value":"internationalization"},{"label":"localization","value":"localization"},{"label":"l10n","value":"l10n"},{"label":"i18n","value":"i18n"},{"label":"overs\u00e6ttelse","value":"overs\u00e6ttelse"},{"label":"datoformat","value":"datoformat"},{"label":"tekstformat","value":"tekstformat"},{"label":"talformat","value":"talformat"}],"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2020-12-21 06:59:15","updated":"2025-06-04 02:17:13","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kristiansborg.dk\/bibliotek\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/\" title=\"B\u00f8ger\">B\u00f8ger<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/\" title=\"Avanceret Java-programmering\">Avanceret Java-programmering<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tKapitel 8 Internationale programmer\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.kristiansborg.dk\/bibliotek"},{"label":"B\u00f8ger","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/"},{"label":"Avanceret Java-programmering","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/"},{"label":"Kapitel 8 Internationale programmer","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/avanceret-java-programmering\/kapitel-8-internationale-programmer\/"}],"_links":{"self":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/410","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/comments?post=410"}],"version-history":[{"count":2,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/410\/revisions"}],"predecessor-version":[{"id":412,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/410\/revisions\/412"}],"up":[{"embeddable":true,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/332"}],"wp:attachment":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/media?parent=410"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}