Werken met Intl

Internationalisering - iets waar je constant ontwikkelaars over hoort praten, maar zelden ziet dat mensen het in de praktijk gebruiken - krijgt een kick in de broek met de nieuwe ECMAScript Internationalization API. Momenteel ondersteund in Chrome 24, Chrome voor Android, Firefox 29, IE 11 en Opera 15 (helaas geen Safari-ondersteuning), biedt de nieuwe Intl-naamruimte een reeks functionaliteit om internationalisatie toe te voegen aan uw nummers, datums en sortering. In dit artikel zal ik de belangrijkste kenmerken van Intl demonstreren en u op weg helpen om ondersteuning te bieden voor de miljarden mensen op internet die buiten uw eigen land wonen!

Kernfuncties

De Intl-naamruimte omvat drie belangrijke functionaliteitgebieden:

  • Getallen opmaken
  • Datums opmaken
  • Sorteerstrings

Binnen elk van deze zijn verschillende opties voor het besturen van zowel de plaatsen die voor opmaak worden gebruikt als de opmaakopties. Als voorbeeld bevat de nummerformattering ondersteuning voor het verwerken van valuta. De datumnotator heeft opties voor welke delen van de datum moeten worden weergegeven.

Laten we een paar voorbeelden bekijken.

Onze applicatie

Onze eerste toepassing is een eenvoudige gegevensreporter. Het gebruikt AJAX om een ​​reeks gegevens met datums en getallen op te halen. Ten eerste de HTML:

Listing 1: test1.html:

          

Huidige statistieken

Datum bezoeken

Noteer de lege tabel. Dat is waar we onze gegevens zullen dumpen. Laten we nu eens kijken naar het JavaScript.

Listing 2: app1.js:

$ (document) .ready (function () // ontvang de tabel dom $ table = $ ("# stats tbody"); // haal nu onze data op uit de api, dat is nep btw $ .getJSON ("stats .json "). done (functie (s) // itereer over stats en voeg toe aan tabel voor (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); ); ); 

Alles wat de code hier doet, is om een ​​AJAX-aanroep naar een bestand te maken en het resultaat voor de gegevens weer te geven. Het gegevensbestand, stats.json, is gewoon een array van tien hard gecodeerde waarden. Hier is een deel van het bestand:

[ "Date": "2013/04/01", "views": 938.213,  "date": "2013/04/02", "views": 238.213, 

Zoals je kunt zien, zijn de datums opgemaakt als maand / datum / jaar en de nummers worden doorgegeven, zoals het is. Dit maakt acceptabel:

Maar let op dat de cijfers moeilijk te lezen zijn zonder opmaak. Laten we beginnen met het toevoegen van wat opmaak aan de cijfers.

Nummeropmaak toevoegen

De volgende wijzigingen zijn te zien in app2.js en getest met test2.html. Eerst zal ik mijn code aanpassen om een ​​nieuwe functie te bellen, nummer formaat:

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

En hier is die functie:

functie numberFormat (n) // cache de formatter eenmaal als (window.Intl &&! window.numberFormatter) window.numberFormatter = window.Intl.NumberFormat (); if (window.numberFormatter) return window.numberFormatter.format (n);  else retour n; 

De functie begint met het controleren of Intl bestaat als onderdeel van de venster voorwerp. Als dit het geval is, controleren we of we de formatter eerder hebben gemaakt. De Intl object maakt een opmaakobject dat u opnieuw kunt gebruiken en omdat we een aantal getallen opmaken, willen we het alleen één keer maken. Dat is precies wat we doen zodra we zien dat we dat ook nodig hebben. We doen voorlopig geen enkele moeite, alleen om het simpel te houden. Eindelijk, als er geen ondersteuning voor was Intl helemaal, we geven het nummer gewoon terug zoals het is. Het resultaat is een aanzienlijke verbetering, met minimaal werk:

Stoer! Dus, hoe testen we andere talen? U bent wellicht in de verleiding om uw browserinstellingen te controleren. Alle browsers hebben een voorkeur voor taal, maar helaas, ze veranderen de taal in de browser is niet genoeg. Het veranderen doet invloed hebben op hoe de browser zich gedraagt. 

Als u uw dev-hulpmiddelen opent en naar netwerkverzoeken kijkt, kunt u zien dat een kop genaamd "Accept-Lanage"zal veranderen op basis van uw instellingen. Als u bijvoorbeeld Frans toevoegt (ik neem aan dat u geen moedertaalspreker bent), ziet u"fr"toegevoegd aan deze header. Maar dit heeft geen impact Intl. In plaats daarvan moet u de taal van uw besturingssysteem wijzigen en de browser opnieuw opstarten. Dit is niet zo eng als het klinkt. Toen ik het testte, was ik bang dat mijn hele besturingssysteem onmiddellijk zou veranderen. Maar in mijn tests kon ik de taal wijzigen, mijn browser opnieuw starten en de wijziging bekijken. Ik veranderde snel terug. Met de Intl-formatteerfuncties kunt u de huidige locale overschrijven en er in plaats daarvan een doorgeven.

Ik heb de applicatie aangepast zodat de eindgebruiker via een drop-down een taal kan specificeren. Dit is de wijziging die in de HTML is aangebracht. (Deze aanpassing is te vinden in test3.html)

De talen die ik heb gekozen waren behoorlijk willekeurig. Volgende - Ik heb mijn applicatiecode bijgewerkt om te luisteren naar wijzigingen in deze vervolgkeuzelijst en om de gewenste locale te controleren bij het formatteren.

Listing 3: app3.js:

functie numberFormat (n) if (window.Intl) var lang = $ ("# langDropdown"). val (); if (lang === "") lang = navigator.language; var formatter = new window.Intl.NumberFormat (lang); return formatter.format (n);  else retour n;  functie getStats () $ .getJSON ("stats.json"). done (functie (s) // itereer over stats en voeg toe aan tabel voor (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(); ); 

Beginnend onderaan - merk op dat ik een eenvoudige gebeurtenishandler heb toegevoegd voor wijzigingen in de vervolgkeuzelijst. Wanneer een verandering wordt gedetecteerd, wordt de tabel leeggemaakt en de functie getStats wordt uitgevoerd. Deze nieuwe functie vat eenvoudig de eerder gebruikte AJAX-code samen. De echte verandering is nu aangebroken nummer formaat. Ik controleer de geselecteerde taal en als een van deze is gekozen, geven we die door als de locale voor de Nummer formaat constructeur. Merk op dat als iets niet is gekozen, we standaard naar navigator.language. Dit biedt ons nu een manier om snel verschillende locaties te testen en te zien hoe ze getallen weergeven.

Datumopmaak toevoegen

Het is nu een goed moment om voor de andere kolom met gegevens te zorgen - de cijfers. Ik volgde dezelfde stijl als voorheen en voegde een oproep toe aan een nieuwe functie, datumnotatie.

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

En hier is het datumnotatie (Je kunt de code vinden in app4.js, die wordt gebruikt door test4.html):

function dateFormat (n) // Gebruikt voor datumweergave var opts = ; opts.day = "numeriek"; opts.weekday = "lang"; opts.year = "numeriek"; opts.month = "lang"; if (window.Intl) var lang = $ ("# langDropdown"). val (); if (lang === "") lang = navigator.language; var formatter = new window.Intl.DateTimeFormat (lang, opts); n = nieuwe datum (n); return formatter.format (n);  else retour n;  

Dit is vergelijkbaar met nummeropmaak, behalve dat we deze keer expliciet enkele opties doorgeven wanneer we de formatter maken. De opties specificeren zowel welke velden zichtbaar zijn in de datum, als hoe ze eruitzien. Elk deel van een datum kan worden getoond of niet en elk heeft verschillende opties. De opties omvatten:

  • weekdag
  • tijdperk
  • jaar
  • maand
  • dag
  • uur
  • minuut
  • tweede
  • timeZoneName

Zie de MDN-documentatie voor een volledige lijst met de waarden die u kunt gebruiken DateTimeFormat, maar als voorbeeld kunnen maanden worden weergegeven als een nummer of in verschillende tekstuele vormen. Dus wat maakt dit? Hier is de Engelse versie:

En hier is het in het Frans:

U vraagt ​​zich misschien af: wat dekt de locatie van elk veld af? Voor zover ik weet, heb je hier geen controle over. U kunt natuurlijk meerdere formatteerbewerkingen maken en deze vervolgens combineren, maar met behulp van een formatter wordt de lay-out van de velden bepaald door interne logica. Als u bijvoorbeeld de dag van de maand uitschakelt, ziet u hier wat u krijgt: april 2013 maandag. Waarom? Eerlijk gezegd heb ik geen idee.

Tot slot - merk op dat u een datumwaarde, niet een string, aan de formatter moet doorgeven. U kunt zien waar ik de datumconstructor in de formatter gebruik om mijn tekenreeksdatum te ontleden. Dit is - een beetje los - dus houd hier rekening mee wanneer u deze functionaliteit gebruikt.

Toon me het geld

Valutanotering is geen afzonderlijk object, maar eerder een optioneel gebruik van de nummerformattering. Voor de volgende demo hebben we een nieuw gegevensbestand gemaakt, stats2.json, en een kolom 'Verkoop' aan onze gegevens toegevoegd. Hier is een voorbeeld:

 "Date": "2013/04/01", "views": 938.213, "sales": 3890,21,  "date": "2013/04/02", "views": 238.213, "sales": 9.890,10 

De kolom is toegevoegd aan de HTML (test5.html), toegevoegd in de JavaScript-iteratie over de rijen met gegevens (zie app5.js), en doorgegeven aan een nieuwe functie genaamd currencyFormat. Laten we daar eens naar kijken.

function currencyFormat (n) var opts = ; opts.style = "valuta"; opts.currency = "USD"; if (window.Intl) var lang = $ ("# langDropdown"). val (); if (lang === "") lang = navigator.language; var formatter = new window.Intl.NumberFormat (lang, opts); return formatter.format (n);  else retour n;  

Voor het weergeven van getallen als valuta zijn twee optionele waarden vereist. Eerst een stijl van 'valuta' en vervolgens het valutatype. Andere opties (zoals het weergeven van de naam van de valuta) bestaan ​​ook. Hier komt het deel dat je een beetje kan doen struikelen. U moet geef het valutatype op. 

U denkt misschien: hoe begrijp ik in hemelsnaam het valutatype voor alle mogelijke waarden? De mogelijke waarden zijn gebaseerd op een spec (http://www.currency-iso.org/en/home/tables/table-a1.html) en in theorie zou je hun XML kunnen ontleden, maar dat wil je niet doen. De reden is vrij duidelijk, maar ik kan eerlijk zeggen dat ik het aanvankelijk ook ben vergeten. U wilt niet alleen een bepaald nummer opnieuw weergeven in een landspecifieke valuta. Waarom? Omdat tien dollar Amerikaans zeker is niet hetzelfde als tien dollar in peso's. Dat is vrij duidelijk en hopelijk ben ik de enige persoon die dat vergeet.

Met behulp van de bovenstaande code kunnen we de volgende resultaten zien in de Franse locale. Merk op hoe de getallen juist voor de locale worden opgemaakt en het valutasymbool achter het nummer wordt geplaatst.

Sorteren met Collator

Voor ons laatste voorbeeld zullen we kijken naar de collator constructeur. Met Collators kunt u tekst sorteren. Hoewel sommige talen een eenvoudig A tot Z bestelsysteem volgen, hebben andere talen verschillende regels. En natuurlijk wordt het nog interessanter als je accenten begint toe te voegen. Kun je, met zekerheid, zeggen als je achter een? Ik weet dat ik het niet kan. De verzamelprogramma-constructor neemt een aantal argumenten mee om precies te specificeren hoe deze moet worden gesorteerd, maar de standaard zal waarschijnlijk goed voor u werken.

Voor dit voorbeeld hebben we een geheel nieuwe demo gebouwd, maar een die vergelijkbaar is met de vorige voorbeelden. In test6.html, je kunt een nieuwe tabel zien, voor studenten. Onze nieuwe code laadt een JSON-pakket met studenten op en sorteert ze vervolgens op de client. De JSON-gegevens zijn gewoon een reeks namen, dus ik sla een fragment over. Laten we naar de applicatielogica kijken.

Listing 4: app6.js:

functie sorter (x, y) if (window.Intl) var lang = $ ("# langDropdown"). val (); if (lang === "") lang = navigator.language; return window.Intl.Collator (lang) .compare (x, y);  else return x.localeCompare (y);  functie getStudents () $ .getJSON ("students.json"). done (functie (s) // itereer over stats en voeg toe aan tabel s.sort (sorter); for (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(); ); 

Zoals ik al zei, deze code lijkt veel op de vorige voorbeelden, dus focus op getStudents eerste. De cruciale lijn hier is: s.sort (sorter). We gebruiken de ingebouwde functie voor arrays om te sorteren via een aangepaste functie. Die functie krijgt twee dingen doorgegeven om te vergelijken en moet terugkeren -1, 0, of 1 om aan te geven hoe de twee items moeten worden gesorteerd. Laten we nu eens kijken naar sorter.

Als we een hebben Intl object maken we een nieuw collator (en nogmaals, we laten je toe om in een locale door te geven) en dan starten we de vergelijken functie. Dat is het. Zoals ik al zei, zijn er opties om de manier waarop dingen worden gesorteerd aan te passen, maar we kunnen de standaardinstellingen gebruiken. De fallback is localeCompare, die ook zal proberen om locale specifieke opmaak te gebruiken, maar heeft (in deze vorm) iets betere ondersteuning. We kunnen ook naar die ondersteuning kijken en er nog een fallback voor toevoegen werkelijk goede ondersteuning, maar ik laat dat voor je achter, als een oefening.

We hebben ook de voorkant aangepast om Zweeds als taal te gebruiken. Ik deed dit omdat de uitstekende MDN-documentatie aantoonde dat het een goede manier was om het sorteren in actie te zien. Dit is het Engelse soort van onze studentennamen:

En hier is het in het Zweeds:

Merk op dat ätest anders is gesorteerd. (Sorry, ik kon geen naam bedenken die met ä begon.)

Afronden

Al met al, de Intl klasse biedt een aantal heel eenvoudige manieren om locale specifieke opmaak toe te voegen aan uw code. Dit is zeker iets dat je nu kunt vinden, waarschijnlijk in een paar duizend verschillende JavaScript-bibliotheken, maar het is geweldig om te zien dat de browserfabrikanten ondersteuning toevoegen in de taal zelf. Het gebrek aan iOS-ondersteuning is een spelbreker, maar hopelijk zal het binnenkort worden toegevoegd.

Bedankt aan het uitstekende Mozilla Developer Network voor zijn geweldige Intl-documentatie.