Arbeta med Intl

Internationalisering - något du ständigt hör utvecklare pratar om men ser sällan faktiskt på att människor använder i praktiken - får en spark i byxorna med det nya ECMAScript Internationalization API. För närvarande stöds i Chrome 24, Chrome för Android, Firefox 29, IE 11 och Opera 15 (tyvärr ingen Safari support), den nya Intl namespace ger en uppsättning funktioner för att lägga till internationalisering till dina nummer, datum och sortering. I den här artikeln ska jag demonstrera de viktigaste funktionerna i Intl och få dig på vägen för att anta stöd för de miljarder människor på Internet som bor utanför ditt eget land!

Kärnfunktioner

Intl namespace täcker tre huvudområden av funktionalitet:

  • Formateringsnummer
  • Formateringsdatum
  • Sortera strängar

Inom varje av dessa finns olika alternativ för att styra både de språk som används för formatering och formatering. Som exempel innefattar talformateraren stöd för hantering av valuta. Datumformateraren har alternativ för vilka delar av datumet som ska visas.

Låt oss titta på några exempel.

Vår ansökan

Vår första ansökan är en enkel dataregister. Det använder AJAX för att hämta en uppsättning data som innehåller datum och nummer. Först HTML:

Listning 1: test1.html:

          

Aktuella statistik

Datum besök

Notera den tomma tabellen. Det är där vi kommer att dumpa våra data. Låt oss nu titta på JavaScript.

Notering 2: app1.js:

$ (dokument) .ready (funktion () // få tabellen dom $ table = $ ("# stats tbody"); // nu, hämta vår data från api, vilket är falskt btw $ .getJSON .json "). gjort (funktion (er) // iterera över statistik och lägg till i tabell för (var i = 0; i < s.length; i++)  $table.append(""+s[i].date+""+s[i].views+"");  ).fail(function(e)  console.log("we failed"); console.dir(e); ); ); 

Allt som koden gör här är att göra ett AJAX-samtal till en fil och göra resultatet till data. Datafilen, stats.json, är helt enkelt en uppsättning av tio hårdkodade värden. Här är en del av filen:

[ "Date": "2013/04/01", "åsikter": 938213  "Datum": "2013/04/02", "åsikter": 238213, 

Som du kan se formateras datumen som månad / datum / år och numren är passerade, som det är. Detta gör acceptabelt:

Men notera att siffrorna är lite svåra att läsa utan att formatera. Låt oss börja med att lägga till någon formatering till numren.

Lägga till talformatering

Följande ändringar kan ses i app2.js och testas med test2.html. Först ändrar jag min kod för att ringa en ny funktion, Number:

$ Table.append ( "" + s [i] .date + "" + Number (s [i] .views) + "");

Och här är den funktionen:

funktionsnummerFormat (n) // cache formateraren en gång om (window.Intl &&! window.numberFormatter) window.numberFormatter = window.Intl.NumberFormat (); om (window.numberFormatter) return window.numberFormatter.format (n);  annars return n; 

Funktionen börjar med att kontrollera om Intl existerar som en del av fönster objekt. Om det gör så kontrollerar vi sedan om vi har gjort formateraren innan. De Intl objekt skapar ett formateringsobjekt som du kan återanvända, och eftersom vi formaterar en massa tal vill vi bara skapa den en gång. Det är precis vad vi gör så fort vi ser att vi behöver det också. Vi stör inte med några alternativ för nu, bara för att hålla det enkelt. Slutligen, om det inte fanns något stöd för Intl alls, vi returnerar bara numret som det är. Resultatet är en signifikant förbättring, med minimalt arbete:

Häftigt! Så, hur testar vi andra språk? Du kan bli frestad att kontrollera dina webbläsarinställningar. Alla webbläsare föredrar språk, men tyvärr ändrar språket i webbläsaren är inte tillräckligt. Ändra det gör påverkar hur webbläsaren beter sig. 

Om du öppnar dina dev-verktyg och tittar på nätverksförfrågningar kan du se att en rubrik som heter "Acceptera-Lanage"kommer att ändras baserat på dina inställningar. Om du lägger till franska, till exempel (jag antar att du inte är en fransk fransk talare) kommer du att se"fr"läggs till i denna rubrik. Men detta påverkar inte Intl. I stället måste du ändra ditt operativsystems språk och starta om webbläsaren. Detta är inte så läskigt som det låter. När jag testade var jag orolig att hela mitt operativsystem skulle ändras omedelbart. Men i mina test kunde jag ändra språket, starta om min webbläsare och se förändringen. Jag bytte mig snabbt tillbaka. Intl formateringsfunktionerna tillåter dig att överstyra det aktuella läget och skicka en i istället.

Jag modifierade programmet för att tillåta slutanvändaren att ange ett språk via en nedrullning. Här är ändringen gjord i HTML. (Denna ändring kan hittas i test3.html)

De språk jag valde var ganska godtyckliga. Nästa - Jag uppdaterade min programkod för att lyssna på ändringar i den här nedrullningen samt att kontrollera önskad plats när du formaterar.

Notering 3: app3.js:

funktionsnummerFormat (n) if (window.Intl) var lang = $ ("# langDropdown") .val (); om (lang === "") lang = navigator.language; var formatter = nytt fönster.Intl.NumberFormat (lang); returnera formatter.format (n);  annars return n;  funktion getStats () $ .getJSON ("stats.json"). gjort (funktion (er) // iterera över statistik och lägg till tabell för (var i = 0; i < s.length; i++)  $table.append(""+s[i].date+""+numberFormat(s[i].views)+"");  ).fail(function(e)  console.log("we failed"); console.dir(e); );  $(document).ready(function()  //get the table dom $table = $("#stats tbody"); //notice changes to drop down $("#langDropdown").on("change", function(e)  $table.empty(); getStats(); ); getStats(); ); 

Börja längst ner - notera att jag har lagt till en enkel händelsehanterare för ändringar i rullgardinsmenyn. När en förändring upptäcks tappas tabellen och funktionen getStats körs. Den här nya funktionen abstrakt bara AJAX-koden som användes tidigare. Den verkliga förändringen är nu i Number. Jag kontrollerar det valda språket och om en av dem valdes, skickar vi det som språk till Number konstruktör. Observera att om något inte valdes, standardiserar vi till navigator.language. Detta ger oss nu ett sätt att snabbt prova olika språk och se hur de gör nummer.

Lägg till datumformatering

Nu är det en perfekt tid att ta hand om den andra kolumnen av data - siffrorna. Jag följde samma stil som tidigare och lade till ett samtal till en ny funktion, datumformat.

$ Table.append ( "" + dateformat (s [i] .date) + "" + Number (s [i] .views) + "");

Och här är det datumformat (Du hittar koden i app4.js, som används av test4.html):

funktionsdatumFormat (n) // Används för datumvisning var opts = ; opts.day = "numeric"; opts.weekday = "long"; opts.year = "numeric"; opts.month = "long"; om (window.Intl) var lang = $ ("# langDropdown") .val (); om (lang === "") lang = navigator.language; var formatter = nytt fönster.Intl.DateTimeFormat (lang, ops); n = nytt datum (n); returnera formatter.format (n);  annars return n;  

Det här ligner mycket på nummerformatering, förutom den här gången överför vi uttryckligen vissa alternativ när vi skapar formateraren. Alternativen anger både vilka fält som är synliga i datumet, liksom hur de ser ut. Varje del av ett datum kan visas eller inte, och var och en har olika alternativ. Alternativen inkluderar:

  • veckodag
  • epok
  • år
  • månad
  • dag
  • timme
  • minut
  • andra
  • timeZoneName

För en fullständig lista över vilka värden du kan använda, se MDN-dokumentationen för DateTimeFormat, men som exempel kan månader visas som ett nummer eller i olika textformar. Så vad skapar detta? Här är den engelska versionen:

Och här är det på franska:

Du kanske undrar - vad täcker platsen för varje fält? Såvitt jag kan säga har du ingen kontroll över detta. Du kan självklart skapa flera formateringar och sedan kombinera dem ihop, men med en formaterare är fältets layout driven av intern logik. Om du stänger av månadens dag, till exempel, är här vad du får: april 2013 måndag. Varför? Ärligt talat har jag ingen aning.

Slutligen - notera att du måste skicka ett datumvärde, inte en sträng, till formateraren. Du kan se var jag använder datumkonstruktorn i formateraren för att analysera mitt strängbaserade datum. Detta är - lite lös - så kom ihåg detta när du använder den här funktionaliteten.

Visa mig pengarna

Valutaformatering är inte ett separat objekt, utan snarare en valfri användning av talformateraren. För nästa demonstration har vi skapat en ny datafil, stats2.json, och lagt till en "försäljning" kolumn till våra data. Här är ett urval:

 "Datum": "2013/04/01", "åsikter": 938213, "försäljning": 3890.21,  "datum": "2013/04/02", "åsikter": 238213, "försäljning": 9890,10 

Kolumnen läggs till i HTML-koden (test5.html), läggs till i JavaScript-iterering över raderna av data (se app5.js), och vidarebefordras till en ny funktion som heter currencyFormat. Låt oss titta på det.

funktionen valutaFormat (n) var opts = ; opts.style = "currency"; opts.currency = "USD"; om (window.Intl) var lang = $ ("# langDropdown") .val (); om (lang === "") lang = navigator.language; var formatter = nytt fönster.Intl.NumberFormat (lang, ops); returnera formatter.format (n);  annars return n;  

Visar nummer som valutor kräver två valfria värden. Först en stil av "valuta", och sedan valutatypen. Andra alternativ (som hur man visar namnet på valutan) finns också. Här kommer den del som kan leda till dig lite. Du måste Ange valutatypen. 

Du kanske tror - hur mår jag ihop valutatypen för alla möjliga värden? De möjliga värdena är baserade på en spec (http://www.currency-iso.org/en/home/tables/table-a1.html) och i teorin kan du analysera deras XML, men du vill inte göra det. Anledningen till var ganska uppenbar men jag kan ärligt säga att jag glömde i början också. Du vill inte bara visa ett visst nummer i en lokal valuta. Varför? Eftersom tio dollar amerikanska är säkert inte detsamma som tio dollar i pesos. Det är ganska uppenbart och förhoppningsvis är jag den enda personen att glömma det.

Med hjälp av koden ovan kan vi se följande resultat i franska locale. Observera hur siffrorna formateras rätt för lokalen och valutasymbolen placeras efter numret.

Sortering med Collator

För vårt slutliga exempel tittar vi på Collator konstruktör. Collators tillåter dig att hantera text sortering. Medan vissa språk följer ett enkelt A-Ö-ordersystem har andra språk olika regler. Och självklart blir sakerna ännu mer intressanta när du börjar lägga till accenter. Kan du säga, förvisso, om ä kommer efter en? Jag vet att jag inte kan. Kollatorkonstruktorn tar ett antal argument för att hjälpa till att ange exakt hur det ska sortera, men standard kommer troligen fungera bra för dig.

För det här exemplet har vi byggt en helt ny demo, men en som liknar de tidigare exemplen. I test6.html, du kan se ett nytt bord för studenter. Vår nya kod laddar upp ett JSON-paket av studenter och sorterar dem sedan på klienten. JSON-data är helt enkelt en mängd namn så jag hoppar över att visa ett utdrag. Låt oss titta på applikationslogiken.

Notering 4: app6.js:

funktion sorterare (x, y) if (window.Intl) var lang = $ ("# langDropdown") .val (); om (lang === "") lang = navigator.language; returnera window.Intl.Collator (lang) .compare (x, y);  annars returnera x.localeCompare (y);  funktion getStudents () $ .getJSON ("students.json"). gjort (funktion (er) // iterera över statistik och lägg till tabell s.sort (sorterare); för (var i = 0; i < s.length; i++)  $table.append(""+s[i]+"");  ).fail(function(e)  console.log("we failed"); console.dir(e); );  $(document).ready(function()  //get the table dom $table = $("#students tbody"); //notice changes to drop down $("#langDropdown").on("change", function(e)  $table.empty(); getStudents(); ); getStudents(); ); 

Som jag sa är den här koden ganska lik de tidigare exemplen, så fokuserad på getStudents först. Den avgörande linjen här är: s.sort (sorterare). Vi använder den inbyggda funktionen för att arrayer ska göra sortering via en anpassad funktion. Den funktionen ges två saker att jämföra och måste återvända -1, 0, eller 1 för att representera hur de två objekten ska sorteras. Nu ska vi titta på sorteraren.

Om vi ​​har en Intl objekt, vi skapar en ny Collator (och igen tillåter vi dig att passera i en lokal) och sedan kör vi jämföra fungera. Det är allt. Som jag sa finns det alternativ att ändra hur saker sorteras, men vi kan använda standardinställningarna. Fallbacken är localeCompare, som också kommer att försöka använda lokaliserad specifik formatering, men har (i denna form) något bättre stöd. Vi kan också kolla på det stödet och lägga till ytterligare en återgång för verkligen Bra stöd, men jag lämnar det för dig som en övning.

Vi har också ändrat framsidan för att använda svenska som språk. Det gjorde jag eftersom den utmärkta MDN-dokumentationen visade att det var ett bra sätt att se sorteringen i åtgärd. Här är den engelska sorten av våra studentnamn:

Och här är det på svenska:

Observera hur ätest sorteras annorlunda. (Tyvärr, jag kunde inte tänka på ett namn som började med ä.)

Sammanfatta

Sammantaget är det Intl klassen ger lite mycket Enkla sätt att lägga till lokaliserad specifik formatering till din kod. Det här är verkligen något du kan hitta nu, förmodligen i några tusen olika JavaScript-bibliotek, men det är fantastiskt att se webbläsarfabrikanterna som lägger till stöd direkt inom själva språket. Bristen på iOS-support är en bummer, men förhoppningsvis kommer den att läggas till snart.

Tack går till det utmärkta Mozilla Developer Network för sin stora Intl-dokumentation.