meertalig
Ik vond al iets hier: http://stackoverflow.com/questions/3084675/how-does-internationalization-work-in-javascript dat naar een API verwijst op http://ecma-international.org/ecma-402/1.0/ waar je voor IE10 weer iets speciaals moet doen met https://github.com/andyearnshaw/Intl.js
Hoe verhoudt dit zich tot PHP's intl-extentie? Kan je beide door elkaar gebruiken?
Wat wil je precies meertalig maken?
Datumberekeningen (conflicten ed.) zullen voornamelijk op database-niveau moeten plaatsvinden, dat werkt het snelst. Dus gewoon in het native format met DATETIME velden. Maar de ondersteuning voor locales in de database is niet zo uitgebreid, het enige dat ik heb gevonden is dat de database (MariaDB/MySQL) dag en maandnamen omzet, en al het andere mag je zelf doen met formatting.
Ik heb gekeken naar de intl-extentie in PHP, en die is ideaal voor gebruik in PHP. Echter, als je een formulier met datumwidget hebt, of een kalender, dan wil je niet voor elk wissewasje een AJAX-call maken van soms 0.5s of meer naar de backend. Ofwel, als ik in JavaScript wil gaan rekenen met datums, dan is het handig als de vertaalslag van Engels naar Nederlands meteen in JavaScript kan.
Dan komt mijn vraag: wat is handig om te doen? Er is een Internationalization API in JavaScript, maar niet voor IE10 wat mijn klanten ook gebruiken. Wat kan je aan de browser overlaten? Welke dingen wil je toch via PHP laten doen?
Het idee dat ik op het moment heb, is dat je zo min mogelijk aan JS wilt overlaten om browserafhankelijkheid te omzeilen. Een inputwidget moet de ruwe datum bevatten, met een versie die via HTML-elementen getoond wordt in de browser, locale-bewust. En een tekstelement met de printversie van de datum, zodat het goed wordt afgedrukt, zonder de controls.
Uiteraard ben ik niet de enige die een dergelijk probleem heeft, dus vraag ik me af wat de ervaring is van anderen, wat is aan te raden?
Je hebt maar 7 dagnamen, 12 maandnamen en 4 datumnotaties, namelijk de korte en de lange in respectievelijk Nederlands en Engels. En zelfs dat niet als je een maandkalender-widget gebruikt: dan hoef je alleen de maandnamen te lokaliseren. Daarvoor zou ik geen karrenvracht aan JavaScript API laden die niet eens compatibel is met alle clients. Ik zou zelfs php_intl dan links laten liggen. Allebei overkill. Met een handvol arrays en wat functies kom je er ook.
Wat als er straks ook Frans en Duits en Spaans bij komt, of als er een vestiging in Hongkong opent? Of als ik het kalenderobject wil hergebruiken in anderstalige applicaties?
Het fijne van intl lijkt mij juist dat alles al is uitgezocht, dat alle namen goed staan, alle lengten van perioden, sorteringen en nummerformattering van monetaire eenheden, alles van veel talen/culturen.
Eenmaal uitgeschreven hoef je het alleen nog te configureren, evt. via autodetectie. Die tijdsinvestering is geen probleem.
En ik ga er blind van uit dat het sneller werkt dan het in mijn ogen erg trage DateTime-object van PHP, omdat er bij ICU erg gelet wordt op performance, zelfs in de C-implementatie.
Ik ga er zowieso mee aan de slag, misschien kom ik nog op andere gedachten bij gebruik van intl.
Qua JavaScript ben ik er nog niet uit of de internationalization API of compatibility-library voor IE10 en ouder vergelijkbare functies heeft en een beetje aansluit op PHP's intl extentie.
Ter vergelijk met PHP: intl past bijvoorbeeld moeizaam op PHP's date() functie omdat de interne verwerking van datums met intl via 64-bit signed integers gaat, en als ik het aantal microseconden (UNIX-timestamp) voer aan date(), dan gaat het goed fout. Moet het toch misschien via DateTime oid.
Voor al dat soort details vraag ik me af wie kan vertellen wat handige combinaties zijn met JavaScript, ook omdat de hele internationalization API relatief nieuw is in browserland.
Het alternatief is dat ik JavaScript niet laat nadenken over datums en berekeningen, maar dat ik het denkwerk voorbereid met intl en dat via arrays aan JavaScript geef voor widgets ed.
Wat bedoel je precies?
dan kun je daar een schil omheen bouwen die naar de gebruiker in een mooi formaat de datum toont.
Dat kan bijvoorbeeld door
$date = new DateTime("2015-12-31 23:44");
en dan
met echo $date->format('een leuk formaat')
als het nodig is om te achterhalen op welk vakje van de kalender de gebruiker klikt: zorg dan dat zo'n vakje iets heeft als <span data-datum="2015-12-31">...</span>
dus in een fixed formaat. Ziet de gebruiker toch niet.
Moet de gebruiker een datum invoeren: liefst met een of andere widget zorgen dan de invoer "22-04-2016" direct omgaat naar "2016-04-22"
Dan hoef je alleen maar bij de ->format() te zorgen voor een custom formaat en bij de widget
Uit ervaring kan ik je vertellen dat het tof lijkt om op alles voorbereid te zijn maar dat het in werkelijk juist meer tijd kost om dingen te implementeren dan wel te onderhouden. Dan kan je beter een keer zeggen van; We gaan nu refactoren.
Momenteel heb je Nederlands en Engels nodig. Dan maak je daar nu iets voor.
Persoonlijk zou ik iets bestaand pakken (om af te kijken) zoals de datepicker van Bootstrap.
An tje op 22/04/2016 15:31:00:
Wat als er straks ook Frans en Duits en Spaans bij komt, of als er een vestiging in Hongkong opent? Of als ik het kalenderobject wil hergebruiken in anderstalige applicaties?
Met een "wat als" kun je de boel enorm complex maken. Elke invulling van een "wat als" verlengt de ontwikkeltijd, verhoogt de ontwikkelkosten en vergroot de kans op bugs.
Wat als je talen moet ondersteunen die van rechts naar links worden gelezen, zoals Arabisch? Wat als je de Chinese jaartelling moet ondersteunen? Wat als je voor historische doeleinden een paar miljoen jaar voor Christus moet weergeven? Wat als het 2038 wordt? Wat als …
Als je voor je kalender nog meer moet vertalen dan alleen de dagen en maanden dan kan het er net zo makkelijk in mee. De intl extensie is lang niet op iedere HOST geïnstalleerd en dus maak je je website weer afhankelijk van een "niet zo standaard configuratie". Of je bouwt zoals ward al aangaf eenmalig een eigen date-class die de belangrijkste talen ondersteund. Dan kun je waarschijnlijk de rest van je leven hiermee vooruit. Alleen als je echt een tool wilt bouwen waarvan je verwacht dat je gebruikers van over de hele wereld zullen komen en het gaat enkel om de weken en maanden (wat ik me al niet voor kan stellen) dan zou ik intl overwegen.
Mijn applicatie wil ik toekomstbestendig maken. Zo kan ik me nog erg goed herinneren hoe ik een poosje geleden zat te klooien om de applicatie uit het slijk van Latin1 te halen en Unicode te maken, zodat in ieder geval Microsoft Word-documenten goed konden worden ingelezen. Het was een lange refactor-klus, met een tut tot gevolg: https://www.phphulp.nl/php/tutorial/php-algemeen/unicode-enzo/831/
Met terugwerkende kracht kan ik zeggen dat het handiger was om de applicatie van meet af aan Unicode te schrijven, dat had een hoop gedoe met nutteloze transcoding tussen front- en backend bespaard.
De keuze voor intl is een logische keuze. Wanneer personeel vanaf een andere plaats (tijdzone) werkt, of in de eigen taal (soms Arabisch idd.), of wanneer het product vermarkt wordt naar bedrijven met eigen locales, dan zou het fijn zijn als de applicatie, inclusief de kalender, dat gewoon alvast ondersteunt. Te meer omdat bedrijven een voorkeur hebben voor web-enabled front-ends, om deployment op clients te besparen, is intl een goede investering. Sterker, als ik voor mijn Unicode-exercitie van het bestaan van intl had geweten, had ik niet in mijn tutorial aangeraden om zoveel mogelijk in de database te doen, en de mb_*-functies te vermijden. In plaats daarvan had ik meteen intl aangeraden. Ondersteuning voor locales in MySQL/MariaDB lijkt mij beduidend minder dan de mogelijkheden van intl. Ik ben het daarom eens met Ivo om de database in haar native format te laten en een schil met intl te maken.
Misschien dat wanneer ik een overstap naar PostgreSQL kan maken, dat ik deze keuze moet heroverwegen, momenteel heb ik die keuze niet.
Tot zover de verdediging van mijn keuze voor intl, zonder direct mee te gaan in de typische reflex op phphulp.nl om de vragensteller op andere gedachten te brengen. :-)
Ik ben nu bezig met het oriënteren voor de planningsmodule om te kijken wat handig is. intl is het probleem niet, de library is iets meer dan 100k, en de code is goed te begrijpen: https://www.phphulp.nl/php/forum/topic/dagen-/99808/
Wanneer ik een kalender teken op het scherm voor meerdere mensen tegelijkertijd, vergelijkbaar met een kalender van Outlook, dan kan ik daarvoor eenvoudig geparametriseerde JavaScript code gebruiken met variabelen van intl, om de load van een XHR-verzoek zo licht mogelijk te houden.
Echter, als iemand een willekeurige datum invult en ik zou bijvoorbeeld willen berekenen of dat een geldige datum is, wat de dag van het jaar is ed., dan zie ik nog niet voor me hoe dat gemakkelijk in JavaScript (van IE10) zou kunnen op een manier die compatible is met intl, zonder extra XHR-verzoek. Misschien is dat niet heel erg, want met een extra XHR-verzoek kan ik controleren op conflicten en aanvullende informatie ophalen, maar ik zou het niet voor elke situatie willen. Bijvoorbeeld met een widget in een normaal formulier.
Zo kom ik op mijn oorspronkelijke vraag van dit topic, namelijk wat de mogelijkheden zijn van JavaScript en of ik met geparametriseerde JavaScript-code op de goede weg zit, ondanks het bestaan van de Internationalization API en intl.js. Het zou fijn zijn om hierover terugkoppeling te krijgen, want het is goed mogelijk dat het nog jaren duurt eer de IT-organisatie over zal gaan op IE11 of Edge.
Nu het ineens angstvallig stil blijft, ga ik er vanuit dat geparametriseerde Javascript de beste manier is om met meertalige widgets en een kalender om te gaan. (Als niemand een betere oplossing weet, mag ik er vanuitgaan dat mijn oplossing niet gek is.. :-)
Het enige wat je nodig hebt is een taal-specifieke "datum string" waarin je de dag-, maand- en jaarvakjes (en wat je nog meer wilt) vult met informatie.
Omrekenen naar een andere/de eigen tijdszone is een apart probleem en kan dus in afzondering opgelost worden (separation of concerns). Dit kan ook direct in PHP via je <favoriete datetime lib>.
Wellicht is dit een oversimplificatie, maar dan begrijp ik ook niet echt wat het probleem is of waar het schip precies strandt :).
Het toevoegen van een taal (wat datums betreft dan) is dan niet meer dan het toevoegen van de "datum strings" voor die taal.
Gewijzigd op 27/04/2016 16:05:59 door Thomas van den Heuvel
Aanpassen van namen van dagen en maanden is slechts een klein onderdeel van het probleem, want in verschillende culturen zijn er onder meer:
- andere talen met andere karakters
- in een andere leesrichting,
- met andere sorteringen
- met andere kalenders dan de gregoriaanse (ander aantal maanden per jaar en dagen per maand)
Om dit alles soepel te laten samenwerken bevat de International Components for Unicode of ICU tooling welke wordt gebruikt door alle grote spelers, zie: http://site.icu-project.org.
We kunnen hier in PHP dankbaar gebruik van maken via de intl-extentie: http://php.net/manual/en/book.intl.php
Nu wil ik in mijn AJAX-applicatie straks een kalender hebben waarin de eindgebruiker activiteiten kan plannen. Of ik heb een datum-widget waarin de eindgebruiker zijn datum kan opgeven. De eindgebruiker tikt dan bijvoorbeeld de datum in, in zijn taal. En ik zou dat dan graag client-side willen controleren, ook op collisions in de al geladen kalender-data, zodat ik niet bij elke muisklik of toetsaanslag een XHR-verzoek naar de server hoef te sturen.
- Hoe kan je dat doen met het JavaScript van Internet Explorer 10, waar de Internationalization API nog niet wordt ondersteund?
- Hoe past die data op intl? Gaat dat goed met de 64-bit integers die intl onderhuids gebruikt?
Ik zou graag feedback willen over hoe anderen dit probleem oplossen, dus niet alleen namen van dagen/maanden.