Merge branch '2.3' into 2.5

* 2.3:
  [Doc] Use Markdown syntax highlighting
  [Finder] tweaked docs
  [Finder] Add info about possibilities offered by SplFileInfo
  fix components tests
  [Intl] FIxed failing test
  [Intl] Generated the data for ICU version 54-rc
  [EventDispatcher] fix doc bloc on EventDispatcherInterface
  [Validator] Update validators.zh_CN.xlf, fix translation error
  bumped Symfony version to 2.3.21
  updated VERSION for 2.3.20
  update CONTRIBUTORS for 2.3.20
  updated CHANGELOG for 2.3.20
  [Intl] Integrated ICU data into Intl component

Conflicts:
	src/Symfony/Component/HttpKernel/Kernel.php
	src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php
This commit is contained in:
Fabien Potencier 2014-10-01 07:50:18 +02:00
commit cfd1ecfe84
1085 changed files with 247752 additions and 2914 deletions

View File

@ -35,6 +35,6 @@ install:
- sh -c 'if [ "$components" = "no" ]; then sh -c "COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev install"; fi;'
script:
- sh -c 'if [ "$components" = "no" ]; then sh -c "ls -d src/Symfony/*/* | parallel --gnu --keep-order '\''echo \"Running {} tests\"; phpunit --exclude-group tty,benchmark {};'\''"; fi;'
- sh -c 'if [ "$components" = "no" ]; then sh -c "ls -d src/Symfony/*/* | parallel --gnu --keep-order '\''echo \"Running {} tests\"; phpunit --exclude-group tty,benchmark,intl-data {};'\''"; fi;'
- sh -c 'if [ "$components" = "no" ]; then sh -c "echo "\""Running tests requiring tty"\""; phpunit --group tty"; fi;'
- sh -c 'if [ "$components" = "yes" ]; then sh -c "find src/Symfony -mindepth 3 -type f -name '\''phpunit.xml.dist'\'' | sed '\''s#\(.*\)/.*#\1#'\'' | parallel --gnu --keep-order '\''echo \"Running {} tests\"; cd {}; COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev install; phpunit --exclude-group tty,benchmark;'\''"; fi;'
- sh -c 'if [ "$components" = "yes" ]; then sh -c "find src/Symfony -mindepth 3 -type f -name '\''phpunit.xml.dist'\'' | sed '\''s#\(.*\)/.*#\1#'\'' | parallel --gnu --keep-order '\''echo \"Running {} tests\"; cd {}; COMPOSER_ROOT_VERSION=dev-master composer --prefer-source --dev install; phpunit --exclude-group tty,benchmark,intl-data;'\''"; fi;'

View File

@ -7,6 +7,37 @@ in 2.3 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.3.0...v2.3.1
* 2.3.20 (2014-09-28)
* bug #9453 [Form][DateTime] Propagate invalid_message & invalid_message_parameters to date & time (egeloen)
* bug #11058 [Security] bug #10242 Missing checkPreAuth from RememberMeAuthenticationProvider (glutamatt)
* bug #12004 [Form] Fixed ValidatorTypeGuesser to guess properties without constraints not to be required (webmozart)
* bug #11904 Make twig ExceptionController conformed with ExceptionListener (megazoll)
* bug #11924 [Form] Moved POST_MAX_SIZE validation from FormValidator to request handler (rpg600, webmozart)
* bug #11079 Response::isNotModified returns true when If-Modified-Since is later than Last-Modified (skolodyazhnyy)
* bug #11989 [Finder][Urgent] Remove asterisk and question mark from folder name in test to prevent windows file system issues. (Adam)
* bug #11908 [Translation] [Config] Clear libxml errors after parsing xliff file (pulzarraider)
* bug #11937 [HttpKernel] Make sure HttpCache is a trusted proxy (thewilkybarkid)
* bug #11970 [Finder] Escape location for regex searches (ymc-dabe)
* bug #11837 Use getPathname() instead of string casting to get BinaryFileReponse file path (nervo)
* bug #11513 [Translation] made XliffFileDumper support CDATA sections. (hhamon)
* bug #11907 [Intl] Improved bundle reader implementations (webmozart)
* bug #11874 [Console] guarded against non-traversable aliases (thierrymarianne)
* bug #11799 [YAML] fix handling of empty sequence items (xabbuh)
* bug #11906 [Intl] Fixed a few bugs in TextBundleWriter (webmozart)
* bug #11459 [Form][Validator] All index items after children are to be considered grand-children when resolving ViolationPath (Andrew Moore)
* bug #11715 [Form] FormBuilder::getIterator() now deals with resolved children (issei-m)
* bug #11892 [SwiftmailerBridge] Bump allowed versions of swiftmailer (ymc-dabe)
* bug #11918 [DependencyInjection] remove `service` parameter type from XSD (xabbuh)
* bug #11905 [Intl] Removed non-working $fallback argument from ArrayAccessibleResourceBundle (webmozart)
* bug #11497 Use separated function to resolve command and related arguments (JJK801)
* bug #11374 [DI] Added safeguards against invalid config in the YamlFileLoader (stof)
* bug #11897 [FrameworkBundle] Remove invalid markup (flack)
* bug #11860 [Security] Fix usage of unexistent method in DoctrineAclCache. (mauchede)
* bug #11850 [YAML] properly mask escape sequences in quoted strings (xabbuh)
* bug #11856 [FrameworkBundle] backport more error information from 2.6 to 2.3 (xabbuh)
* bug #11843 [Yaml] improve error message when detecting unquoted asterisks (xabbuh)
* 2.3.19 (2014-09-03)
* security #11832 CVE-2014-6072 (fabpot)

View File

@ -26,22 +26,22 @@ Symfony2 is the result of the work of many people who made the code better
- Hugo Hamon (hhamon)
- Martin Hasoň (hason)
- Eriksen Costa (eriksencosta)
- Nicolas Grekas (nicolas-grekas)
- Jonathan Wage (jwage)
- Grégoire Pineau (lyrixx)
- Alexandre Salomé (alexandresalome)
- William Durand (couac)
- ornicar
- stealth35 (stealth35)
- Grégoire Pineau (lyrixx)
- Alexander Mols (asm89)
- Christian Flothmann (xabbuh)
- Bulat Shakirzyanov (avalanche123)
- Nicolas Grekas (nicolas-grekas)
- Francis Besset (francisbesset)
- Saša Stamenković (umpirsky)
- Miha Vrhovnik
- Henrik Bjørnskov (henrikbjorn)
- Konstantin Kudryashov (everzet)
- Wouter De Jong (wouterj)
- Christian Flothmann (xabbuh)
- Bilal Amarni (bamarni)
- Florin Patan (florinpatan)
- Eric Clemmons (ericclemmons)
@ -56,28 +56,29 @@ Symfony2 is the result of the work of many people who made the code better
- Brandon Turner
- Douglas Greenshields (shieldo)
- Daniel Holmes (dholmes)
- Bart van den Burg (burgov)
- Jordan Alliot (jalliot)
- John Wards (johnwards)
- Fran Moreno (franmomu)
- Bart van den Burg (burgov)
- Antoine Hérault (herzult)
- Toni Uebernickel (havvg)
- Luis Cordova (cordoval)
- Arnaud Le Blanc (arnaud-lb)
- Tim Nagel (merk)
- Kevin Bond (kbond)
- Tim Nagel (merk)
- Ait Boudad Abdellatif (aitboudad)
- Brice BERNARD (brikou)
- marc.weistroff
- lenar
- Włodzimierz Gajda (gajdaw)
- Colin Frei
- excelwebzone
- Florian Voutzinos (florianv)
- Fabien Pennequin (fabienpennequin)
- Jacob Dreesen (jdreesen)
- Florian Voutzinos (florianv)
- Adrien Brault (adrienbrault)
- Fabien Pennequin (fabienpennequin)
- Jérôme Tamarelle (gromnan)
- Gábor Egyed (1ed)
- Ait Boudad Abdellatif (aitboudad)
- Michal Piotrowski (eventhorizon)
- Gordon Franke (gimler)
- Robert Schönthal (digitalkaoz)
@ -90,11 +91,11 @@ Symfony2 is the result of the work of many people who made the code better
- Pablo Godel (pgodel)
- Jérémie Augustin (jaugustin)
- Rafael Dohms (rdohms)
- Jérôme Tamarelle (gromnan)
- Eric GELOEN (gelo)
- Tigran Azatyan (tigranazatyan)
- Javier Eguiluz (javier.eguiluz)
- Richard Shank (iampersistent)
- Eric GELOEN (gelo)
- Clemens Tolboom
- Helmer Aaviksoo
- Sebastiaan Stok (sstok)
- Hiromi Hishida (77web)
@ -104,7 +105,9 @@ Symfony2 is the result of the work of many people who made the code better
- Jonathan Ingram (jonathaningram)
- Artur Kotyrba
- Guilherme Blanco (guilhermeblanco)
- Clemens Tolboom
- Rouven Weßling (realityking)
- Jérémy DERUSSÉ (jderusse)
- Stefano Sala (stefano.sala)
- Dmitrii Chekaliuk (lazyhammer)
- Clément JOBEILI (dator)
- Dorian Villet (gnutix)
@ -112,9 +115,7 @@ Symfony2 is the result of the work of many people who made the code better
- Arnaud Kleinpeter (nanocom)
- Mario A. Alvarez Garcia (nomack84)
- Dennis Benkert (denderello)
- Rouven Weßling (realityking)
- Benjamin Dulau (dbenjamin)
- Stefano Sala (stefano.sala)
- Andreas Hucks (meandmymonkey)
- Andréia Bohner (andreia)
- Noel Guilbert (noel)
@ -128,6 +129,7 @@ Symfony2 is the result of the work of many people who made the code better
- Pierre Minnieur (pminnieur)
- fivestar
- Dominique Bongiraud
- Kévin Dunglas (dunglas)
- Leszek Prabucki (l3l0)
- François Zaninotto (fzaninotto)
- Dustin Whittle (dustinwhittle)
@ -141,12 +143,14 @@ Symfony2 is the result of the work of many people who made the code better
- Tugdual Saunier (tucksaun)
- Sergey Linnik (linniksa)
- Marcel Beerta (mazen)
- hacfi (hifi)
- Francois Zaninotto
- Alexander Kotynia (olden)
- Daniel Tschinder
- Elnur Abdurrakhimov (elnur)
- Manuel Reinhard (sprain)
- Danny Berger (dpb587)
- Roman Marintšenko (inori)
- Xavier Montaña Carreras (xmontana)
- Michele Orselli (orso)
- Xavier Perez
@ -159,6 +163,7 @@ Symfony2 is the result of the work of many people who made the code better
- Joseph Rouff (rouffj)
- Félix Labrecque (woodspire)
- GordonsLondon
- Issei Murasawa (issei_m)
- Jan Sorgalla (jsor)
- Ray
- Chekote
@ -166,6 +171,7 @@ Symfony2 is the result of the work of many people who made the code better
- Albert Casademont (acasademont)
- jdhoek
- Wodor Wodorski
- julien pauli (jpauli)
- Beau Simensen (simensen)
- Robert Kiss (kepten)
- Kim Hemsø Rasmussen (kimhemsoe)
@ -174,12 +180,11 @@ Symfony2 is the result of the work of many people who made the code better
- Peter Kruithof (pkruithof)
- Michael Holm (hollo)
- Marc Weistroff (futurecat)
- Roman Marintšenko (inori)
- Chris Smith (cs278)
- Florian Klein (docteurklein)
- Manuel Kiessling (manuelkiessling)
- Atsuhiro KUBO (iteman)
- Issei Murasawa (issei_m)
- Andrew Moore (finewolf)
- Bertrand Zuchuat (garfield-fr)
- Gabor Toth (tgabi333)
- realmfoo
@ -201,8 +206,6 @@ Symfony2 is the result of the work of many people who made the code better
- janschoenherr
- Marco Pivetta (ocramius)
- Ricard Clau (ricardclau)
- Jérémy DERUSSÉ (jderusse)
- Kévin Dunglas (dunglas)
- Erin Millard
- Matthew Lewinski (lewinski)
- alquerci
@ -218,6 +221,7 @@ Symfony2 is the result of the work of many people who made the code better
- Kristen Gilden (kgilden)
- Robbert Klarenbeek (robbertkl)
- hossein zolfi (ocean)
- Clément Gautier (clementgautier)
- Eduardo Gulias (egulias)
- giulio de donato (liuggio)
- Stéphane PY (steph_py)
@ -225,17 +229,17 @@ Symfony2 is the result of the work of many people who made the code better
- Kirill chEbba Chebunin (chebba)
- Greg Thornton (xdissent)
- Grégoire Paris (greg0ire)
- julien pauli (jpauli)
- Chris Wilkinson (thewilkybarkid)
- Costin Bereveanu (schniper)
- Loïc Chardonnet (gnusat)
- Marek Kalnik (marekkalnik)
- Andrew Moore (finewolf)
- Vyacheslav Salakhutdinov (megazoll)
- Tamas Szijarto
- Pavel Volokitin (pvolok)
- Endre Fejes
- Tobias Naumann (tna)
- Ismael Ambrosi (iambrosi)
- Shein Alexey
- hacfi (hifi)
- Joe Lencioni
- Kai
- Xavier HAUSHERR
@ -255,7 +259,9 @@ Symfony2 is the result of the work of many people who made the code better
- Michel Salib (michelsalib)
- geoffrey
- Nikita Konstantinov
- Matthieu Auger (matthieuauger)
- Jeanmonod David (jeanmonod)
- Iltar van der Berg
- Jan Schumann
- Niklas Fiekas
- John Kary (johnkary)
@ -280,7 +286,6 @@ Symfony2 is the result of the work of many people who made the code better
- François-Xavier de Guillebon (de-gui_f)
- boombatower
- Fabrice Bernhard (fabriceb)
- Clément Gautier (clementgautier)
- Fabian Lange (codingfabian)
- Yoshio HANAWA
- Baptiste Clavié (talus)
@ -294,7 +299,6 @@ Symfony2 is the result of the work of many people who made the code better
- Iker Ibarguren (ikerib)
- Ricardo Oliveira (ricardolotr)
- ondrowan
- Vyacheslav Salakhutdinov (megazoll)
- Daniel Wehner
- Evan S Kaufman (evanskaufman)
- mcben
@ -302,7 +306,6 @@ Symfony2 is the result of the work of many people who made the code better
- mmoreram
- Markus Lanthaler (lanthaler)
- Vicent Soria Durá (vicentgodella)
- Chris Wilkinson (thewilkybarkid)
- Ioan Negulescu
- Jakub Škvára (jskvara)
- Andrew Udvare (audvare)
@ -316,6 +319,7 @@ Symfony2 is the result of the work of many people who made the code better
- Gábor Fási
- Benjamin Leveque (benji07)
- sasezaki
- Florian Rey (nervo)
- Denis Gorbachev (starfall)
- Steven Surowiec
- Daniel Tschinder
@ -349,11 +353,13 @@ Symfony2 is the result of the work of many people who made the code better
- Konstantin Myakshin (koc)
- Nahuel Cuesta (ncuesta)
- Chris Boden (cboden)
- Asmir Mustafic (goetas)
- Pierre du Plessis (pierredup)
- Josip Kruslin
- Hany el-Kerdany
- Wang Jingyu
- Åsmund Garfors
- Maxime Douailin
- Javier López (loalf)
- Dustin Dobervich (dustin10)
- Alexander M. Turek (derrabus)
@ -366,9 +372,11 @@ Symfony2 is the result of the work of many people who made the code better
- Vincent Simonin
- Christian Schmidt
- Stefan Warman
- Tristan Maindron (tmaindron)
- Ke WANG (yktd26)
- Jakub Kucharovic
- Miquel Rodríguez Telep (mrtorrent)
- Sergey Kolodyazhnyy (skolodyazhnyy)
- umpirski
- Chris Heng (gigablah)
- Ulumuddin Yunus (joenoez)
@ -377,6 +385,7 @@ Symfony2 is the result of the work of many people who made the code better
- Arturs Vonda
- Sascha Grossenbacher
- Ben Davies (bendavies)
- Alex Bakhturin
- Simon Schick (simonsimcity)
- redstar504
- Hossein Bukhamsin
@ -414,14 +423,15 @@ Symfony2 is the result of the work of many people who made the code better
- Mark Challoner
- Andrew Tchircoff (andrewtch)
- michaelwilliams
- 1emming
- Leevi Graham (leevigraham)
- Casper Valdemar Poulsen
- Josiah (josiah)
- Marek Štípek (maryo)
- John Bohn (jbohn)
- Andrew Hilobok (hilobok)
- Matthieu Auger (matthieuauger)
- Christian Soronellas (theunic)
- Daniel Beyer
- Jérôme Vieilledent (lolautruche)
- Degory Valentine
- Benoit Lévêque (benoit_leveque)
@ -430,8 +440,10 @@ Symfony2 is the result of the work of many people who made the code better
- Xavier Lacot (xavier)
- Olivier Maisonneuve (olineuve)
- Francis Turmel (fturmel)
- Loick Piera (pyrech)
- cgonzalez
- Ben
- Lee Rowlands
- Jayson Xu (superjavason)
- Tobias Nyholm (tobias)
- Jaik Dean (jaikdean)
@ -452,6 +464,7 @@ Symfony2 is the result of the work of many people who made the code better
- Maksim Kotlyar (makasim)
- Neil Ferreira
- Dmitry Parnas (parnas)
- DQNEO
- Emanuele Iannone
- Tony Malzhacker
- Cyril Quintin (cyqui)
@ -474,6 +487,7 @@ Symfony2 is the result of the work of many people who made the code better
- Benjamin Laugueux (yzalis)
- Christian Morgan
- Alexander Miehe (engerim)
- Morgan Auchede (mauchede)
- Titouan Galopin (tgalopin)
- Don Pinkster
- Maksim Muruev
@ -492,15 +506,16 @@ Symfony2 is the result of the work of many people who made the code better
- Daniel Cestari
- Magnus Nordlander (magnusnordlander)
- Mikhail Yurasov (mym)
- Florian Rey (nervo)
- LOUARDI Abdeltif (ouardisoft)
- Robert Gruendler (pulse00)
- Simon Terrien (sterrien)
- Benoît Merlet (trompette)
- Koen Kuipers
- datibbaw
- Raul Fraile (raulfraile)
- sensio
- Patrick Kaufmann
- Matthieu Napoli (mnapoli)
- Ben Ramsey (ramsey)
- Christian Jul Jensen
- The Whole Life to Learn
@ -511,6 +526,7 @@ Symfony2 is the result of the work of many people who made the code better
- Colin O'Dell (colinodell)
- xaav
- Mahmoud Mostafa (mahmoud)
- Michael Tibben
- Sander Marechal
- Radosław Benkel
- ttomor
@ -540,6 +556,7 @@ Symfony2 is the result of the work of many people who made the code better
- Alex Bogomazov
- tamirvs
- julien.galenski
- Christian Neff
- Per Sandström (per)
- Goran Juric
- Lin Clark
@ -574,8 +591,8 @@ Symfony2 is the result of the work of many people who made the code better
- Matteo Giachino (matteosister)
- Alex Demchenko (pilot)
- Benoit Garret
- Thomas Royer (cydonia7)
- DerManoMann
- Asmir Mustafic (goetas)
- Julien Bianchi (jubianchi)
- Marcin Chwedziak
- Roland Franssen (ro0)
@ -584,18 +601,22 @@ Symfony2 is the result of the work of many people who made the code better
- e-ivanov
- Jochen Bayer (jocl)
- Jeremy Bush
- rpg600
- Péter Buri (burci)
- Davide Borsatto (davide.borsatto)
- kaiwa
- Charles Sanquer (csanquer)
- Albert Ganiev (helios-ag)
- Neil Katin
- David Otton
- peter
- Jérémy Jourdin (jjk801)
- Artem Kolesnikov (tyomo4ka)
- Gustavo Adrian
- Yannick
- Luc Vieillescazes (iamluc)
- Eduardo García Sanz (coma)
- Roy Van Ginneken
- David de Boer (ddeboer)
- Gilles Doge (gido)
- Brooks Boyd
@ -607,6 +628,7 @@ Symfony2 is the result of the work of many people who made the code better
- Patrick Landolt (scube)
- WybrenKoelmans
- Derek Lambert
- Kacper Gunia (cakper)
- Felicitus
- Krzysztof Przybyszewski
- Paul Matthews
@ -617,6 +639,7 @@ Symfony2 is the result of the work of many people who made the code better
- Clement Herreman (clemherreman)
- Trent Steel (trsteel88)
- Marco
- Marc Torres
- Alberto Aldegheri
- heccjj
- Alexandre Melard
@ -661,14 +684,12 @@ Symfony2 is the result of the work of many people who made the code better
- Anthony Ferrara
- ShiraNai7
- Janusz Jabłoński (yanoosh)
- Sergey Kolodyazhnyy
- George Giannoulopoulos
- Daniel Richter (richtermeister)
- ChrisC
- Ilya Biryukov
- Jason Desrosiers
- m.chwedziak
- Endre Fejes
- Lance McNearney
- Giorgio Premi
- caponica
@ -697,10 +718,12 @@ Symfony2 is the result of the work of many people who made the code better
- Adrien Samson (adriensamson)
- Samuel Gordalina (gordalina)
- Max Romanovsky (maxromanovsky)
- Mathieu Morlon
- Rafał Muszyński (rafmus90)
- Timothy Anido (xanido)
- Rick Prent
- Martin Eckhardt
- Damien Tournoud
- Jon Gotlin (jongotlin)
- Michael Dowling (mtdowling)
- BilgeXA
@ -738,6 +761,7 @@ Symfony2 is the result of the work of many people who made the code better
- Hoffmann András
- Olivier
- pscheit
- Dan Harper
- moldcraft
- Ramon Kleiss (akathos)
- Nicolas Badey (nico-b)
@ -772,6 +796,7 @@ Symfony2 is the result of the work of many people who made the code better
- Paul Seiffert (seiffert)
- Vasily Khayrulin (sirian)
- Stefan Koopmanschap (skoop)
- Yosmany Garcia (yosmanyga)
- Ivan Kurnosov
- stloyd
- Chris Tickner
@ -789,11 +814,13 @@ Symfony2 is the result of the work of many people who made the code better
- Andrey Ryaguzov
- Manatsawin Hanmongkolchai
- Gunther Konig
- flack
- František Bereň
- Christoph Nissle (derstoffel)
- Ionel Scutelnicu (ionelscutelnicu)
- Johnny Peck (johnnypeck)
- Nicolas Tallefourtané (nicolab)
- Thierry Marianne (thierrymarianne)
- Nick Stemerdink
- jjanvier
- Romain Dorgueil
@ -822,11 +849,10 @@ Symfony2 is the result of the work of many people who made the code better
- Jordi Llonch (jordillonch)
- Cédric Dugat (ph3nol)
- Philip Dahlstrøm (phidah)
- Loick Piera (pyrech)
- Milos Colakovic (project2481)
- Rénald Casagraude (rcasagraude)
- Robin Duval (robin-duval)
- Artem Lopata (bumz)
- Iltar van der Berg
- Alexey Popkov
- Artyom Protaskin
- Nathanael d. Noblet
@ -838,6 +864,7 @@ Symfony2 is the result of the work of many people who made the code better
- dened
- Sam Ward
- Walther Lalk
- Adam
- devel
- Trevor Suarez
- gedrox
@ -846,6 +873,7 @@ Symfony2 is the result of the work of many people who made the code better
- Drew Butler
- J Bruni
- Alexey Prilipko
- bertillon
- Hans Nilsson (hansnilsson)
- Jan Marek (janmarek)
- Mark de Haan (markdehaan)
@ -860,6 +888,7 @@ Symfony2 is the result of the work of many people who made the code better
- Tom Maguire
- David Zuelke
- Pierre Rineau
- adenkejawen
- Ari Pringle (apringle)
- Dan Ordille (dordille)
- Jan Eichhorn (exeu)
@ -868,6 +897,7 @@ Symfony2 is the result of the work of many people who made the code better
- Florian Pfitzer (marmelatze)
- Martin Mayer (martin)
- Grzegorz Łukaszewicz (newicz)
- grifx
- Robert Campbell
- Matt Lehner
- Ruben Kruiswijk
@ -881,6 +911,8 @@ Symfony2 is the result of the work of many people who made the code better
- Rowan Manning
- David Windell
- Gabriel Birke
- Steffen Roßkamp
- skafandri
- Alan Chen
- Maerlyn
- Even André Fiskvik
@ -901,6 +933,7 @@ Symfony2 is the result of the work of many people who made the code better
- Dave Marshall (davedevelopment)
- David Joos (djoos)
- Denis Klementjev (dklementjev)
- Tomáš Polívka (draczris)
- Vincent Composieux (eko)
- Franz Liedke (franzliedke)
- gondo (gondo)
@ -926,6 +959,7 @@ Symfony2 is the result of the work of many people who made the code better
- Curtis
- Alexey Popkov
- Joseph Deray
- Damian Sromek
- Arnaud Buathier (arnapou)
- chesteroni (chesteroni)
- Mauricio Lopez (diaspar)
@ -940,7 +974,6 @@ Symfony2 is the result of the work of many people who made the code better
- goohib
- Xavier HAUSHERR
- Cas
- Maxime Douailin
- Myke79
- Brian Debuire
- Sylvain Lorinet
@ -949,6 +982,7 @@ Symfony2 is the result of the work of many people who made the code better
- jc
- BenjaminBeck
- Aurelijus Rožėnas
- znerol
- Christian Eikermann
- Antonio Angelino
- Vladimir Sazhin
@ -980,7 +1014,6 @@ Symfony2 is the result of the work of many people who made the code better
- Brian Freytag
- Skorney
- mieszko4
- datibbaw
- Markus Staab
- Pierre-Louis LAUNAY
- djama
@ -988,6 +1021,7 @@ Symfony2 is the result of the work of many people who made the code better
- Jon Cave
- Sébastien HOUZE
- Abdulkadir N. A.
- Yevgen Kovalienia
- Sema
- Thorsten Hallwas
- Michael Squires
@ -1013,7 +1047,6 @@ Symfony2 is the result of the work of many people who made the code better
- Michaël VEROUX
- sualko
- Nicolas Roudaire
- Lee Rowlands
- Andreas Forsblom (aforsblo)
- Alaattin Kahramanlar (alaattin)
- Alex Olmos (alexolmos)
@ -1052,7 +1085,6 @@ Symfony2 is the result of the work of many people who made the code better
- Laurent Bachelier (laurentb)
- Jérôme Parmentier (lctrs)
- Matthieu Moquet (mattketmo)
- Morgan Auchede (mauchede)
- Moritz Borgmann (mborgmann)
- Matt Drollette (mdrollette)
- Adam Monsen (meonkeys)
@ -1073,7 +1105,6 @@ Symfony2 is the result of the work of many people who made the code better
- Julien Sanchez (sumbobyboys)
- Guillermo Gisinger (t3chn0r)
- Markus Tacker (tacker)
- Tristan Maindron (tmaindron)
- Tyler Stroud (tystr)
- Víctor Mateo (victormateo)
- Vincent (vincent1870)

View File

@ -40,7 +40,7 @@
Before:
```
```yaml
framework:
session:
default_locale: fr
@ -48,7 +48,7 @@
After:
```
```yaml
framework:
default_locale: fr
```
@ -74,10 +74,10 @@
##### Simulate old behavior
You can simulate that the locale for the user is still stored in the session by
registering a listener that looks like the following if the parameter which
registering a listener that looks like the following if the parameter which
handles the locale value in the request is `_locale`:
```
```php
namespace XXX;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@ -138,7 +138,7 @@
Before:
```
```php
class User implements UserInterface
{
// ...
@ -149,7 +149,7 @@
After:
```
```php
class User implements UserInterface, EquatableInterface
{
// ...
@ -165,13 +165,13 @@
Before:
``` yaml
```yaml
security:
factories:
- "%kernel.root_dir%/../src/Acme/DemoBundle/Resources/config/security_factories.yml"
```
``` yaml
```yaml
# src/Acme/DemoBundle/Resources/config/security_factories.yml
services:
security.authentication.factory.custom:
@ -182,7 +182,7 @@
After:
```
```php
namespace Acme\DemoBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
@ -212,7 +212,7 @@
Before:
``` yaml
```yaml
security:
providers:
my_chain_provider:
@ -225,7 +225,7 @@
After:
``` yaml
```yaml
security:
providers:
my_chain_provider:
@ -245,14 +245,14 @@
Before:
```
```php
use Symfony\Bundle\SecurityBundle\Validator\Constraint\UserPassword;
use Symfony\Bundle\SecurityBundle\Validator\Constraint as SecurityAssert;
```
After:
```
```php
use Symfony\Component\Security\Core\Validator\Constraint\UserPassword;
use Symfony\Component\Security\Core\Validator\Constraint as SecurityAssert;
```
@ -270,7 +270,7 @@
Before:
```
```php
use Symfony\Component\Form\FormBuilder;
public function buildForm(FormBuilder $builder, array $options)
@ -278,7 +278,7 @@
After:
```
```php
use Symfony\Component\Form\FormBuilderInterface;
public function buildForm(FormBuilderInterface $builder, array $options)
@ -301,7 +301,7 @@
Before:
```
```php
public function getParent(array $options)
{
return 'field';
@ -310,7 +310,7 @@
After:
```
```php
public function getParent()
{
return 'form';
@ -333,7 +333,7 @@
Before:
```
```php
public function getParent(array $options)
{
return $options['expanded'] ? 'form' : 'field';
@ -342,7 +342,7 @@
After:
```
```php
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\Options;
@ -374,7 +374,7 @@
Form mapped to an instance of `Person`:
```
```php
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
public function setDefaultOptions(OptionsResolverInterface $resolver)
@ -399,7 +399,7 @@
Before:
```
```php
$builder->add('name', 'text', array(
'property_path' => 'address.street',
));
@ -407,7 +407,7 @@
After (if the address object is an array):
```
```php
$builder->add('name', 'text', array(
'property_path' => 'address[street]',
));
@ -427,7 +427,7 @@
underscores wherever you specify a value for the field's "prototype_name"
option.
```
```php
$builder->add('tags', 'collection', array('prototype_name' => '__proto__'));
// results in the name "__proto__" in the template
@ -455,7 +455,7 @@
Before:
```
```jinja
{% block url_widget %}
{% spaceless %}
{% set type = type|default('url') %}
@ -466,7 +466,7 @@
After:
```
```jinja
{% block url_widget %}
{% spaceless %}
{% set type = type|default('url') %}
@ -482,7 +482,7 @@
Before:
```
```jinja
{% block form_errors %}
{% spaceless %}
... form code ...
@ -498,7 +498,7 @@
After:
```
```jinja
{% block form_errors %}
{% spaceless %}
{% if compound %}
@ -526,13 +526,13 @@
* In the choice field type's template, the `_form_is_choice_selected` method
used to identify a selected choice has been replaced with the `selectedchoice`
filter. Similarly, the `_form_is_choice_group` method used to check if a
choice is grouped has been removed and can be checked with the `iterable`
filter. Similarly, the `_form_is_choice_group` method used to check if a
choice is grouped has been removed and can be checked with the `iterable`
test.
Before:
```
```jinja
{% for choice, label in choices %}
{% if _form_is_choice_group(label) %}
<optgroup label="{{ choice|trans }}">
@ -550,7 +550,7 @@
After:
```
```jinja
{% for label, choice in choices %}
{% if choice is iterable %}
<optgroup label="{{ label|trans({}, translation_domain) }}">
@ -571,7 +571,7 @@
accommodate those cases when the `label` option has not been explicitly
set.
```
```jinja
{% block form_label %}
{% if label is empty %}
{% set label = name|humanize %}
@ -588,7 +588,7 @@
Before:
```
```jinja
{% block _author_tags_0_label %}
{# ... #}
{% endblock %}
@ -600,7 +600,7 @@
After:
```
```jinja
{% block _author_tags_entry_label %}
{# ... #}
{% endblock %}
@ -612,13 +612,13 @@
Before:
```
```php
<?php echo $view['form']->renderBlock('widget_attributes') ?>
```
After:
```
```php
<?php echo $view['form']->block($form, 'widget_attributes') ?>
```
@ -631,13 +631,13 @@
Before:
```
```php
$form = $factory->createNamed('text', 'firstName');
```
After:
```
```php
$form = $factory->createNamed('firstName', 'text');
```
@ -648,7 +648,7 @@
Before:
```
```php
class MyChoiceList extends ArrayChoiceList
{
protected function load()
@ -664,7 +664,7 @@
After:
```
```php
class MyChoiceList extends SimpleChoiceList
{
public function __construct()
@ -680,7 +680,7 @@
accessed for the first time -- you can extend `LazyChoiceList` instead
and load the choices by overriding `loadChoiceList()`.
```
```php
class MyChoiceList extends LazyChoiceList
{
protected function loadChoiceList()
@ -705,13 +705,13 @@
Before:
```
```jinja
{{ form_label(form.name, 'Your Name', { 'attr': {'class': 'foo'} }) }}
```
After:
```
```jinja
{{ form_label(form.name, 'Your Name', { 'label_attr': {'class': 'foo'} }) }}
```
@ -751,7 +751,7 @@
Before:
```
```php
public function getDefaultOptions(array $options)
{
return array(
@ -769,7 +769,7 @@
After:
```
```php
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
@ -786,7 +786,7 @@
Before:
```
```php
public function getDefaultOptions(array $options)
{
$defaultOptions = array();
@ -801,7 +801,7 @@
After:
```
```php
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
@ -832,13 +832,13 @@
Before:
```
```php
$builder->appendClientTransformer(new MyTransformer());
```
After:
```
```php
$builder->addViewTransformer(new MyTransformer());
```
@ -857,7 +857,7 @@
Before:
```
```php
$builder->addListener(FormEvents::BIND_CLIENT_DATA, function (FilterDataEvent $event) {
// ...
});
@ -865,7 +865,7 @@
After:
```
```php
$builder->addListener(FormEvents::PRE_BIND, function (FormEvent $event) {
// ...
});
@ -886,7 +886,7 @@
Before:
```
```php
public function guessMinLength($class, $property)
{
if (/* condition */) {
@ -897,7 +897,7 @@
After:
```
```php
public function guessPattern($class, $property)
{
if (/* condition */) {
@ -914,7 +914,7 @@
Before:
```
```php
$builder->add('termsAccepted', 'checkbox', array(
'property_path' => false,
));
@ -922,7 +922,7 @@
After:
```
```php
$builder->add('termsAccepted', 'checkbox', array(
'mapped' => false,
));
@ -944,13 +944,13 @@
Before:
```
```php
$form->getErrorBubbling()
```
After:
```
```php
$form->getConfig()->getErrorBubbling();
```
@ -962,13 +962,13 @@
Before:
```
```php
if ($form->hasChildren()) {
```
After:
```
```php
if (count($form) > 0) {
```
@ -976,13 +976,13 @@
Before:
```
```php
$form->bindRequest($request);
```
After:
```
```php
$form->bind($request);
```
@ -992,7 +992,7 @@
Before:
```
```php
$builder->add('name', 'text', array(
'validation_constraint' => new NotBlank(),
));
@ -1000,7 +1000,7 @@
After:
```
```php
$builder->add('name', 'text', array(
'constraints' => new NotBlank(),
));
@ -1008,7 +1008,7 @@
Unlike previously, you can also pass a list of constraints now:
```
```php
$builder->add('name', 'text', array(
'constraints' => array(
new NotBlank(),
@ -1021,7 +1021,7 @@
to the validated group! So if you validate a form in group "Custom"
and previously did:
```
```php
$builder->add('name', 'text', array(
'validation_constraint' => new NotBlank(),
));
@ -1029,7 +1029,7 @@
Then you need to add the constraint to the group "Custom" now:
```
```php
$builder->add('name', 'text', array(
'constraints' => new NotBlank(array('groups' => 'Custom')),
));
@ -1041,7 +1041,7 @@
Before:
```
```php
$builder->add('scheduledFor', 'date', array(
'data_timezone' => 'UTC',
'user_timezone' => 'America/New_York',
@ -1050,7 +1050,7 @@
After:
```
```php
$builder->add('scheduledFor', 'date', array(
'model_timezone' => 'UTC',
'view_timezone' => 'America/New_York',
@ -1063,13 +1063,13 @@
Before:
```
```php
$this->get('form.factory')->addType(new MyFormType());
```
After:
```
```php
$registry = $this->get('form.registry');
$registry->addType($registry->resolveType(new MyFormType()));
@ -1098,14 +1098,14 @@
Before:
```
```php
$view->set('help', 'A text longer than six characters');
$view->set('error_class', 'max_length_error');
```
After:
```
```php
$view->vars = array_replace($view->vars, array(
'help' => 'A text longer than six characters',
'error_class' => 'max_length_error',
@ -1114,25 +1114,25 @@
Before:
```
```php
echo $view->get('error_class');
```
After:
```
```php
echo $view->vars['error_class'];
```
Before:
```
```php
if ($view->hasChildren()) { ...
```
After:
```
```php
if (count($view->children)) { ...
```
@ -1147,7 +1147,7 @@
Before:
```
```php
public function isValid($value, Constraint $constraint)
{
// ...
@ -1163,7 +1163,7 @@
After:
```
```php
public function isValid($value, Constraint $constraint)
{
// ...
@ -1185,7 +1185,7 @@
Before:
```
```php
public function isPropertyValid(ExecutionContext $context)
{
// ...
@ -1197,7 +1197,7 @@
After:
```
```php
public function isPropertyValid(ExecutionContext $context)
{
// ...
@ -1216,7 +1216,7 @@
Before:
```
```php
public function isValid($value, Constraint $constraint)
{
// ...
@ -1232,7 +1232,7 @@
After:
```
```php
public function validate($value, Constraint $constraint)
{
// ...
@ -1259,14 +1259,14 @@
Before:
```
```php
/** @Assert\Valid */
private $recursiveCollection;
```
After:
```
```php
/** @Assert\Valid(deep = true) */
private $recursiveCollection;
```
@ -1276,28 +1276,28 @@
Before:
```
```php
/** @Assert\Size(min = 2, max = 16) */
private $numberOfCpus;
```
After:
```
```php
/** @Assert\Range(min = 2, max = 16) */
private $numberOfCpus;
```
Before:
```
```php
/** @Assert\Min(2) */
private $numberOfCpus;
```
After:
```
```php
/** @Assert\Range(min = 2) */
private $numberOfCpus;
```
@ -1307,14 +1307,14 @@
Before:
```
```php
/** @Assert\MinLength(8) */
private $password;
```
After:
```
```php
/** @Assert\Length(min = 8) */
private $password;
```
@ -1325,14 +1325,14 @@
Before:
```
```php
$validator = ValidatorFactory::buildDefault(array('path/to/mapping.xml'))
->getValidator();
```
After:
```
```php
$validator = Validation::createValidatorBuilder()
->addXmlMapping('path/to/mapping.xml')
->getValidator();
@ -1349,7 +1349,7 @@
Before:
```
```jinja
{% if app.session.hasFlash('notice') %}
<div class="flash-notice">
{{ app.session.getFlash('notice') }}
@ -1358,7 +1358,7 @@
```
After:
```
```jinja
{% for flashMessage in app.session.flashbag.get('notice') %}
<div class="flash-notice">
{{ flashMessage }}
@ -1368,7 +1368,7 @@
You can process all flash messages in a single loop with:
```
```jinja
{% for type, flashMessages in app.session.flashbag.all() %}
{% for flashMessage in flashMessages %}
<div class="flash-{{ type }}">
@ -1391,7 +1391,7 @@
* The `item` element is now converted to an array when deserializing XML.
``` xml
```xml
<?xml version="1.0"?>
<response>
<item><title><![CDATA[title1]]></title></item><item><title><![CDATA[title2]]></title></item>
@ -1433,7 +1433,7 @@
Before:
```
```yaml
framework:
session:
lifetime: 3600
@ -1445,7 +1445,7 @@
After:
```
```yaml
framework:
session:
cookie_lifetime: 3600
@ -1457,7 +1457,7 @@
Added `handler_id`, defaults to `session.handler.native_file`.
```
```yaml
framework:
session:
storage_id: session.storage.native
@ -1466,7 +1466,7 @@ Added `handler_id`, defaults to `session.handler.native_file`.
To use mock session storage use the following. `handler_id` is irrelevant in this context.
```
```yaml
framework:
session:
storage_id: session.storage.mock_file

View File

@ -7,13 +7,13 @@
Before:
```
```jinja
{% render 'BlogBundle:Post:list' with { 'limit': 2 }, { 'alt': 'BlogBundle:Post:error' } %}
```
After:
```
```jinja
{% render controller('BlogBundle:Post:list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error' } %}
{# Or: #}
{{ render(controller('BlogBundle:Post:list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error'}) }}
@ -29,7 +29,7 @@
Before:
```
```jinja
{% render 'BlogBundle:Post:list' with { 'limit': 2 }, {'standalone': true} %}
{% render 'BlogBundle:Post:list' with { 'limit': 2 }, {'standalone': false} %}
{% render 'BlogBundle:Post:list' with { 'limit': 2 }, {'standalone': 'js'} %}
@ -37,7 +37,7 @@
After:
```
```jinja
{{ render(controller('BlogBundle:Post:list', { 'limit': 2 }), { 'strategy': 'esi'}) }}
{{ render(controller('BlogBundle:Post:list', { 'limit': 2 }), { 'strategy': 'inline'}) }}
{{ render(controller('BlogBundle:Post:list', { 'limit': 2 }), { 'strategy': 'hinclude'}) }}
@ -65,7 +65,7 @@
You should now use the `AcceptHeader` class which give you fluent methods to
parse request accept-* headers. Some examples:
```
```php
$accept = AcceptHeader::fromString($request->headers->get('Accept'));
if ($accept->has('text/html') {
$item = $accept->get('html');
@ -95,7 +95,7 @@
Before:
```
```jinja
{{
error.messagePluralization is null
? error.messageTemplate|trans(error.messageParameters, 'validators')
@ -105,7 +105,7 @@
After:
```
```jinja
{{ error.message }}
```
@ -117,7 +117,7 @@
Before:
```
```php
use Symfony\Component\Form\Extensions\Core\DataMapper\PropertyPathMapper;
class CustomMapper extends PropertyPathMapper
@ -133,7 +133,7 @@
After:
```
```php
use Symfony\Component\Form\Extensions\Core\DataMapper\PropertyPathMapper;
class CustomMapper extends PropertyPathMapper
@ -163,7 +163,7 @@
Before:
```
```php
use Symfony\Component\Form\Util\PropertyPath;
use Symfony\Component\Form\Util\PropertyPathBuilder;
use Symfony\Component\Form\Util\PropertyPathInterface;
@ -176,7 +176,7 @@
After:
```
```php
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\PropertyAccess\PropertyPathBuilder;
use Symfony\Component\PropertyAccess\PropertyPathInterface;
@ -192,7 +192,7 @@
Before:
```
```php
use Symfony\Component\Form\Util\FormUtil;
$singular = FormUtil::singularify($plural);
@ -200,7 +200,7 @@
After:
```
```php
use Symfony\Component\PropertyAccess\StringUtil;
$singular = StringUtil::singularify($plural);
@ -211,7 +211,7 @@
Before:
```
```php
use Symfony\Component\Form\Util\PropertyPath;
$propertyPath = new PropertyPath('some.path');
@ -222,7 +222,7 @@
After (alternative 1):
```
```php
use Symfony\Component\PropertyAccess\PropertyAccess;
$propertyAccessor = PropertyAccess::getPropertyAccessor();
@ -233,7 +233,7 @@
After (alternative 2):
```
```php
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyPath;
@ -253,7 +253,7 @@
Before:
```
```php
$rootCollection = new RouteCollection();
$subCollection = new RouteCollection();
$rootCollection->addCollection($subCollection);
@ -262,7 +262,7 @@
After:
```
```php
$rootCollection = new RouteCollection();
$subCollection = new RouteCollection();
$subCollection->add('foo', new Route('/foo'));
@ -272,7 +272,7 @@
Also one must call `addCollection` from the bottom to the top hierarchy.
So the correct sequence is the following (and not the reverse):
```
```php
$childCollection->addCollection($grandchildCollection);
$rootCollection->addCollection($childCollection);
```
@ -298,7 +298,7 @@
use-case instead.
Before: `$parentCollection->addCollection($collection, '/prefix', array(...), array(...))`
After:
```
```php
$collection->addPrefix('/prefix', array(...), array(...));
$parentCollection->addCollection($collection);
```
@ -312,7 +312,7 @@
Before:
```
```php
use Symfony\Component\Validator\ExecutionContext;
public function validateCustomLogic(ExecutionContext $context)
@ -320,7 +320,7 @@
After:
```
```php
use Symfony\Component\Validator\ExecutionContextInterface;
public function validateCustomLogic(ExecutionContextInterface $context)
@ -331,7 +331,7 @@
Before:
```
```php
use Symfony\Component\Validator\ConstraintValidatorInterface;
use Symfony\Component\Validator\ExecutionContext;
@ -346,7 +346,7 @@
After:
```
```php
use Symfony\Component\Validator\ConstraintValidatorInterface;
use Symfony\Component\Validator\ExecutionContextInterface;
@ -391,7 +391,7 @@
Before:
```
```php
use Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface;
class MyMetadataFactory implements ClassMetadataFactoryInterface
@ -405,7 +405,7 @@
After:
```
```php
use Symfony\Component\Validator\MetadataFactoryInterface;
use Symfony\Component\Validator\Exception\NoSuchMetadataException;
@ -432,14 +432,14 @@
Before:
```
```php
$metadataFactory = $validator->getMetadataFactory();
$metadata = $metadataFactory->getClassMetadata('Vendor\MyClass');
```
After:
```
```php
$metadataFactory = $validator->getMetadataFactory();
$metadata = $metadataFactory->getMetadataFor('Vendor\MyClass');
```
@ -451,7 +451,7 @@
Before:
```
```php
use Symfony\Component\Validator\ExecutionContext;
public function validateCustomLogic(ExecutionContext $context)
@ -471,7 +471,7 @@
After:
```
```php
use Symfony\Component\Validator\ExecutionContextInterface;
public function validateCustomLogic(ExecutionContextInterface $context)
@ -488,7 +488,7 @@
Before:
```
```php
use Symfony\Component\Validator\ExecutionContext;
public function validateCustomLogic(ExecutionContext $context)
@ -501,7 +501,7 @@
After:
```
```php
use Symfony\Component\Validator\ExecutionContextInterface;
public function validateCustomLogic(ExecutionContextInterface $context)
@ -519,7 +519,7 @@
Before:
```
```php
use Symfony\Component\Validator\ExecutionContext;
public function validateCustomLogic(ExecutionContext $context)
@ -534,7 +534,7 @@
After:
```
```php
use Symfony\Component\Validator\ExecutionContextInterface;
public function validateCustomLogic(ExecutionContextInterface $context)
@ -553,20 +553,20 @@
Before:
```
```php
<?php echo $view['actions']->render('BlogBundle:Post:list', array('limit' => 2), array('alt' => 'BlogBundle:Post:error')) ?>
```
After:
```
```php
<?php echo $view['actions']->render($view['router']->generate('post_list', array('limit' => 2)), array('alt' => 'BlogBundle:Post:error')) ?>
```
where `post_list` is the route name for the `BlogBundle:Post:list`
controller, or if you don't want to create a route:
```
```php
<?php echo $view['actions']->render(new ControllerReference('BlogBundle:Post:list', array('limit' => 2)), array('alt' => 'BlogBundle:Post:error')) ?>
```
@ -577,7 +577,7 @@
Before:
```
```yaml
# app/config/config.yml
framework:
trust_proxy_headers: false
@ -585,7 +585,7 @@
After:
```
```yaml
# app/config/config.yml
framework:
trusted_proxies: ['127.0.0.1', '10.0.0.1'] # a list of proxy IPs you trust
@ -598,13 +598,13 @@
Before:
```
```php
use Symfony\Component\Security\Core\Validator\Constraint\UserPassword;
```
After: (note the `s` at the end of `Constraint`)
```
```php
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
```
@ -612,7 +612,7 @@
``service`` option that allows to specify a custom validator service name in
order to validate the current logged-in user's password.
```
```php
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
$constraint = new UserPassword(array(
@ -628,14 +628,14 @@
Before:
```
```php
use Symfony\Component\Security\Core\Validator\Constraint\UserPassword;
use Symfony\Component\Security\Core\Validator\Constraint\UserPasswordValidator;
```
After:
```
```php
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator;
```

View File

@ -41,7 +41,7 @@ Form
Before:
```
```php
use Symfony\Component\Form\DataMapperInterface;
class MyDataMapper
@ -60,7 +60,7 @@ Form
After:
```
```php
use Symfony\Component\Form\DataMapperInterface;
class MyDataMapper
@ -84,7 +84,7 @@ Form
Before:
```
```php
use Symfony\Component\Form\Util\VirtualFormAwareIterator;
public function mapFormsToData(array $forms, $data)
@ -101,7 +101,7 @@ Form
After:
```
```php
public function mapFormsToData($forms, $data)
{
foreach ($forms as $form) {
@ -121,7 +121,7 @@ Form
Before:
```
```php
$form = $factory->create('form');
$form->add($factory->createNamed('field', 'text'));
```
@ -135,7 +135,7 @@ Form
After (Alternative 1):
```
```php
$form = $factory->create('form');
$form->add($factory->createNamed('field', 'text', array(), array(
'auto_initialize' => false,
@ -147,7 +147,7 @@ Form
After (Alternative 2):
```
```php
$builder = $factory->createBuilder('form');
$builder->add($factory->createBuilder('field', 'text'));
$form = $builder->getForm();
@ -157,14 +157,14 @@ Form
After (Alternative 3):
```
```php
$form = $factory->create('form');
$form->add('field', 'text');
```
After (Alternative 4):
```
```php
$builder = $factory->createBuilder('form');
$builder->add('field', 'text');
$form = $builder->getForm();
@ -180,7 +180,7 @@ Form
Before:
```
```php
$builder->add('field', 'text', array(
'data' => $defaultData ?: null,
));
@ -188,7 +188,7 @@ Form
After:
```
```php
$options = array();
if ($defaultData) {
$options['data'] = $defaultData;
@ -203,7 +203,7 @@ PropertyAccess
even if a non-public match was found. This means that the property "author"
in the following class will now correctly be found:
```
```php
class Article
{
public $author;
@ -224,7 +224,7 @@ PropertyAccess
Before:
```
```php
use Symfony\Component\PropertyAccess\Exception\PropertyAccessDeniedException;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
@ -239,7 +239,7 @@ PropertyAccess
After:
```
```php
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
try {
@ -257,7 +257,7 @@ DomCrawler
Before:
```
```php
$data = $crawler->each(function ($node, $i) {
return $node->nodeValue;
});
@ -265,7 +265,7 @@ DomCrawler
After:
```
```php
$data = $crawler->each(function ($crawler, $i) {
return $crawler->text();
});
@ -280,13 +280,13 @@ Console
Before:
```
```php
if (OutputInterface::VERBOSITY_VERBOSE === $output->getVerbosity()) { ... }
```
After:
```
```php
if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { ... }
```

View File

@ -98,13 +98,13 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
$form->bind(array(...));
```
After:
```
```php
$form->submit(array(...));
```
@ -115,7 +115,7 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
if ('POST' === $request->getMethod()) {
$form->bind($request);
@ -127,7 +127,7 @@ UPGRADE FROM 2.x to 3.0
After:
```
```php
$form->handleRequest($request);
if ($form->isValid()) {
@ -138,7 +138,7 @@ UPGRADE FROM 2.x to 3.0
If you want to test whether the form was submitted separately, you can use
the method `isSubmitted()`:
```
```php
$form->handleRequest($request);
if ($form->isSubmitted()) {
@ -155,7 +155,7 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
$builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) {
// ...
});
@ -163,7 +163,7 @@ UPGRADE FROM 2.x to 3.0
After:
```
```php
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
// ...
});
@ -173,7 +173,7 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
$builder->add('address', 'form', array(
'virtual' => true,
));
@ -181,7 +181,7 @@ UPGRADE FROM 2.x to 3.0
After:
```
```php
$builder->add('address', 'form', array(
'inherit_data' => true,
));
@ -191,7 +191,7 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
use Symfony\Component\Form\Util\VirtualFormAwareIterator;
$iterator = new VirtualFormAwareIterator($forms);
@ -199,7 +199,7 @@ UPGRADE FROM 2.x to 3.0
After:
```
```php
use Symfony\Component\Form\Util\InheritDataAwareIterator;
$iterator = new InheritDataAwareIterator($forms);
@ -209,7 +209,7 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
use Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase
class MyTypeTest extends TypeTestCase
@ -220,7 +220,7 @@ UPGRADE FROM 2.x to 3.0
After:
```
```php
use Symfony\Component\Form\Test\TypeTestCase;
class MyTypeTest extends TypeTestCase
@ -310,7 +310,7 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
<form method="post" action="http://example.com" <?php echo $view['form']->enctype($form) ?>>
...
</form>
@ -318,7 +318,7 @@ UPGRADE FROM 2.x to 3.0
After:
```
```php
<?php echo $view['form']->start($form) ?>
...
<?php echo $view['form']->end($form) ?>
@ -330,7 +330,7 @@ UPGRADE FROM 2.x to 3.0
Alternative 1:
```
```php
$form = $this->createForm('my_form', $formData, array(
'method' => 'PUT',
'action' => $this->generateUrl('target_route'),
@ -339,7 +339,7 @@ UPGRADE FROM 2.x to 3.0
Alternative 2:
```
```php
$form = $this->createFormBuilder($formData)
// ...
->setMethod('PUT')
@ -349,7 +349,7 @@ UPGRADE FROM 2.x to 3.0
It is also possible to override the method and the action in the template:
```
```php
<?php echo $view['form']->start($form, array('method' => 'GET', 'action' => 'http://example.com')) ?>
...
<?php echo $view['form']->end($form) ?>
@ -408,7 +408,7 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
use Symfony\Component\PropertyAccess\PropertyAccess;
$accessor = PropertyAccess::getPropertyAccessor();
@ -416,7 +416,7 @@ UPGRADE FROM 2.x to 3.0
After:
```
```php
use Symfony\Component\PropertyAccess\PropertyAccess;
$accessor = PropertyAccess::createPropertyAccessor();
@ -431,17 +431,21 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```yaml
article_edit:
pattern: /article/{id}
requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' }
```
```xml
<route id="article_edit" pattern="/article/{id}">
<requirement key="_method">POST|PUT</requirement>
<requirement key="_scheme">https</requirement>
<requirement key="id">\d+</requirement>
</route>
```
```php
$route = new Route();
$route->setPattern('/article/{id}');
$route->setRequirement('_method', 'POST|PUT');
@ -450,17 +454,21 @@ UPGRADE FROM 2.x to 3.0
After:
```
```yaml
article_edit:
path: /article/{id}
methods: [POST, PUT]
schemes: https
requirements: { 'id': '\d+' }
```
```xml
<route id="article_edit" path="/article/{id}" methods="POST PUT" schemes="https">
<requirement key="id">\d+</requirement>
</route>
```
```php
$route = new Route();
$route->setPath('/article/{id}');
$route->setMethods(array('POST', 'PUT'));
@ -489,7 +497,7 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
<form method="post" action="http://example.com" {{ form_enctype(form) }}>
...
</form>
@ -497,7 +505,7 @@ UPGRADE FROM 2.x to 3.0
After:
```
```jinja
{{ form_start(form) }}
...
{{ form_end(form) }}
@ -509,7 +517,7 @@ UPGRADE FROM 2.x to 3.0
Alternative 1:
```
```php
$form = $this->createForm('my_form', $formData, array(
'method' => 'PUT',
'action' => $this->generateUrl('target_route'),
@ -518,7 +526,7 @@ UPGRADE FROM 2.x to 3.0
Alternative 2:
```
```php
$form = $this->createFormBuilder($formData)
// ...
->setMethod('PUT')
@ -528,7 +536,7 @@ UPGRADE FROM 2.x to 3.0
It is also possible to override the method and the action in the template:
```
```jinja
{{ form_start(form, {'method': 'GET', 'action': 'http://example.com'}) }}
...
{{ form_end(form) }}
@ -565,7 +573,7 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
use Symfony\Component\Validator\Constraints as Assert;
/**
@ -579,7 +587,7 @@ UPGRADE FROM 2.x to 3.0
After:
```
```php
use Symfony\Component\Validator\Constraints as Assert;
/**
@ -957,13 +965,13 @@ UPGRADE FROM 2.x to 3.0
Before:
```
```php
Yaml::parse($fileName);
```
After:
```
```php
Yaml::parse(file_get_contents($fileName));
### Process

View File

@ -17,7 +17,6 @@
],
"require": {
"php": ">=5.3.3",
"symfony/icu": "~1.0",
"doctrine/common": "~2.2",
"twig/twig": "~1.12",
"psr/log": "~1.0"

View File

@ -24,6 +24,7 @@
<groups>
<exclude>
<group>benchmark</group>
<group>intl-data</group>
</exclude>
</groups>

View File

@ -27,7 +27,10 @@ class AddCacheWarmerPassTest extends \PHPUnit_Framework_TestCase
);
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$container = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('findTaggedServiceIds', 'getDefinition', 'hasDefinition')
);
$container->expects($this->atLeastOnce())
->method('findTaggedServiceIds')
@ -56,7 +59,10 @@ class AddCacheWarmerPassTest extends \PHPUnit_Framework_TestCase
public function testThatCompilerPassIsIgnoredIfThereIsNoCacheWarmerDefinition()
{
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$container = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
);
$container->expects($this->never())->method('findTaggedServiceIds');
$container->expects($this->never())->method('getDefinition');
@ -73,7 +79,10 @@ class AddCacheWarmerPassTest extends \PHPUnit_Framework_TestCase
public function testThatCacheWarmersMightBeNotDefined()
{
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$container = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
);
$container->expects($this->atLeastOnce())
->method('findTaggedServiceIds')

View File

@ -37,7 +37,10 @@ class FragmentRendererPassTest extends \PHPUnit_Framework_TestCase
->method('getClass')
->will($this->returnValue('stdClass'));
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$builder = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
);
$builder->expects($this->any())
->method('hasDefinition')
->will($this->returnValue(true));
@ -73,7 +76,10 @@ class FragmentRendererPassTest extends \PHPUnit_Framework_TestCase
->method('getClass')
->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\RendererService'));
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$builder = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
);
$builder->expects($this->any())
->method('hasDefinition')
->will($this->returnValue(true));

View File

@ -17,6 +17,13 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass;
class ProfilerPassTest extends \PHPUnit_Framework_TestCase
{
private $profilerDefinition;
protected function setUp()
{
$this->profilerDefinition = new Definition('ProfilerClass');
}
/**
* Tests that collectors that specify a template but no "id" will throw
* an exception (both are needed if the template is specified). Thus,
@ -31,10 +38,7 @@ class ProfilerPassTest extends \PHPUnit_Framework_TestCase
'my_collector_service' => array(0 => array('template' => 'foo')),
);
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$builder->expects($this->atLeastOnce())
->method('findTaggedServiceIds')
->will($this->returnValue($services));
$builder = $this->createContainerMock($services);
$this->setExpectedException('InvalidArgumentException');
@ -49,16 +53,11 @@ class ProfilerPassTest extends \PHPUnit_Framework_TestCase
'my_collector_service' => array(0 => array('template' => 'foo', 'id' => 'my_collector')),
);
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$container->expects($this->atLeastOnce())
->method('findTaggedServiceIds')
->will($this->returnValue($services));
$container = $this->createContainerMock($services);
// fake the getDefinition() to return a Profiler definition
$definition = new Definition('ProfilerClass');
$container->expects($this->atLeastOnce())
->method('getDefinition')
->will($this->returnValue($definition));
->method('getDefinition');
// assert that the data_collector.templates parameter should be set
$container->expects($this->once())
@ -69,8 +68,28 @@ class ProfilerPassTest extends \PHPUnit_Framework_TestCase
$profilerPass->process($container);
// grab the method calls off of the "profiler" definition
$methodCalls = $definition->getMethodCalls();
$methodCalls = $this->profilerDefinition->getMethodCalls();
$this->assertCount(1, $methodCalls);
$this->assertEquals('add', $methodCalls[0][0]); // grab the method part of the first call
}
private function createContainerMock($services)
{
$container = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'setParameter')
);
$container->expects($this->any())
->method('hasDefinition')
->with($this->equalTo('profiler'))
->will($this->returnValue(true));
$container->expects($this->any())
->method('getDefinition')
->will($this->returnValue($this->profilerDefinition));
$container->expects($this->atLeastOnce())
->method('findTaggedServiceIds')
->will($this->returnValue($services));
return $container;
}
}

View File

@ -24,7 +24,7 @@ class SerializerPassTest extends \PHPUnit_Framework_TestCase
{
public function testThrowExceptionWhenNoNormalizers()
{
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder', array('hasDefinition', 'findTaggedServiceIds'));
$container->expects($this->once())
->method('hasDefinition')
@ -45,7 +45,10 @@ class SerializerPassTest extends \PHPUnit_Framework_TestCase
public function testThrowExceptionWhenNoEncoders()
{
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$container = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
);
$container->expects($this->once())
->method('hasDefinition')
@ -83,7 +86,7 @@ class SerializerPassTest extends \PHPUnit_Framework_TestCase
new Reference('n3'),
);
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder', array('findTaggedServiceIds'));
$container->expects($this->atLeastOnce())
->method('findTaggedServiceIds')

View File

@ -27,7 +27,10 @@ class TranslatorPassTest extends \PHPUnit_Framework_TestCase
->method('addMethodCall')
->with('addLoader', array('xlf', new Reference('xliff')));
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$container = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'getDefinition', 'findTaggedServiceIds', 'findDefinition')
);
$container->expects($this->any())
->method('hasDefinition')
->will($this->returnValue(true));

View File

@ -46,7 +46,7 @@ class ConstraintValidatorFactoryTest extends \PHPUnit_Framework_TestCase
$validator = $this->getMockForAbstractClass('Symfony\\Component\\Validator\\ConstraintValidator');
// mock ContainerBuilder b/c it implements TaggedContainerInterface
$container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder');
$container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder', array('get'));
$container
->expects($this->once())
->method('get')

View File

@ -19,7 +19,10 @@ class TwigLoaderPassTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$this->builder = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'findTaggedServiceIds', 'setAlias', 'getDefinition')
);
$this->chainLoader = new Definition('loader');
$this->pass = new TwigLoaderPass();
}

View File

@ -9,51 +9,63 @@ standard or the PEAR naming convention.
First, register the autoloader:
require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
```php
require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
use Symfony\Component\ClassLoader\UniversalClassLoader;
use Symfony\Component\ClassLoader\UniversalClassLoader;
$loader = new UniversalClassLoader();
$loader->register();
$loader = new UniversalClassLoader();
$loader->register();
```
Then, register some namespaces with the `registerNamespace()` method:
$loader->registerNamespace('Symfony', __DIR__.'/src');
$loader->registerNamespace('Monolog', __DIR__.'/vendor/monolog/src');
```php
$loader->registerNamespace('Symfony', __DIR__.'/src');
$loader->registerNamespace('Monolog', __DIR__.'/vendor/monolog/src');
```
The `registerNamespace()` method takes a namespace prefix and a path where to
look for the classes as arguments.
You can also register a sub-namespaces:
$loader->registerNamespace('Doctrine\\Common', __DIR__.'/vendor/doctrine-common/lib');
```php
$loader->registerNamespace('Doctrine\\Common', __DIR__.'/vendor/doctrine-common/lib');
```
The order of registration is significant and the first registered namespace
takes precedence over later registered one.
You can also register more than one path for a given namespace:
$loader->registerNamespace('Symfony', array(__DIR__.'/src', __DIR__.'/symfony/src'));
```php
$loader->registerNamespace('Symfony', array(__DIR__.'/src', __DIR__.'/symfony/src'));
```
Alternatively, you can use the `registerNamespaces()` method to register more
than one namespace at once:
$loader->registerNamespaces(array(
'Symfony' => array(__DIR__.'/src', __DIR__.'/symfony/src'),
'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib',
'Doctrine' => __DIR__.'/vendor/doctrine/lib',
'Monolog' => __DIR__.'/vendor/monolog/src',
));
```php
$loader->registerNamespaces(array(
'Symfony' => array(__DIR__.'/src', __DIR__.'/symfony/src'),
'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib',
'Doctrine' => __DIR__.'/vendor/doctrine/lib',
'Monolog' => __DIR__.'/vendor/monolog/src',
));
```
For better performance, you can use the APC based version of the universal
class loader:
require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
require_once __DIR__.'/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
```php
require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
require_once __DIR__.'/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
$loader = new ApcUniversalClassLoader('apc.prefix.');
$loader = new ApcUniversalClassLoader('apc.prefix.');
```
Furthermore, the component provides tools to aggregate classes into a single
file, which is especially useful to improve performance on servers that do not

View File

@ -5,10 +5,12 @@ Console eases the creation of beautiful and testable command line interfaces.
The Application object manages the CLI application:
use Symfony\Component\Console\Application;
```php
use Symfony\Component\Console\Application;
$console = new Application();
$console->run();
$console = new Application();
$console->run();
```
The ``run()`` method parses the arguments and options passed on the command
line and executes the right command.
@ -16,23 +18,25 @@ line and executes the right command.
Registering a new command can easily be done via the ``register()`` method,
which returns a ``Command`` instance:
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
```php
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
$console
->register('ls')
->setDefinition(array(
new InputArgument('dir', InputArgument::REQUIRED, 'Directory name'),
))
->setDescription('Displays the files in the given directory')
->setCode(function (InputInterface $input, OutputInterface $output) {
$dir = $input->getArgument('dir');
$console
->register('ls')
->setDefinition(array(
new InputArgument('dir', InputArgument::REQUIRED, 'Directory name'),
))
->setDescription('Displays the files in the given directory')
->setCode(function (InputInterface $input, OutputInterface $output) {
$dir = $input->getArgument('dir');
$output->writeln(sprintf('Dir listing for <info>%s</info>', $dir));
})
;
$output->writeln(sprintf('Dir listing for <info>%s</info>', $dir));
})
;
```
You can also register new commands via classes.

View File

@ -6,9 +6,11 @@ CssSelector converts CSS selectors to XPath expressions.
The component only goal is to convert CSS selectors to their XPath
equivalents:
use Symfony\Component\CssSelector\CssSelector;
```php
use Symfony\Component\CssSelector\CssSelector;
print CssSelector::toXPath('div.item > h4 > a');
print CssSelector::toXPath('div.item > h4 > a');
```
HTML and XML are different
--------------------------
@ -18,11 +20,13 @@ default. If you need to use this component with `XML` documents, you have to
disable this `HTML` extension. That's because, `HTML` tag & attribute names
are always lower-cased, but case-sensitive in `XML`:
// disable `HTML` extension:
CssSelector::disableHtmlExtension();
```php
// disable `HTML` extension:
CssSelector::disableHtmlExtension();
// re-enable `HTML` extension:
CssSelector::enableHtmlExtension();
// re-enable `HTML` extension:
CssSelector::enableHtmlExtension();
```
When the `HTML` extension is enabled, tag names are lower-cased, attribute
names are lower-cased, the following extra pseudo-classes are supported:

View File

@ -6,23 +6,27 @@ Debug provides tools to make debugging easier.
Enabling all debug tools is as easy as calling the `enable()` method on the
main `Debug` class:
use Symfony\Component\Debug\Debug;
```php
use Symfony\Component\Debug\Debug;
Debug::enable();
Debug::enable();
```
You can also use the tools individually:
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
```php
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
error_reporting(-1);
error_reporting(-1);
ErrorHandler::register($errorReportingLevel);
if ('cli' !== php_sapi_name()) {
ExceptionHandler::register();
} elseif (!ini_get('log_errors') || ini_get('error_log')) {
ini_set('display_errors', 1);
}
ErrorHandler::register($errorReportingLevel);
if ('cli' !== php_sapi_name()) {
ExceptionHandler::register();
} elseif (!ini_get('log_errors') || ini_get('error_log')) {
ini_set('display_errors', 1);
}
```
Note that the `Debug::enable()` call also registers the debug class loader
from the Symfony ClassLoader component when available.

View File

@ -6,45 +6,51 @@ Injection Container.
Here is a simple example that shows how to register services and parameters:
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
```php
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
$sc = new ContainerBuilder();
$sc
->register('foo', '%foo.class%')
->addArgument(new Reference('bar'))
;
$sc->setParameter('foo.class', 'Foo');
$sc = new ContainerBuilder();
$sc
->register('foo', '%foo.class%')
->addArgument(new Reference('bar'))
;
$sc->setParameter('foo.class', 'Foo');
$sc->get('foo');
$sc->get('foo');
```
Method Calls (Setter Injection):
$sc = new ContainerBuilder();
```php
$sc = new ContainerBuilder();
$sc
->register('bar', '%bar.class%')
->addMethodCall('setFoo', array(new Reference('foo')))
;
$sc->setParameter('bar.class', 'Bar');
$sc
->register('bar', '%bar.class%')
->addMethodCall('setFoo', array(new Reference('foo')))
;
$sc->setParameter('bar.class', 'Bar');
$sc->get('bar');
$sc->get('bar');
```
Factory Class:
If your service is retrieved by calling a static method:
$sc = new ContainerBuilder();
```php
$sc = new ContainerBuilder();
$sc
->register('bar', '%bar.class%')
->setFactoryClass('%bar.class%')
->setFactoryMethod('getInstance')
->addArgument('Aarrg!!!')
;
$sc->setParameter('bar.class', 'Bar');
$sc
->register('bar', '%bar.class%')
->setFactoryClass('%bar.class%')
->setFactoryMethod('getInstance')
->addArgument('Aarrg!!!')
;
$sc->setParameter('bar.class', 'Bar');
$sc->get('bar');
$sc->get('bar');
```
File Include:
@ -52,16 +58,18 @@ For some services, especially those that are difficult or impossible to
autoload, you may need the container to include a file before
instantiating your class.
$sc = new ContainerBuilder();
```php
$sc = new ContainerBuilder();
$sc
->register('bar', '%bar.class%')
->setFile('/path/to/file')
->addArgument('Aarrg!!!')
;
$sc->setParameter('bar.class', 'Bar');
$sc
->register('bar', '%bar.class%')
->setFile('/path/to/file')
->addArgument('Aarrg!!!')
;
$sc->setParameter('bar.class', 'Bar');
$sc->get('bar');
$sc->get('bar');
```
Resources
---------

View File

@ -5,22 +5,26 @@ DomCrawler eases DOM navigation for HTML and XML documents.
If you are familiar with jQuery, DomCrawler is a PHP equivalent:
use Symfony\Component\DomCrawler\Crawler;
```php
use Symfony\Component\DomCrawler\Crawler;
$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
print $crawler->filterXPath('descendant-or-self::body/p')->text();
print $crawler->filterXPath('descendant-or-self::body/p')->text();
```
If you are also using the CssSelector component, you can use CSS Selectors
instead of XPath expressions:
use Symfony\Component\DomCrawler\Crawler;
```php
use Symfony\Component\DomCrawler\Crawler;
$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
print $crawler->filter('body > p')->text();
print $crawler->filter('body > p')->text();
```
Resources
---------

View File

@ -64,8 +64,8 @@ interface EventDispatcherInterface
/**
* Removes an event listener from the specified events.
*
* @param string|array $eventName The event(s) to remove a listener from
* @param callable $listener The listener to remove
* @param string $eventName The event to remove a listener from
* @param callable $listener The listener to remove
*/
public function removeListener($eventName, $listener);

View File

@ -4,16 +4,18 @@ EventDispatcher Component
The Symfony2 EventDispatcher component implements the Mediator pattern in a
simple and effective way to make your projects truly extensible.
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
```php
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
$dispatcher = new EventDispatcher();
$dispatcher = new EventDispatcher();
$dispatcher->addListener('event_name', function (Event $event) {
// ...
});
$dispatcher->addListener('event_name', function (Event $event) {
// ...
});
$dispatcher->dispatch('event_name');
$dispatcher->dispatch('event_name');
```
Resources
---------

View File

@ -37,7 +37,10 @@ class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase
->method('getClass')
->will($this->returnValue('stdClass'));
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$builder = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
);
$builder->expects($this->any())
->method('hasDefinition')
->will($this->returnValue(true));
@ -69,7 +72,10 @@ class RegisterListenersPassTest extends \PHPUnit_Framework_TestCase
->method('getClass')
->will($this->returnValue('Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService'));
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
$builder = $this->getMock(
'Symfony\Component\DependencyInjection\ContainerBuilder',
array('hasDefinition', 'findTaggedServiceIds', 'getDefinition')
);
$builder->expects($this->any())
->method('hasDefinition')
->will($this->returnValue(true));

View File

@ -3,32 +3,41 @@ Finder Component
Finder finds files and directories via an intuitive fluent interface.
use Symfony\Component\Finder\Finder;
```php
use Symfony\Component\Finder\Finder;
$finder = new Finder();
$finder = new Finder();
$iterator = $finder
->files()
->name('*.php')
->depth(0)
->size('>= 1K')
->in(__DIR__);
$iterator = $finder
->files()
->name('*.php')
->depth(0)
->size('>= 1K')
->in(__DIR__);
foreach ($iterator as $file) {
print $file->getRealpath()."\n";
}
foreach ($iterator as $file) {
print $file->getRealpath()."\n";
}
```
The iterator returns instances of [Symfony\Component\Finder\SplFileInfo\SplFileInfo][1].
Besides the build-in methods inherited from [\SplFileInfo][2] (`getPerms()`, `getSize()`, ...),
you can also use `getRelativePath()` and `getRelativePathname()`. Read the
[official documentation][3] for more information.
But you can also use it to find files stored remotely like in this example where
we are looking for files on Amazon S3:
$s3 = new \Zend_Service_Amazon_S3($key, $secret);
$s3->registerStreamWrapper("s3");
```php
$s3 = new \Zend_Service_Amazon_S3($key, $secret);
$s3->registerStreamWrapper("s3");
$finder = new Finder();
$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
foreach ($finder->in('s3://bucket-name') as $file) {
print $file->getFilename()."\n";
}
$finder = new Finder();
$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
foreach ($finder->in('s3://bucket-name') as $file) {
print $file->getFilename()."\n";
}
```
Resources
---------
@ -39,3 +48,6 @@ You can run the unit tests with the following command:
$ composer.phar install
$ phpunit
[1]: http://api.symfony.com/2.5/Symfony/Component/Finder/SplFileInfo.html
[2]: http://php.net/splfileinfo
[3]: http://symfony.com/doc/current/components/finder.html#usage

View File

@ -31,7 +31,7 @@ class LanguageTypeTest extends TypeTestCase
$this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false);
$this->assertContains(new ChoiceView('en_GB', 'en_GB', 'British English'), $choices, '', false, false);
$this->assertContains(new ChoiceView('en_US', 'en_US', 'U.S. English'), $choices, '', false, false);
$this->assertContains(new ChoiceView('en_US', 'en_US', 'American English'), $choices, '', false, false);
$this->assertContains(new ChoiceView('fr', 'fr', 'French'), $choices, '', false, false);
$this->assertContains(new ChoiceView('my', 'my', 'Burmese'), $choices, '', false, false);
}

View File

@ -9,21 +9,27 @@ sessions, ...
In this example, we get a Request object from the current PHP global
variables:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
```php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request = Request::createFromGlobals();
echo $request->getPathInfo();
$request = Request::createFromGlobals();
echo $request->getPathInfo();
```
You can also create a Request directly -- that's interesting for unit testing:
$request = Request::create('/?foo=bar', 'GET');
echo $request->getPathInfo();
```php
$request = Request::create('/?foo=bar', 'GET');
echo $request->getPathInfo();
```
And here is how to create and send a Response:
$response = new Response('Not Found', 404, array('Content-Type' => 'text/plain'));
$response->send();
```php
$response = new Response('Not Found', 404, array('Content-Type' => 'text/plain'));
$response->send();
```
The Request and the Response classes have many other methods that implement
the HTTP specification.
@ -33,10 +39,12 @@ Loading
If you are not using Composer but are using PHP 5.3.x, you must add the following to your autoloader:
// SessionHandlerInterface
if (!interface_exists('SessionHandlerInterface')) {
$loader->registerPrefixFallback(__DIR__.'/../vendor/symfony/src/Symfony/Component/HttpFoundation/Resources/stubs');
}
```php
// SessionHandlerInterface
if (!interface_exists('SessionHandlerInterface')) {
$loader->registerPrefixFallback(__DIR__.'/../vendor/symfony/src/Symfony/Component/HttpFoundation/Resources/stubs');
}
```
Resources
---------

View File

@ -7,17 +7,19 @@ frameworks.
``HttpKernelInterface`` is the core interface of the Symfony2 full-stack
framework:
interface HttpKernelInterface
{
/**
* Handles a Request to convert it to a Response.
*
* @param Request $request A Request instance
*
* @return Response A Response instance
*/
function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
}
```php
interface HttpKernelInterface
{
/**
* Handles a Request to convert it to a Response.
*
* @param Request $request A Request instance
*
* @return Response A Response instance
*/
function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
}
```
It takes a ``Request`` as an input and should return a ``Response`` as an
output. Using this interface makes your code compatible with all frameworks
@ -27,28 +29,30 @@ free.
Creating a framework based on the Symfony2 components is really easy. Here is
a very simple, but fully-featured framework based on the Symfony2 components:
$routes = new RouteCollection();
$routes->add('hello', new Route('/hello', array('_controller' =>
function (Request $request) {
return new Response(sprintf("Hello %s", $request->get('name')));
}
)));
```php
$routes = new RouteCollection();
$routes->add('hello', new Route('/hello', array('_controller' =>
function (Request $request) {
return new Response(sprintf("Hello %s", $request->get('name')));
}
)));
$request = Request::createFromGlobals();
$request = Request::createFromGlobals();
$context = new RequestContext();
$context->fromRequest($request);
$context = new RequestContext();
$context->fromRequest($request);
$matcher = new UrlMatcher($routes, $context);
$matcher = new UrlMatcher($routes, $context);
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber(new RouterListener($matcher));
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber(new RouterListener($matcher));
$resolver = new ControllerResolver();
$resolver = new ControllerResolver();
$kernel = new HttpKernel($dispatcher, $resolver);
$kernel = new HttpKernel($dispatcher, $resolver);
$kernel->handle($request)->send();
$kernel->handle($request)->send();
```
This is all you need to create a flexible framework with the Symfony2
components.
@ -56,24 +60,30 @@ components.
Want to add an HTTP reverse proxy and benefit from HTTP caching and Edge Side
Includes?
$kernel = new HttpKernel($dispatcher, $resolver);
```php
$kernel = new HttpKernel($dispatcher, $resolver);
$kernel = new HttpCache($kernel, new Store(__DIR__.'/cache'));
$kernel = new HttpCache($kernel, new Store(__DIR__.'/cache'));
```
Want to functional test this small framework?
$client = new Client($kernel);
$crawler = $client->request('GET', '/hello/Fabien');
```php
$client = new Client($kernel);
$crawler = $client->request('GET', '/hello/Fabien');
$this->assertEquals('Fabien', $crawler->filter('p > span')->text());
$this->assertEquals('Fabien', $crawler->filter('p > span')->text());
```
Want nice error pages instead of ugly PHP exceptions?
$dispatcher->addSubscriber(new ExceptionListener(function (Request $request) {
$msg = 'Something went wrong! ('.$request->get('exception')->getMessage().')';
```php
$dispatcher->addSubscriber(new ExceptionListener(function (Request $request) {
$msg = 'Something went wrong! ('.$request->get('exception')->getMessage().')';
return new Response($msg, 500);
}));
return new Response($msg, 500);
}));
```
And that's why the simple looking ``HttpKernelInterface`` is so powerful. It
gives you access to a lot of cool features, ready to be used out of the box,

View File

@ -17,7 +17,10 @@ class MergeExtensionConfigurationPassTest extends \PHPUnit_Framework_TestCase
{
public function testAutoloadMainExtension()
{
$container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerBuilder');
$container = $this->getMock(
'Symfony\\Component\\DependencyInjection\\ContainerBuilder',
array('getExtensionConfig', 'loadFromExtension', 'getParameterBag')
);
$params = $this->getMock('Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag');
$container->expects($this->at(0))

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Compiler;
namespace Symfony\Component\Intl\Data\Bundle\Compiler;
/**
* Compiles a resource bundle.

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Compiler;
namespace Symfony\Component\Intl\Data\Bundle\Compiler;
use Symfony\Component\Intl\Exception\RuntimeException;
@ -20,7 +20,7 @@ use Symfony\Component\Intl\Exception\RuntimeException;
*
* @internal
*/
class BundleCompiler implements BundleCompilerInterface
class GenrbCompiler implements BundleCompilerInterface
{
/**
* @var string The path to the "genrb" executable.

View File

@ -9,9 +9,9 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Reader;
namespace Symfony\Component\Intl\Data\Bundle\Reader;
use Symfony\Component\Intl\ResourceBundle\Util\RingBuffer;
use Symfony\Component\Intl\Data\Util\RingBuffer;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
@ -53,12 +53,4 @@ class BufferedBundleReader implements BundleReaderInterface
return $this->buffer[$hash];
}
/**
* {@inheritdoc}
*/
public function getLocales($path)
{
return $this->reader->getLocales($path);
}
}

View File

@ -9,24 +9,24 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Reader;
namespace Symfony\Component\Intl\Data\Bundle\Reader;
use Symfony\Component\Intl\Exception\MissingResourceException;
use Symfony\Component\Intl\Exception\OutOfBoundsException;
use Symfony\Component\Intl\Exception\ResourceBundleNotFoundException;
use Symfony\Component\Intl\Locale;
use Symfony\Component\Intl\ResourceBundle\Util\RecursiveArrayAccess;
use Symfony\Component\Intl\Data\Util\RecursiveArrayAccess;
/**
* Default implementation of {@link StructuredBundleReaderInterface}.
* Default implementation of {@link BundleEntryReaderInterface}.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @see StructuredResourceBundleBundleReaderInterface
* @see BundleEntryReaderInterface
*
* @internal
*/
class StructuredBundleReader implements StructuredBundleReaderInterface
class BundleEntryReader implements BundleEntryReaderInterface
{
/**
* @var BundleReaderInterface
@ -138,7 +138,7 @@ class StructuredBundleReader implements StructuredBundleReaderInterface
}
// Remember which locales we tried
$testedLocales[] = $currentLocale.'.res';
$testedLocales[] = $currentLocale;
// Check whether fallback is allowed
if (!$fallback) {
@ -162,10 +162,10 @@ class StructuredBundleReader implements StructuredBundleReaderInterface
// Entry is still NULL, read error occurred. Throw an exception
// containing the detailed path and locale
$errorMessage = sprintf(
'Couldn\'t read the indices [%s] from "%s/%s.res".',
'Couldn\'t read the indices [%s] for the locale "%s" in "%s".',
implode('][', $indices),
$path,
$locale
$locale,
$path
);
// Append fallback locales, if any
@ -174,19 +174,11 @@ class StructuredBundleReader implements StructuredBundleReaderInterface
array_shift($testedLocales);
$errorMessage .= sprintf(
' The indices also couldn\'t be found in the fallback locale(s) "%s".',
' The indices also couldn\'t be found for the fallback locale(s) "%s".',
implode('", "', $testedLocales)
);
}
throw new MissingResourceException($errorMessage, 0, $exception);
}
/**
* {@inheritdoc}
*/
public function getLocales($path)
{
return $this->reader->getLocales($path);
}
}

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Reader;
namespace Symfony\Component\Intl\Data\Bundle\Reader;
use Symfony\Component\Intl\Exception\MissingResourceException;
@ -20,7 +20,7 @@ use Symfony\Component\Intl\Exception\MissingResourceException;
*
* @internal
*/
interface StructuredBundleReaderInterface extends BundleReaderInterface
interface BundleEntryReaderInterface extends BundleReaderInterface
{
/**
* Reads an entry from a resource bundle.

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Reader;
namespace Symfony\Component\Intl\Data\Bundle\Reader;
/**
* Reads resource bundle files.
@ -30,13 +30,4 @@ interface BundleReaderInterface
* complex data, a scalar value otherwise.
*/
public function read($path, $locale);
/**
* Reads the available locales of a resource bundle.
*
* @param string $path The path to the resource bundle.
*
* @return string[] A list of supported locale codes.
*/
public function getLocales($path);
}

View File

@ -9,10 +9,10 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Reader;
namespace Symfony\Component\Intl\Data\Bundle\Reader;
use Symfony\Component\Intl\Exception\ResourceBundleNotFoundException;
use Symfony\Component\Intl\ResourceBundle\Util\ArrayAccessibleResourceBundle;
use Symfony\Component\Intl\Data\Util\ArrayAccessibleResourceBundle;
/**
* Reads binary .res resource bundles.
@ -21,7 +21,7 @@ use Symfony\Component\Intl\ResourceBundle\Util\ArrayAccessibleResourceBundle;
*
* @internal
*/
class BinaryBundleReader implements BundleReaderInterface
class IntlBundleReader implements BundleReaderInterface
{
/**
* {@inheritdoc}
@ -52,18 +52,4 @@ class BinaryBundleReader implements BundleReaderInterface
// which are OK for us.
return new ArrayAccessibleResourceBundle($bundle);
}
/**
* {@inheritdoc}
*/
public function getLocales($path)
{
$locales = glob($path.'/*.res');
// Remove file extension and sort
array_walk($locales, function (&$locale) { $locale = basename($locale, '.res'); });
sort($locales);
return $locales;
}
}

View File

@ -0,0 +1,89 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Bundle\Reader;
use Symfony\Component\Intl\Exception\ResourceBundleNotFoundException;
use Symfony\Component\Intl\Exception\RuntimeException;
/**
* Reads .json resource bundles.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class JsonBundleReader implements BundleReaderInterface
{
/**
* {@inheritdoc}
*/
public function read($path, $locale)
{
$fileName = $path.'/'.$locale.'.json';
if (!file_exists($fileName)) {
throw new ResourceBundleNotFoundException(sprintf(
'The resource bundle "%s/%s.json" does not exist.',
$path,
$locale
));
}
if (!is_file($fileName)) {
throw new RuntimeException(sprintf(
'The resource bundle "%s/%s.json" is not a file.',
$path,
$locale
));
}
$data = json_decode(file_get_contents($fileName), true);
if (null === $data) {
throw new RuntimeException(sprintf(
'The resource bundle "%s/%s.json" contains invalid JSON: %s',
$path,
$locale,
self::getLastJsonError()
));
}
return $data;
}
/**
* @return string The last error message created by {@link json_decode()}
*
* @link http://de2.php.net/manual/en/function.json-last-error-msg.php#113243
*/
private static function getLastJsonError()
{
if (function_exists('json_last_error_msg')) {
return json_last_error_msg();
}
static $errors = array(
JSON_ERROR_NONE => null,
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
);
$error = json_last_error();
return array_key_exists($error, $errors)
? $errors[$error]
: sprintf('Unknown error (%s)', $error);
}
}

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Reader;
namespace Symfony\Component\Intl\Data\Bundle\Reader;
use Symfony\Component\Intl\Exception\ResourceBundleNotFoundException;
use Symfony\Component\Intl\Exception\RuntimeException;
@ -48,18 +48,4 @@ class PhpBundleReader implements BundleReaderInterface
return include $fileName;
}
/**
* {@inheritdoc}
*/
public function getLocales($path)
{
$locales = glob($path.'/*.php');
// Remove file extension and sort
array_walk($locales, function (&$locale) { $locale = basename($locale, '.php'); });
sort($locales);
return $locales;
}
}

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Writer;
namespace Symfony\Component\Intl\Data\Bundle\Writer;
/**
* Writes resource bundle files.

View File

@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Bundle\Writer;
/**
* Writes .json resource bundles.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class JsonBundleWriter implements BundleWriterInterface
{
/**
* {@inheritdoc}
*/
public function write($path, $locale, $data)
{
if ($data instanceof \Traversable) {
$data = iterator_to_array($data);
}
array_walk_recursive($data, function (&$value) {
if ($value instanceof \Traversable) {
$value = iterator_to_array($value);
}
});
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
// Use JSON_PRETTY_PRINT so that we can see what changed in Git diffs
file_put_contents(
$path.'/'.$locale.'.json',
json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)."\n"
);
} else {
file_put_contents($path.'/'.$locale.'.json', json_encode($data)."\n");
}
}
}

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Writer;
namespace Symfony\Component\Intl\Data\Bundle\Writer;
/**
* Writes .php resource bundles.
@ -28,19 +28,20 @@ class PhpBundleWriter implements BundleWriterInterface
$template = <<<TEMPLATE
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
return %s;
TEMPLATE;
if ($data instanceof \Traversable) {
$data = iterator_to_array($data);
}
array_walk_recursive($data, function (&$value) {
if ($value instanceof \Traversable) {
$value = iterator_to_array($value);
}
});
$data = var_export($data, true);
$data = preg_replace('/array \(/', 'array(', $data);
$data = preg_replace('/\n {1,10}array\(/', 'array(', $data);

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Writer;
namespace Symfony\Component\Intl\Data\Bundle\Writer;
use Symfony\Component\Intl\Exception\UnexpectedTypeException;

View File

@ -0,0 +1,143 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Generator;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleReaderInterface;
use Symfony\Component\Intl\Data\Util\LocaleScanner;
use Symfony\Component\Intl\Data\Bundle\Compiler\GenrbCompiler;
use Symfony\Component\Intl\Data\Bundle\Reader\IntlBundleReader;
/**
* The rule for compiling the currency bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
abstract class AbstractDataGenerator
{
/**
* @var GenrbCompiler
*/
private $compiler;
/**
* @var string
*/
private $dirName;
public function __construct(GenrbCompiler $compiler, $dirName)
{
$this->compiler = $compiler;
$this->dirName = $dirName;
}
/**
* {@inheritdoc}
*/
public function generateData(GeneratorConfig $config)
{
$filesystem = new Filesystem();
$localeScanner = new LocaleScanner();
$reader = new IntlBundleReader();
$writers = $config->getBundleWriters();
$tempDir = sys_get_temp_dir().'/icu-data-'.$this->dirName;
// Prepare filesystem directories
foreach ($writers as $targetDir => $writer) {
$filesystem->remove($targetDir.'/'.$this->dirName);
$filesystem->mkdir($targetDir.'/'.$this->dirName);
}
$filesystem->remove($tempDir);
$filesystem->mkdir($tempDir);
$locales = $this->scanLocales($localeScanner, $config->getSourceDir());
$this->compileTemporaryBundles($this->compiler, $config->getSourceDir(), $tempDir);
$this->preGenerate();
foreach ($locales as $locale) {
$localeData = $this->generateDataForLocale($reader, $tempDir, $locale);
if (null !== $localeData) {
foreach ($writers as $targetDir => $writer) {
$writer->write($targetDir.'/'.$this->dirName, $locale, $localeData);
}
}
}
$rootData = $this->generateDataForRoot($reader, $tempDir);
if (null !== $rootData) {
foreach ($writers as $targetDir => $writer) {
$writer->write($targetDir.'/'.$this->dirName, 'root', $rootData);
}
}
$metaData = $this->generateDataForMeta($reader, $tempDir);
if (null !== $metaData) {
foreach ($writers as $targetDir => $writer) {
$writer->write($targetDir.'/'.$this->dirName, 'meta', $metaData);
}
}
// Clean up
$filesystem->remove($tempDir);
}
/**
* @param LocaleScanner $scanner
* @param string $sourceDir
*
* @return string[]
*/
abstract protected function scanLocales(LocaleScanner $scanner, $sourceDir);
/**
* @param GenrbCompiler $compiler
* @param string $sourceDir
* @param string $tempDir
*/
abstract protected function compileTemporaryBundles(GenrbCompiler $compiler, $sourceDir, $tempDir);
abstract protected function preGenerate();
/**
* @param BundleReaderInterface $reader
* @param string $tempDir
* @param string $displayLocale
*
* @return array|null
*/
abstract protected function generateDataForLocale(BundleReaderInterface $reader, $tempDir, $displayLocale);
/**
* @param BundleReaderInterface $reader
* @param string $tempDir
*
* @return array|null
*/
abstract protected function generateDataForRoot(BundleReaderInterface $reader, $tempDir);
/**
* @param BundleReaderInterface $reader
* @param string $tempDir
*
* @return array|null
*/
abstract protected function generateDataForMeta(BundleReaderInterface $reader, $tempDir);
}

View File

@ -0,0 +1,217 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Generator;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleReaderInterface;
use Symfony\Component\Intl\Data\Util\ArrayAccessibleResourceBundle;
use Symfony\Component\Intl\Data\Bundle\Compiler\GenrbCompiler;
use Symfony\Component\Intl\Data\Util\LocaleScanner;
/**
* The rule for compiling the currency bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class CurrencyDataGenerator extends AbstractDataGenerator
{
const UNKNOWN_CURRENCY_ID = 'XXX';
const EUROPEAN_COMPOSITE_UNIT_ID = 'XBA';
const EUROPEAN_MONETARY_UNIT_ID = 'XBB';
const EUROPEAN_UNIT_OF_ACCOUNT_XBC_ID = 'XBC';
const EUROPEAN_UNIT_OF_ACCOUNT_XBD_ID = 'XBD';
const TESTING_CURRENCY_CODE_ID = 'XTS';
const ADB_UNIT_OF_ACCOUNT_ID = 'XUA';
const GOLD_ID = 'XAU';
const SILVER_ID = 'XAG';
const PLATINUM_ID = 'XPT';
const PALLADIUM_ID = 'XPD';
const SUCRE_ID = 'XSU';
const SPECIAL_DRAWING_RIGHTS_ID = 'XDR';
/**
* Monetary units excluded from generation.
*
* @var array
*/
private static $blacklist = array(
self::UNKNOWN_CURRENCY_ID => true,
self::EUROPEAN_COMPOSITE_UNIT_ID => true,
self::EUROPEAN_MONETARY_UNIT_ID => true,
self::EUROPEAN_UNIT_OF_ACCOUNT_XBC_ID => true,
self::EUROPEAN_UNIT_OF_ACCOUNT_XBD_ID => true,
self::TESTING_CURRENCY_CODE_ID => true,
self::ADB_UNIT_OF_ACCOUNT_ID => true,
self::GOLD_ID => true,
self::SILVER_ID => true,
self::PLATINUM_ID => true,
self::PALLADIUM_ID => true,
self::SUCRE_ID => true,
self::SPECIAL_DRAWING_RIGHTS_ID => true,
);
/**
* Collects all available currency codes
*
* @var string[]
*/
private $currencyCodes = array();
/**
* {@inheritdoc}
*/
protected function scanLocales(LocaleScanner $scanner, $sourceDir)
{
return $scanner->scanLocales($sourceDir.'/curr');
}
/**
* {@inheritdoc}
*/
protected function compileTemporaryBundles(GenrbCompiler $compiler, $sourceDir, $tempDir)
{
$compiler->compile($sourceDir.'/curr', $tempDir);
$compiler->compile($sourceDir.'/misc/currencyNumericCodes.txt', $tempDir);
}
/**
* {@inheritdoc}
*/
protected function preGenerate()
{
$this->currencyCodes = array();
}
/**
* {@inheritdoc}
*/
protected function generateDataForLocale(BundleReaderInterface $reader, $tempDir, $displayLocale)
{
$localeBundle = $reader->read($tempDir, $displayLocale);
if (isset($localeBundle['Currencies']) && null !== $localeBundle['Currencies']) {
$data = array(
'Version' => $localeBundle['Version'],
'Names' => $this->generateSymbolNamePairs($localeBundle),
);
$this->currencyCodes = array_merge($this->currencyCodes, array_keys($data['Names']));
return $data;
}
return;
}
/**
* {@inheritdoc}
*/
protected function generateDataForRoot(BundleReaderInterface $reader, $tempDir)
{
$rootBundle = $reader->read($tempDir, 'root');
return array(
'Version' => $rootBundle['Version'],
'Names' => $this->generateSymbolNamePairs($rootBundle),
);
}
/**
* {@inheritdoc}
*/
protected function generateDataForMeta(BundleReaderInterface $reader, $tempDir)
{
$rootBundle = $reader->read($tempDir, 'root');
$supplementalDataBundle = $reader->read($tempDir, 'supplementalData');
$numericCodesBundle = $reader->read($tempDir, 'currencyNumericCodes');
$this->currencyCodes = array_unique($this->currencyCodes);
sort($this->currencyCodes);
$data = array(
'Version' => $rootBundle['Version'],
'Currencies' => $this->currencyCodes,
'Meta' => $this->generateCurrencyMeta($supplementalDataBundle),
'Alpha3ToNumeric' => $this->generateAlpha3ToNumericMapping($numericCodesBundle, $this->currencyCodes),
);
$data['NumericToAlpha3'] = $this->generateNumericToAlpha3Mapping($data['Alpha3ToNumeric']);
return $data;
}
/**
* @param $rootBundle
*
* @return array
*/
private function generateSymbolNamePairs(ArrayAccessibleResourceBundle $rootBundle)
{
$symbolNamePairs = iterator_to_array($rootBundle['Currencies']);
// Remove unwanted currencies
$symbolNamePairs = array_diff_key($symbolNamePairs, self::$blacklist);
return $symbolNamePairs;
}
private function generateCurrencyMeta(ArrayAccessibleResourceBundle $supplementalDataBundle)
{
// The metadata is already de-duplicated. It contains one key "DEFAULT"
// which is used for currencies that don't have dedicated entries.
return iterator_to_array($supplementalDataBundle['CurrencyMeta']);
}
private function generateAlpha3ToNumericMapping(ArrayAccessibleResourceBundle $numericCodesBundle, array $currencyCodes)
{
$alpha3ToNumericMapping = iterator_to_array($numericCodesBundle['codeMap']);
asort($alpha3ToNumericMapping);
// Filter unknown currencies (e.g. "AYM")
$alpha3ToNumericMapping = array_intersect_key($alpha3ToNumericMapping, array_flip($currencyCodes));
return $alpha3ToNumericMapping;
}
private function generateNumericToAlpha3Mapping(array $alpha3ToNumericMapping)
{
$numericToAlpha3Mapping = array();
foreach ($alpha3ToNumericMapping as $alpha3 => $numeric) {
// Make sure that the mapping is stored as table and not as array
$numeric = (string) $numeric;
if (!isset($numericToAlpha3Mapping[$numeric])) {
$numericToAlpha3Mapping[$numeric] = array();
}
$numericToAlpha3Mapping[$numeric][] = $alpha3;
}
return $numericToAlpha3Mapping;
}
}

View File

@ -0,0 +1,87 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Generator;
use Symfony\Component\Intl\Data\Bundle\Writer\BundleWriterInterface;
/**
* Stores contextual information for resource bundle generation.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class GeneratorConfig
{
/**
* @var string
*/
private $sourceDir;
/**
* @var string
*/
private $icuVersion;
/**
* @var BundleWriterInterface[]
*/
private $bundleWriters = array();
public function __construct($sourceDir, $icuVersion)
{
$this->sourceDir = $sourceDir;
$this->icuVersion = $icuVersion;
}
/**
* Adds a writer to be used during the data conversion.
*
* @param string $targetDir The output directory
* @param BundleWriterInterface $writer The writer instance
*/
public function addBundleWriter($targetDir, BundleWriterInterface $writer)
{
$this->bundleWriters[$targetDir] = $writer;
}
/**
* Returns the writers indexed by their output directories.
*
* @return BundleWriterInterface[]
*/
public function getBundleWriters()
{
return $this->bundleWriters;
}
/**
* Returns the directory where the source versions of the resource bundles
* are stored.
*
* @return string An absolute path to a directory.
*/
public function getSourceDir()
{
return $this->sourceDir;
}
/**
* Returns the ICU version of the bundles being converted.
*
* @return string The ICU version string.
*/
public function getIcuVersion()
{
return $this->icuVersion;
}
}

View File

@ -0,0 +1,211 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Generator;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleReaderInterface;
use Symfony\Component\Intl\Data\Util\ArrayAccessibleResourceBundle;
use Symfony\Component\Intl\Data\Util\LocaleScanner;
use Symfony\Component\Intl\Exception\RuntimeException;
use Symfony\Component\Intl\Data\Bundle\Compiler\GenrbCompiler;
/**
* The rule for compiling the language bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class LanguageDataGenerator extends AbstractDataGenerator
{
/**
* Source: http://www-01.sil.org/iso639-3/codes.asp
*
* @var array
*/
private static $preferredAlpha2ToAlpha3Mapping = array(
'ak' => 'aka',
'ar' => 'ara',
'ay' => 'aym',
'az' => 'aze',
'bo' => 'bod',
'cr' => 'cre',
'cs' => 'ces',
'cy' => 'cym',
'de' => 'deu',
'el' => 'ell',
'et' => 'est',
'eu' => 'eus',
'fa' => 'fas',
'ff' => 'ful',
'fr' => 'fra',
'gn' => 'grn',
'hy' => 'hye',
'ik' => 'ipk',
'is' => 'isl',
'iu' => 'iku',
'ka' => 'kat',
'kr' => 'kau',
'kg' => 'kon',
'kv' => 'kom',
'ku' => 'kur',
'lv' => 'lav',
'mg' => 'mlg',
'mi' => 'mri',
'mk' => 'mkd',
'mn' => 'mon',
'ms' => 'msa',
'my' => 'mya',
'nb' => 'nob',
'ne' => 'nep',
'nl' => 'nld',
'oj' => 'oji',
'om' => 'orm',
'or' => 'ori',
'ps' => 'pus',
'qu' => 'que',
'ro' => 'ron',
'sc' => 'srd',
'sk' => 'slk',
'sq' => 'sqi',
'sw' => 'swa',
'uz' => 'uzb',
'yi' => 'yid',
'za' => 'zha',
'zh' => 'zho',
);
/**
* Collects all available language codes
*
* @var string[]
*/
private $languageCodes = array();
/**
* {@inheritdoc}
*/
protected function scanLocales(LocaleScanner $scanner, $sourceDir)
{
return $scanner->scanLocales($sourceDir.'/lang');
}
/**
* {@inheritdoc}
*/
protected function compileTemporaryBundles(GenrbCompiler $compiler, $sourceDir, $tempDir)
{
$compiler->compile($sourceDir.'/lang', $tempDir);
$compiler->compile($sourceDir.'/misc/metadata.txt', $tempDir);
}
/**
* {@inheritdoc}
*/
protected function preGenerate()
{
$this->languageCodes = array();
}
/**
* {@inheritdoc}
*/
protected function generateDataForLocale(BundleReaderInterface $reader, $tempDir, $displayLocale)
{
$localeBundle = $reader->read($tempDir, $displayLocale);
// isset() on \ResourceBundle returns true even if the value is null
if (isset($localeBundle['Languages']) && null !== $localeBundle['Languages']) {
$data = array(
'Version' => $localeBundle['Version'],
'Names' => iterator_to_array($localeBundle['Languages']),
);
$this->languageCodes = array_merge($this->languageCodes, array_keys($data['Names']));
return $data;
}
return;
}
/**
* {@inheritdoc}
*/
protected function generateDataForRoot(BundleReaderInterface $reader, $tempDir)
{
return;
}
/**
* {@inheritdoc}
*/
protected function generateDataForMeta(BundleReaderInterface $reader, $tempDir)
{
$rootBundle = $reader->read($tempDir, 'root');
$metadataBundle = $reader->read($tempDir, 'metadata');
$this->languageCodes = array_unique($this->languageCodes);
sort($this->languageCodes);
return array(
'Version' => $rootBundle['Version'],
'Languages' => $this->languageCodes,
'Aliases' => $metadataBundle['languageAlias'],
'Alpha2ToAlpha3' => $this->generateAlpha2ToAlpha3Mapping($metadataBundle),
);
}
private function generateAlpha2ToAlpha3Mapping(ArrayAccessibleResourceBundle $metadataBundle)
{
$aliases = $metadataBundle['languageAlias'];
$alpha2ToAlpha3 = array();
foreach ($aliases as $alias => $language) {
if (2 === strlen($language) && 3 === strlen($alias)) {
if (isset(self::$preferredAlpha2ToAlpha3Mapping[$language])) {
// Validate to prevent typos
if (!isset($aliases[self::$preferredAlpha2ToAlpha3Mapping[$language]])) {
throw new RuntimeException(
'The statically set three-letter mapping '.
self::$preferredAlpha2ToAlpha3Mapping[$language].' '.
'for the language code '.$language.' seems to be '.
'invalid. Typo?'
);
}
$alpha3 = self::$preferredAlpha2ToAlpha3Mapping[$language];
if ($language !== $aliases[$alpha3]) {
throw new RuntimeException(
'The statically set three-letter mapping '.$alpha3.' '.
'for the language code '.$language.' seems to be '.
'an alias for '.$aliases[$alpha3].'. Wrong mapping?'
);
}
$alpha2ToAlpha3[$language] = $alpha3;
} elseif (isset($alpha2ToAlpha3[$language])) {
throw new RuntimeException(
'Multiple three-letter mappings exist for the language '.
'code '.$language.'. Please add one of them to the '.
'property $preferredAlpha2ToAlpha3Mapping.'
);
} else {
$alpha2ToAlpha3[$language] = $alias;
}
}
}
return $alpha2ToAlpha3;
}
}

View File

@ -0,0 +1,252 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Generator;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Intl\Data\Provider\LanguageDataProvider;
use Symfony\Component\Intl\Data\Provider\RegionDataProvider;
use Symfony\Component\Intl\Data\Provider\ScriptDataProvider;
use Symfony\Component\Intl\Data\Util\LocaleScanner;
use Symfony\Component\Intl\Exception\MissingResourceException;
use Symfony\Component\Intl\Exception\ResourceBundleNotFoundException;
use Symfony\Component\Intl\Locale;
/**
* The rule for compiling the locale bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class LocaleDataGenerator
{
/**
* @var string
*/
private $dirName;
/**
* @var LanguageDataProvider
*/
private $languageDataProvider;
/**
* @var ScriptDataProvider
*/
private $scriptDataProvider;
/**
* @var RegionDataProvider
*/
private $regionDataProvider;
public function __construct($dirName, LanguageDataProvider $languageDataProvider, ScriptDataProvider $scriptDataProvider, RegionDataProvider $regionDataProvider)
{
$this->dirName = $dirName;
$this->languageDataProvider = $languageDataProvider;
$this->scriptDataProvider = $scriptDataProvider;
$this->regionDataProvider = $regionDataProvider;
}
/**
* {@inheritdoc}
*/
public function generateData(GeneratorConfig $config)
{
$filesystem = new Filesystem();
$localeScanner = new LocaleScanner();
$writers = $config->getBundleWriters();
// Prepare filesystem directories
foreach ($writers as $targetDir => $writer) {
$filesystem->remove($targetDir.'/'.$this->dirName);
$filesystem->mkdir($targetDir.'/'.$this->dirName);
}
$locales = $localeScanner->scanLocales($config->getSourceDir().'/locales');
$aliases = $localeScanner->scanAliases($config->getSourceDir().'/locales');
// Flip to facilitate lookup
$flippedLocales = array_flip($locales);
// Don't generate names for aliases (names will be generated for the
// locale they are duplicating)
$displayLocales = array_diff_key($flippedLocales, $aliases);
ksort($displayLocales);
// Generate a list of (existing) locale fallbacks
$fallbackMapping = $this->generateFallbackMapping($displayLocales, $aliases);
$localeNames = array();
// Generate locale names for all locales that have translations in
// at least the language or the region bundle
foreach ($displayLocales as $displayLocale => $_) {
$localeNames[$displayLocale] = array();
foreach ($locales as $locale) {
try {
// Generate a locale name in the language of each display locale
// Each locale name has the form: "Language (Script, Region, Variant1, ...)
// Script, Region and Variants are optional. If none of them is
// available, the braces are not printed.
if (null !== ($name = $this->generateLocaleName($locale, $displayLocale))) {
$localeNames[$displayLocale][$locale] = $name;
}
} catch (MissingResourceException $e) {
} catch (ResourceBundleNotFoundException $e) {
}
}
}
// Process again to de-duplicate locales and their fallback locales
// Only keep the differences
foreach ($displayLocales as $displayLocale => $_) {
$fallback = $displayLocale;
while (isset($fallbackMapping[$fallback])) {
$fallback = $fallbackMapping[$fallback];
$localeNames[$displayLocale] = array_diff(
$localeNames[$displayLocale],
$localeNames[$fallback]
);
}
// If no names remain to be saved for the current locale, skip it
if (0 === count($localeNames[$displayLocale])) {
continue;
}
foreach ($writers as $targetDir => $writer) {
$writer->write($targetDir.'/'.$this->dirName, $displayLocale, array(
'Names' => $localeNames[$displayLocale],
));
}
}
// Generate aliases, needed to enable proper fallback from alias to its
// target
foreach ($aliases as $alias => $aliasOf) {
foreach ($writers as $targetDir => $writer) {
$writer->write($targetDir.'/'.$this->dirName, $alias, array(
'%%ALIAS' => $aliasOf,
));
}
}
// Create root file which maps locale codes to locale codes, for fallback
foreach ($writers as $targetDir => $writer) {
$writer->write($targetDir.'/'.$this->dirName, 'meta', array(
'Locales' => $locales,
'Aliases' => $aliases,
));
}
}
private function generateLocaleName($locale, $displayLocale)
{
$name = null;
$lang = \Locale::getPrimaryLanguage($locale);
$script = \Locale::getScript($locale);
$region = \Locale::getRegion($locale);
$variants = \Locale::getAllVariants($locale);
// Currently the only available variant is POSIX, which we don't want
// to include in the list
if (count($variants) > 0) {
return;
}
// Some languages are translated together with their region,
// i.e. "en_GB" is translated as "British English"
// we don't include these languages though because they mess up
// the name sorting
// $name = $this->langBundle->getLanguageName($displayLocale, $lang, $region);
// Some languages are simply not translated
// Example: "az" (Azerbaijani) has no translation in "af" (Afrikaans)
if (null === ($name = $this->languageDataProvider->getName($lang, $displayLocale))) {
return;
}
// "as" (Assamese) has no "Variants" block
//if (!$langBundle->get('Variants')) {
// continue;
//}
$extras = array();
// Discover the name of the script part of the locale
// i.e. in zh_Hans_MO, "Hans" is the script
if ($script) {
// Some scripts are not translated into every language
if (null === ($scriptName = $this->scriptDataProvider->getName($script, $displayLocale))) {
return;
}
$extras[] = $scriptName;
}
// Discover the name of the region part of the locale
// i.e. in de_AT, "AT" is the region
if ($region) {
// Some regions are not translated into every language
if (null === ($regionName = $this->regionDataProvider->getName($region, $displayLocale))) {
return;
}
$extras[] = $regionName;
}
if (count($extras) > 0) {
// Remove any existing extras
// For example, in German, zh_Hans is "Chinesisch (vereinfacht)".
// The latter is the script part which is already included in the
// extras and will be appended again with the other extras.
if (preg_match('/^(.+)\s+\([^\)]+\)$/', $name, $matches)) {
$name = $matches[1];
}
$name .= ' ('.implode(', ', $extras).')';
}
return $name;
}
private function generateFallbackMapping(array $displayLocales, array $aliases)
{
$mapping = array();
foreach ($displayLocales as $displayLocale => $_) {
$mapping[$displayLocale] = null;
$fallback = $displayLocale;
// Recursively search for a fallback locale until one is found
while (null !== ($fallback = Locale::getFallback($fallback))) {
// Currently, no locale has an alias as fallback locale.
// If this starts to be the case, we need to add code here.
assert(!isset($aliases[$fallback]));
// Check whether the fallback exists
if (isset($displayLocales[$fallback])) {
$mapping[$displayLocale] = $fallback;
break;
}
}
}
return $mapping;
}
}

View File

@ -0,0 +1,163 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Generator;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleReaderInterface;
use Symfony\Component\Intl\Data\Util\ArrayAccessibleResourceBundle;
use Symfony\Component\Intl\Data\Bundle\Compiler\GenrbCompiler;
use Symfony\Component\Intl\Data\Util\LocaleScanner;
use Symfony\Component\Intl\Region;
/**
* The rule for compiling the region bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @link http://source.icu-project.org/repos/icu/icu4j/trunk/main/classes/core/src/com/ibm/icu/util/Region.java
*
* @internal
*/
class RegionDataGenerator extends AbstractDataGenerator
{
const UNKNOWN_REGION_ID = 'ZZ';
const OUTLYING_OCEANIA_REGION_ID = 'QO';
const EUROPEAN_UNION_ID = 'EU';
const NETHERLANDS_ANTILLES_ID = 'AN';
const BOUVET_ISLAND_ID = 'BV';
const HEARD_MCDONALD_ISLANDS_ID = 'HM';
const CLIPPERTON_ISLAND_ID = 'CP';
/**
* Regions excluded from generation.
*
* @var array
*/
private static $blacklist = array(
self::UNKNOWN_REGION_ID => true,
// Look like countries, but are sub-continents
self::OUTLYING_OCEANIA_REGION_ID => true,
self::EUROPEAN_UNION_ID => true,
// No longer exists
self::NETHERLANDS_ANTILLES_ID => true,
// Uninhabited islands
self::BOUVET_ISLAND_ID => true,
self::HEARD_MCDONALD_ISLANDS_ID => true,
self::CLIPPERTON_ISLAND_ID => true,
);
/**
* Collects all available language codes
*
* @var string[]
*/
private $regionCodes = array();
/**
* {@inheritdoc}
*/
protected function scanLocales(LocaleScanner $scanner, $sourceDir)
{
return $scanner->scanLocales($sourceDir.'/region');
}
/**
* {@inheritdoc}
*/
protected function compileTemporaryBundles(GenrbCompiler $compiler, $sourceDir, $tempDir)
{
$compiler->compile($sourceDir.'/region', $tempDir);
}
/**
* {@inheritdoc}
*/
protected function preGenerate()
{
$this->regionCodes = array();
}
/**
* {@inheritdoc}
*/
protected function generateDataForLocale(BundleReaderInterface $reader, $tempDir, $displayLocale)
{
$localeBundle = $reader->read($tempDir, $displayLocale);
// isset() on \ResourceBundle returns true even if the value is null
if (isset($localeBundle['Countries']) && null !== $localeBundle['Countries']) {
$data = array(
'Version' => $localeBundle['Version'],
'Names' => $this->generateRegionNames($localeBundle),
);
$this->regionCodes = array_merge($this->regionCodes, array_keys($data['Names']));
return $data;
}
}
/**
* {@inheritdoc}
*/
protected function generateDataForRoot(BundleReaderInterface $reader, $tempDir)
{
}
/**
* {@inheritdoc}
*/
protected function generateDataForMeta(BundleReaderInterface $reader, $tempDir)
{
$rootBundle = $reader->read($tempDir, 'root');
$this->regionCodes = array_unique($this->regionCodes);
sort($this->regionCodes);
return array(
'Version' => $rootBundle['Version'],
'Regions' => $this->regionCodes,
);
}
/**
* @param $localeBundle
*
* @return array
*/
protected function generateRegionNames(ArrayAccessibleResourceBundle $localeBundle)
{
$unfilteredRegionNames = iterator_to_array($localeBundle['Countries']);
$regionNames = array();
foreach ($unfilteredRegionNames as $region => $regionName) {
if (isset(self::$blacklist[$region])) {
continue;
}
// WORLD/CONTINENT/SUBCONTINENT/GROUPING
if (ctype_digit($region) || is_int($region)) {
continue;
}
$regionNames[$region] = $regionName;
}
return $regionNames;
}
}

View File

@ -0,0 +1,101 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Generator;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleReaderInterface;
use Symfony\Component\Intl\Data\Bundle\Compiler\GenrbCompiler;
use Symfony\Component\Intl\Data\Util\LocaleScanner;
/**
* The rule for compiling the script bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class ScriptDataGenerator extends AbstractDataGenerator
{
/**
* Collects all available language codes
*
* @var string[]
*/
private $scriptCodes = array();
/**
* {@inheritdoc}
*/
protected function scanLocales(LocaleScanner $scanner, $sourceDir)
{
return $scanner->scanLocales($sourceDir.'/lang');
}
/**
* {@inheritdoc}
*/
protected function compileTemporaryBundles(GenrbCompiler $compiler, $sourceDir, $tempDir)
{
$compiler->compile($sourceDir.'/lang', $tempDir);
}
/**
* {@inheritdoc}
*/
protected function preGenerate()
{
$this->scriptCodes = array();
}
/**
* {@inheritdoc}
*/
protected function generateDataForLocale(BundleReaderInterface $reader, $tempDir, $displayLocale)
{
$localeBundle = $reader->read($tempDir, $displayLocale);
// isset() on \ResourceBundle returns true even if the value is null
if (isset($localeBundle['Scripts']) && null !== $localeBundle['Scripts']) {
$data = array(
'Version' => $localeBundle['Version'],
'Names' => iterator_to_array($localeBundle['Scripts']),
);
$this->scriptCodes = array_merge($this->scriptCodes, array_keys($data['Names']));
return $data;
}
}
/**
* {@inheritdoc}
*/
protected function generateDataForRoot(BundleReaderInterface $reader, $tempDir)
{
}
/**
* {@inheritdoc}
*/
protected function generateDataForMeta(BundleReaderInterface $reader, $tempDir)
{
$rootBundle = $reader->read($tempDir, 'root');
$this->scriptCodes = array_unique($this->scriptCodes);
sort($this->scriptCodes);
return array(
'Version' => $rootBundle['Version'],
'Scripts' => $this->scriptCodes,
);
}
}

View File

@ -0,0 +1,152 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Provider;
use Symfony\Component\Intl\Exception\MissingResourceException;
use Symfony\Component\Intl\Locale;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
/**
* Data provider for currency-related data.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class CurrencyDataProvider
{
const INDEX_SYMBOL = 0;
const INDEX_NAME = 1;
const INDEX_FRACTION_DIGITS = 0;
const INDEX_ROUNDING_INCREMENT = 1;
/**
* @var string
*/
private $path;
/**
* @var BundleEntryReaderInterface
*/
private $reader;
/**
* Creates a data provider that reads currency-related data from a
* resource bundle.
*
* @param string $path The path to the resource bundle.
* @param BundleEntryReaderInterface $reader The reader for reading the resource bundle.
*/
public function __construct($path, BundleEntryReaderInterface $reader)
{
$this->path = $path;
$this->reader = $reader;
}
public function getCurrencies()
{
return $this->reader->readEntry($this->path, 'meta', array('Currencies'));
}
public function getSymbol($currency, $displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
return $this->reader->readEntry($this->path, $displayLocale, array('Names', $currency, static::INDEX_SYMBOL));
}
public function getName($currency, $displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
return $this->reader->readEntry($this->path, $displayLocale, array('Names', $currency, static::INDEX_NAME));
}
public function getNames($displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
// ====================================================================
// For reference: It is NOT possible to return names indexed by
// numeric code here, because some numeric codes map to multiple
// 3-letter codes (e.g. 32 => "ARA", "ARP", "ARS")
// ====================================================================
$names = $this->reader->readEntry($this->path, $displayLocale, array('Names'));
if ($names instanceof \Traversable) {
$names = iterator_to_array($names);
}
$index = static::INDEX_NAME;
array_walk($names, function (&$value) use ($index) {
$value = $value[$index];
});
// Sorting by value cannot be done during bundle generation, because
// binary bundles are always sorted by keys
$collator = new \Collator($displayLocale);
$collator->asort($names);
return $names;
}
/**
* Data provider for {@link \Symfony\Component\Intl\Currency::getFractionDigits()}.
*/
public function getFractionDigits($currency)
{
try {
return $this->reader->readEntry($this->path, 'meta', array('Meta', $currency, static::INDEX_FRACTION_DIGITS));
} catch (MissingResourceException $e) {
return $this->reader->readEntry($this->path, 'meta', array('Meta', 'DEFAULT', static::INDEX_FRACTION_DIGITS));
}
}
/**
* Data provider for {@link \Symfony\Component\Intl\Currency::getRoundingIncrement()}.
*/
public function getRoundingIncrement($currency)
{
try {
return $this->reader->readEntry($this->path, 'meta', array('Meta', $currency, static::INDEX_ROUNDING_INCREMENT));
} catch (MissingResourceException $e) {
return $this->reader->readEntry($this->path, 'meta', array('Meta', 'DEFAULT', static::INDEX_ROUNDING_INCREMENT));
}
}
/**
* Data provider for {@link \Symfony\Component\Intl\Currency::getNumericCode()}.
*/
public function getNumericCode($currency)
{
return $this->reader->readEntry($this->path, 'meta', array('Alpha3ToNumeric', $currency));
}
/**
* Data provider for {@link \Symfony\Component\Intl\Currency::forNumericCode()}.
*/
public function forNumericCode($numericCode)
{
return $this->reader->readEntry($this->path, 'meta', array('NumericToAlpha3', (string) $numericCode));
}
}

View File

@ -0,0 +1,91 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Provider;
use Symfony\Component\Intl\Locale;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
/**
* Data provider for language-related ICU data.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class LanguageDataProvider
{
/**
* @var string
*/
private $path;
/**
* @var BundleEntryReaderInterface
*/
private $reader;
/**
* Creates a data provider that reads locale-related data from .res files.
*
* @param string $path The path to the directory
* containing the .res files.
* @param BundleEntryReaderInterface $reader The reader for reading the .res
* files.
*/
public function __construct($path, BundleEntryReaderInterface $reader)
{
$this->path = $path;
$this->reader = $reader;
}
public function getLanguages()
{
return $this->reader->readEntry($this->path, 'meta', array('Languages'));
}
public function getAliases()
{
return $this->reader->readEntry($this->path, 'root', array('Aliases'));
}
public function getName($language, $displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
return $this->reader->readEntry($this->path, $displayLocale, array('Names', $language));
}
public function getNames($displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
$languages = $this->reader->readEntry($this->path, $displayLocale, array('Names'));
if ($languages instanceof \Traversable) {
$languages = iterator_to_array($languages);
}
$collator = new \Collator($displayLocale);
$collator->asort($languages);
return $languages;
}
public function getAlpha3Code($language)
{
return $this->reader->readEntry($this->path, 'meta', array('Alpha2ToAlpha3', $language));
}
}

View File

@ -0,0 +1,92 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Provider;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
use Symfony\Component\Intl\Locale;
/**
* Data provider for locale-related ICU data.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class LocaleDataProvider
{
/**
* @var string
*/
private $path;
/**
* @var BundleEntryReaderInterface
*/
private $reader;
/**
* Creates a data provider that reads locale-related data from .res files.
*
* @param string $path The path to the directory
* containing the .res files.
* @param BundleEntryReaderInterface $reader The reader for reading the .res
* files.
*/
public function __construct($path, BundleEntryReaderInterface $reader)
{
$this->path = $path;
$this->reader = $reader;
}
public function getLocales()
{
return $this->reader->readEntry($this->path, 'meta', array('Locales'));
}
public function getAliases()
{
$aliases = $this->reader->readEntry($this->path, 'meta', array('Aliases'));
if ($aliases instanceof \Traversable) {
$aliases = iterator_to_array($aliases);
}
return $aliases;
}
public function getName($locale, $displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
return $this->reader->readEntry($this->path, $displayLocale, array('Names', $locale));
}
public function getNames($displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
$names = $this->reader->readEntry($this->path, $displayLocale, array('Names'));
if ($names instanceof \Traversable) {
$names = iterator_to_array($names);
}
$collator = new \Collator($displayLocale);
$collator->asort($names);
return $names;
}
}

View File

@ -0,0 +1,81 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Provider;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
use Symfony\Component\Intl\Locale;
/**
* Data provider for region-related ICU data.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class RegionDataProvider
{
/**
* @var string
*/
private $path;
/**
* @var BundleEntryReaderInterface
*/
private $reader;
/**
* Creates a data provider that reads locale-related data from .res files.
*
* @param string $path The path to the directory
* containing the .res files.
* @param BundleEntryReaderInterface $reader The reader for reading the .res
* files.
*/
public function __construct($path, BundleEntryReaderInterface $reader)
{
$this->path = $path;
$this->reader = $reader;
}
public function getRegions()
{
return $this->reader->readEntry($this->path, 'meta', array('Regions'));
}
public function getName($region, $displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
return $this->reader->readEntry($this->path, $displayLocale, array('Names', $region));
}
public function getNames($displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
$names = $this->reader->readEntry($this->path, $displayLocale, array('Names'));
if ($names instanceof \Traversable) {
$names = iterator_to_array($names);
}
$collator = new \Collator($displayLocale);
$collator->asort($names);
return $names;
}
}

View File

@ -0,0 +1,81 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Provider;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
use Symfony\Component\Intl\Locale;
/**
* Data provider for script-related ICU data.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class ScriptDataProvider
{
/**
* @var string
*/
private $path;
/**
* @var BundleEntryReaderInterface
*/
private $reader;
/**
* Creates a data provider that reads locale-related data from .res files.
*
* @param string $path The path to the directory
* containing the .res files.
* @param BundleEntryReaderInterface $reader The reader for reading the .res
* files.
*/
public function __construct($path, BundleEntryReaderInterface $reader)
{
$this->path = $path;
$this->reader = $reader;
}
public function getScripts()
{
return $this->reader->readEntry($this->path, 'meta', array('Scripts'));
}
public function getName($script, $displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
return $this->reader->readEntry($this->path, $displayLocale, array('Names', $script));
}
public function getNames($displayLocale = null)
{
if (null === $displayLocale) {
$displayLocale = Locale::getDefault();
}
$names = $this->reader->readEntry($this->path, $displayLocale, array('Names'));
if ($names instanceof \Traversable) {
$names = iterator_to_array($names);
}
$collator = new \Collator($displayLocale);
$collator->asort($names);
return $names;
}
}

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Util;
namespace Symfony\Component\Intl\Data\Util;
use Symfony\Component\Intl\Exception\BadMethodCallException;

View File

@ -0,0 +1,85 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Data\Util;
/**
* Scans a directory with data files for locales.
*
* The name of each file with the extension ".txt" is considered, if it "looks"
* like a locale:
*
* - the name must start with two letters;
* - the two letters may optionally be followed by an underscore and any
* sequence of other symbols.
*
* For example, "de" and "de_DE" are considered to be locales. "root" and "meta"
* are not.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class LocaleScanner
{
/**
* Returns all locales found in the given directory.
*
* @param string $sourceDir The directory with ICU files
*
* @return array An array of locales. The result also contains locales that
* are in fact just aliases for other locales. Use
* {@link scanAliases()} to determine which of the locales
* are aliases
*/
public function scanLocales($sourceDir)
{
$locales = glob($sourceDir.'/*.txt');
// Remove file extension and sort
array_walk($locales, function (&$locale) { $locale = basename($locale, '.txt'); });
// Remove non-locales
$locales = array_filter($locales, function ($locale) {
return preg_match('/^[a-z]{2}(_.+)?$/', $locale);
});
sort($locales);
return $locales;
}
/**
* Returns all locale aliases found in the given directory.
*
* @param string $sourceDir The directory with ICU files
*
* @return array An array with the locale aliases as keys and the aliased
* locales as values
*/
public function scanAliases($sourceDir)
{
$locales = $this->scanLocales($sourceDir, '.txt');
$aliases = array();
// Delete locales that are no aliases
foreach ($locales as $locale) {
$content = file_get_contents($sourceDir.'/'.$locale.'.txt');
// Aliases contain the text "%%ALIAS" followed by the aliased locale
if (preg_match('/"%%ALIAS"\{"([^"]+)"\}/', $content, $matches)) {
$aliases[$locale] = $matches[1];
}
}
return $aliases;
}
}

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Util;
namespace Symfony\Component\Intl\Data\Util;
use Symfony\Component\Intl\Exception\OutOfBoundsException;

View File

@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Util;
namespace Symfony\Component\Intl\Data\Util;
use Symfony\Component\Intl\Exception\OutOfBoundsException;

View File

@ -11,20 +11,30 @@
namespace Symfony\Component\Intl;
use Symfony\Component\Icu\IcuCurrencyBundle;
use Symfony\Component\Icu\IcuData;
use Symfony\Component\Icu\IcuLanguageBundle;
use Symfony\Component\Icu\IcuLocaleBundle;
use Symfony\Component\Icu\IcuRegionBundle;
use Symfony\Component\Intl\ResourceBundle\Reader\BufferedBundleReader;
use Symfony\Component\Intl\ResourceBundle\Reader\StructuredBundleReader;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleReaderInterface;
use Symfony\Component\Intl\Data\Bundle\Reader\JsonBundleReader;
use Symfony\Component\Intl\Data\Bundle\Reader\IntlBundleReader;
use Symfony\Component\Intl\Data\Bundle\Reader\BufferedBundleReader;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReader;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
use Symfony\Component\Intl\Data\Bundle\Reader\PhpBundleReader;
use Symfony\Component\Intl\Data\Provider\ScriptDataProvider;
use Symfony\Component\Intl\Exception\InvalidArgumentException;
use Symfony\Component\Intl\ResourceBundle\CurrencyBundle;
use Symfony\Component\Intl\ResourceBundle\CurrencyBundleInterface;
use Symfony\Component\Intl\ResourceBundle\LanguageBundle;
use Symfony\Component\Intl\ResourceBundle\LanguageBundleInterface;
use Symfony\Component\Intl\ResourceBundle\LocaleBundle;
use Symfony\Component\Intl\ResourceBundle\LocaleBundleInterface;
use Symfony\Component\Intl\ResourceBundle\RegionBundle;
use Symfony\Component\Intl\ResourceBundle\RegionBundleInterface;
/**
* Gives access to internationalization data.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Intl
final class Intl
{
/**
* The number of resource bundles to buffer. Loading the same resource
@ -32,6 +42,31 @@ class Intl
*/
const BUFFER_SIZE = 10;
/**
* The directory name of the currency data.
*/
const CURRENCY_DIR = 'currencies';
/**
* The directory name of the language data.
*/
const LANGUAGE_DIR = 'languages';
/**
* The directory name of the script data.
*/
const SCRIPT_DIR = 'scripts';
/**
* The directory name of the locale data.
*/
const LOCALE_DIR = 'locales';
/**
* The directory name of the region data.
*/
const REGION_DIR = 'regions';
/**
* @var ResourceBundle\CurrencyBundleInterface
*/
@ -63,14 +98,14 @@ class Intl
private static $icuDataVersion = false;
/**
* @var ResourceBundle\Reader\StructuredBundleReaderInterface
* @var BundleEntryReaderInterface
*/
private static $bundleReader;
private static $entryReader;
/**
* Returns whether the intl extension is installed.
*
* @return bool Returns true if the intl extension is installed, false otherwise.
* @return bool Returns true if the intl extension is installed, false otherwise.
*/
public static function isExtensionLoaded()
{
@ -80,12 +115,16 @@ class Intl
/**
* Returns the bundle containing currency information.
*
* @return ResourceBundle\CurrencyBundleInterface The currency resource bundle.
* @return CurrencyBundleInterface The currency resource bundle.
*/
public static function getCurrencyBundle()
{
if (null === self::$currencyBundle) {
self::$currencyBundle = new IcuCurrencyBundle(self::getBundleReader());
self::$currencyBundle = new CurrencyBundle(
self::getDataDirectory().'/'.Intl::CURRENCY_DIR,
self::getEntryReader(),
self::getLocaleBundle()
);
}
return self::$currencyBundle;
@ -94,12 +133,20 @@ class Intl
/**
* Returns the bundle containing language information.
*
* @return ResourceBundle\LanguageBundleInterface The language resource bundle.
* @return LanguageBundleInterface The language resource bundle.
*/
public static function getLanguageBundle()
{
if (null === self::$languageBundle) {
self::$languageBundle = new IcuLanguageBundle(self::getBundleReader());
self::$languageBundle = new LanguageBundle(
self::getDataDirectory().'/'.Intl::LANGUAGE_DIR,
self::getEntryReader(),
self::getLocaleBundle(),
new ScriptDataProvider(
self::getDataDirectory().'/'.Intl::SCRIPT_DIR,
self::getEntryReader()
)
);
}
return self::$languageBundle;
@ -108,12 +155,15 @@ class Intl
/**
* Returns the bundle containing locale information.
*
* @return ResourceBundle\LocaleBundleInterface The locale resource bundle.
* @return LocaleBundleInterface The locale resource bundle.
*/
public static function getLocaleBundle()
{
if (null === self::$localeBundle) {
self::$localeBundle = new IcuLocaleBundle(self::getBundleReader());
self::$localeBundle = new LocaleBundle(
self::getDataDirectory().'/'.Intl::LOCALE_DIR,
self::getEntryReader()
);
}
return self::$localeBundle;
@ -122,12 +172,16 @@ class Intl
/**
* Returns the bundle containing region information.
*
* @return ResourceBundle\RegionBundleInterface The region resource bundle.
* @return RegionBundleInterface The region resource bundle.
*/
public static function getRegionBundle()
{
if (null === self::$regionBundle) {
self::$regionBundle = new IcuRegionBundle(self::getBundleReader());
self::$regionBundle = new RegionBundle(
self::getDataDirectory().'/'.Intl::REGION_DIR,
self::getEntryReader(),
self::getLocaleBundle()
);
}
return self::$regionBundle;
@ -171,7 +225,7 @@ class Intl
public static function getIcuDataVersion()
{
if (false === self::$icuDataVersion) {
self::$icuDataVersion = IcuData::getVersion();
self::$icuDataVersion = trim(file_get_contents(self::getDataDirectory().'/version.txt'));
}
return self::$icuDataVersion;
@ -188,20 +242,44 @@ class Intl
}
/**
* Returns a resource bundle reader for .php resource bundle files.
* Returns the absolute path to the data directory.
*
* @return ResourceBundle\Reader\StructuredBundleReaderInterface The resource reader.
* @return string The absolute path to the data directory
*/
private static function getBundleReader()
public static function getDataDirectory()
{
if (null === self::$bundleReader) {
self::$bundleReader = new StructuredBundleReader(new BufferedBundleReader(
IcuData::getBundleReader(),
return realpath(__DIR__.'/Resources/data');
}
/**
* Returns the cached bundle entry reader.
*
* @return BundleEntryReaderInterface The bundle entry reader
*/
private static function getEntryReader()
{
if (null === self::$entryReader) {
self::$entryReader = new BundleEntryReader(new BufferedBundleReader(
new JsonBundleReader(),
self::BUFFER_SIZE
));
}
return self::$bundleReader;
return self::$entryReader;
}
/**
* Resets the internal state.
*/
private static function reset()
{
self::$currencyBundle = null;
self::$languageBundle = null;
self::$localeBundle = null;
self::$regionBundle = null;
self::$icuVersion = false;
self::$icuDataVersion = false;
self::$entryReader = null;
}
/**

View File

@ -21,9 +21,46 @@ namespace Symfony\Component\Intl;
final class Locale extends \Locale
{
/**
* Returns the fallback locale for a given locale, if any
* @var string
*/
private static $defaultFallback = 'en';
/**
* Sets the default fallback locale.
*
* @param string $locale The ICU locale code to find the fallback for.
* The default fallback locale is used as fallback for locales that have no
* fallback otherwise.
*
* @param string $locale The default fallback locale
*
* @see getFallback()
*/
public static function setDefaultFallback($locale)
{
self::$defaultFallback = $locale;
}
/**
* Returns the default fallback locale.
*
* @return string The default fallback locale
*
* @see setDefaultFallback()
* @see getFallback()
*/
public static function getDefaultFallback()
{
return self::$defaultFallback;
}
/**
* Returns the fallback locale for a given locale.
*
* For example, the fallback of "fr_FR" is "fr". The fallback of "fr" is
* the default fallback locale configured with {@link setDefaultFallback()}.
* The default fallback locale has no fallback.
*
* @param string $locale The ICU locale code to find the fallback for
*
* @return string|null The ICU locale code of the fallback locale, or null
* if no fallback exists
@ -31,11 +68,17 @@ final class Locale extends \Locale
public static function getFallback($locale)
{
if (false === $pos = strrpos($locale, '_')) {
if ('root' === $locale) {
return;
if (self::$defaultFallback === $locale) {
return 'root';
}
return 'root';
// Don't return default fallback for "root", "meta" or others
// Normal locales have two or three letters
if (strlen($locale) < 4) {
return self::$defaultFallback;
}
return;
}
return substr($locale, 0, $pos);

View File

@ -1,72 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle;
use Symfony\Component\Intl\ResourceBundle\Reader\StructuredBundleReaderInterface;
/**
* Base class for {@link ResourceBundleInterface} implementations.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
abstract class AbstractBundle implements ResourceBundleInterface
{
/**
* @var string
*/
private $path;
/**
* @var StructuredBundleReaderInterface
*/
private $reader;
/**
* Creates a bundle at the given path using the given reader for reading
* bundle entries.
*
* @param string $path The path to the bundle.
* @param StructuredBundleReaderInterface $reader The reader for reading
* the bundle.
*/
public function __construct($path, StructuredBundleReaderInterface $reader)
{
$this->path = $path;
$this->reader = $reader;
}
/**
* {@inheritdoc}
*/
public function getLocales()
{
return $this->reader->getLocales($this->path);
}
/**
* Proxy method for {@link StructuredBundleReaderInterface#read}.
*/
protected function read($locale)
{
return $this->reader->read($this->path, $locale);
}
/**
* Proxy method for {@link StructuredBundleReaderInterface#readEntry}.
*/
protected function readEntry($locale, array $indices, $mergeFallback = false)
{
return $this->reader->readEntry($this->path, $locale, $indices, $mergeFallback);
}
}

View File

@ -11,6 +11,12 @@
namespace Symfony\Component\Intl\ResourceBundle;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
use Symfony\Component\Intl\Data\Provider\CurrencyDataProvider;
use Symfony\Component\Intl\Data\Provider\LocaleDataProvider;
use Symfony\Component\Intl\Exception\MissingResourceException;
use Symfony\Component\Intl\Intl;
/**
* Default implementation of {@link CurrencyBundleInterface}.
*
@ -18,64 +24,61 @@ namespace Symfony\Component\Intl\ResourceBundle;
*
* @internal
*/
class CurrencyBundle extends AbstractBundle implements CurrencyBundleInterface
class CurrencyBundle extends CurrencyDataProvider implements CurrencyBundleInterface
{
const INDEX_NAME = 0;
const INDEX_SYMBOL = 1;
const INDEX_FRACTION_DIGITS = 2;
const INDEX_ROUNDING_INCREMENT = 3;
/**
* @var LocaleDataProvider
*/
private $localeProvider;
/**
* {@inheritdoc}
* Creates a new currency bundle.
*
* @param string $path
* @param BundleEntryReaderInterface $reader
* @param LocaleDataProvider $localeProvider
*/
public function getCurrencySymbol($currency, $locale = null)
public function __construct($path, BundleEntryReaderInterface $reader, LocaleDataProvider $localeProvider)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
parent::__construct($path, $reader);
return $this->readEntry($locale, array('Currencies', $currency, static::INDEX_SYMBOL), true);
$this->localeProvider = $localeProvider;
}
/**
* {@inheritdoc}
*/
public function getCurrencyName($currency, $locale = null)
public function getCurrencySymbol($currency, $displayLocale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
try {
return $this->getSymbol($currency, $displayLocale);
} catch (MissingResourceException $e) {
return null;
}
return $this->readEntry($locale, array('Currencies', $currency, static::INDEX_NAME), true);
}
/**
* {@inheritdoc}
*/
public function getCurrencyNames($locale = null)
public function getCurrencyName($currency, $displayLocale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
try {
return $this->getName($currency, $displayLocale);
} catch (MissingResourceException $e) {
return null;
}
}
if (null === ($currencies = $this->readEntry($locale, array('Currencies'), true))) {
return array();
/**
* {@inheritdoc}
*/
public function getCurrencyNames($displayLocale = null)
{
try {
return $this->getNames($displayLocale);
} catch (MissingResourceException $e) {
return null;
}
if ($currencies instanceof \Traversable) {
$currencies = iterator_to_array($currencies);
}
$index = static::INDEX_NAME;
array_walk($currencies, function (&$value) use ($index) {
$value = $value[$index];
});
return $currencies;
}
/**
@ -83,7 +86,11 @@ class CurrencyBundle extends AbstractBundle implements CurrencyBundleInterface
*/
public function getFractionDigits($currency)
{
return $this->readEntry('en', array('Currencies', $currency, static::INDEX_FRACTION_DIGITS), true);
try {
return parent::getFractionDigits($currency);
} catch (MissingResourceException $e) {
return null;
}
}
/**
@ -91,6 +98,22 @@ class CurrencyBundle extends AbstractBundle implements CurrencyBundleInterface
*/
public function getRoundingIncrement($currency)
{
return $this->readEntry('en', array('Currencies', $currency, static::INDEX_ROUNDING_INCREMENT), true);
try {
return parent::getRoundingIncrement($currency);
} catch (MissingResourceException $e) {
return null;
}
}
/**
* {@inheritdoc}
*/
public function getLocales()
{
try {
return $this->localeProvider->getLocales();
} catch (MissingResourceException $e) {
return null;
}
}
}

View File

@ -22,33 +22,33 @@ interface CurrencyBundleInterface extends ResourceBundleInterface
* Returns the symbol used for a currency.
*
* @param string $currency A currency code (e.g. "EUR").
* @param string $locale Optional. The locale to return the result in.
* @param string $displayLocale Optional. The locale to return the result in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The currency symbol or NULL if not found.
*/
public function getCurrencySymbol($currency, $locale = null);
public function getCurrencySymbol($currency, $displayLocale = null);
/**
* Returns the name of a currency.
*
* @param string $currency A currency code (e.g. "EUR").
* @param string $locale Optional. The locale to return the name in.
* @param string $displayLocale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the currency or NULL if not found.
*/
public function getCurrencyName($currency, $locale = null);
public function getCurrencyName($currency, $displayLocale = null);
/**
* Returns the names of all known currencies.
*
* @param string $locale Optional. The locale to return the names in.
* @param string $displayLocale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of currency names indexed by currency codes.
*/
public function getCurrencyNames($locale = null);
public function getCurrencyNames($displayLocale = null);
/**
* Returns the number of digits after the comma of a currency.

View File

@ -11,6 +11,13 @@
namespace Symfony\Component\Intl\ResourceBundle;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
use Symfony\Component\Intl\Data\Provider\LanguageDataProvider;
use Symfony\Component\Intl\Data\Provider\LocaleDataProvider;
use Symfony\Component\Intl\Data\Provider\ScriptDataProvider;
use Symfony\Component\Intl\Exception\MissingResourceException;
use Symfony\Component\Intl\Intl;
/**
* Default implementation of {@link LanguageBundleInterface}.
*
@ -18,100 +25,99 @@ namespace Symfony\Component\Intl\ResourceBundle;
*
* @internal
*/
class LanguageBundle extends AbstractBundle implements LanguageBundleInterface
class LanguageBundle extends LanguageDataProvider implements LanguageBundleInterface
{
/**
* @var LocaleDataProvider
*/
private $localeProvider;
/**
* @var ScriptDataProvider
*/
private $scriptProvider;
/**
* Creates a new language bundle.
*
* @param string $path
* @param BundleEntryReaderInterface $reader
* @param LocaleDataProvider $localeProvider
*/
public function __construct($path, BundleEntryReaderInterface $reader, LocaleDataProvider $localeProvider, ScriptDataProvider $scriptProvider)
{
parent::__construct($path, $reader);
$this->localeProvider = $localeProvider;
$this->scriptProvider = $scriptProvider;
}
/**
* {@inheritdoc}
*/
public function getLanguageName($lang, $region = null, $locale = null)
public function getLanguageName($language, $region = null, $displayLocale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
if (null === ($languages = $this->readEntry($locale, array('Languages'), true))) {
return;
}
// Some languages are translated together with their region,
// i.e. "en_GB" is translated as "British English"
if (null !== $region && isset($languages[$lang.'_'.$region])) {
return $languages[$lang.'_'.$region];
}
return $languages[$lang];
}
/**
* {@inheritdoc}
*/
public function getLanguageNames($locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
if (null === ($languages = $this->readEntry($locale, array('Languages'), true))) {
return array();
}
if ($languages instanceof \Traversable) {
$languages = iterator_to_array($languages);
}
return $languages;
}
/**
* {@inheritdoc}
*/
public function getScriptName($script, $lang = null, $locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
$data = $this->read($locale);
// Some languages are translated together with their script,
// e.g. "zh_Hans" is translated as "Simplified Chinese"
if (null !== $lang && isset($data['Languages'][$lang.'_'.$script])) {
$langName = $data['Languages'][$lang.'_'.$script];
// If the script is appended in braces, extract it, e.g. "zh_Hans"
// is translated as "Chinesisch (vereinfacht)" in locale "de"
if (strpos($langName, '(') !== false) {
list($langName, $scriptName) = preg_split('/[\s()]/', $langName, null, PREG_SPLIT_NO_EMPTY);
return $scriptName;
if (null !== $region) {
try {
return $this->getName($language.'_'.$region, $displayLocale);
} catch (MissingResourceException $e) {
}
}
// "af" (Afrikaans) has no "Scripts" block
if (!isset($data['Scripts'][$script])) {
return;
try {
return $this->getName($language, $displayLocale);
} catch (MissingResourceException $e) {
return null;
}
return $data['Scripts'][$script];
}
/**
* {@inheritdoc}
*/
public function getScriptNames($locale = null)
public function getLanguageNames($displayLocale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
try {
return $this->getNames($displayLocale);
} catch (MissingResourceException $e) {
return null;
}
}
if (null === ($scripts = $this->readEntry($locale, array('Scripts'), true))) {
return array();
/**
* {@inheritdoc}
*/
public function getScriptName($script, $language = null, $displayLocale = null)
{
try {
return $this->scriptProvider->getName($script, $displayLocale);
} catch (MissingResourceException $e) {
return null;
}
}
if ($scripts instanceof \Traversable) {
$scripts = iterator_to_array($scripts);
/**
* {@inheritdoc}
*/
public function getScriptNames($displayLocale = null)
{
try {
return $this->scriptProvider->getNames($displayLocale);
} catch (MissingResourceException $e) {
return null;
}
}
return $scripts;
/**
* {@inheritdoc}
*/
public function getLocales()
{
try {
return $this->localeProvider->getLocales();
} catch (MissingResourceException $e) {
return null;
}
}
}

View File

@ -21,44 +21,44 @@ interface LanguageBundleInterface extends ResourceBundleInterface
/**
* Returns the name of a language.
*
* @param string $lang A language code (e.g. "en").
* @param string $language A language code (e.g. "en").
* @param string|null $region Optional. A region code (e.g. "US").
* @param string $locale Optional. The locale to return the name in.
* @param string $displayLocale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the language or NULL if not found.
*/
public function getLanguageName($lang, $region = null, $locale = null);
public function getLanguageName($language, $region = null, $displayLocale = null);
/**
* Returns the names of all known languages.
*
* @param string $locale Optional. The locale to return the names in.
* @param string $displayLocale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of language names indexed by language codes.
*/
public function getLanguageNames($locale = null);
public function getLanguageNames($displayLocale = null);
/**
* Returns the name of a script.
*
* @param string $script A script code (e.g. "Hans").
* @param string $lang Optional. A language code (e.g. "zh").
* @param string $locale Optional. The locale to return the name in.
* @param string $language Optional. A language code (e.g. "zh").
* @param string $displayLocale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the script or NULL if not found.
*/
public function getScriptName($script, $lang = null, $locale = null);
public function getScriptName($script, $language = null, $displayLocale = null);
/**
* Returns the names of all known scripts.
*
* @param string $locale Optional. The locale to return the names in.
* @param string $displayLocale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of script names indexed by script codes.
*/
public function getScriptNames($locale = null);
public function getScriptNames($displayLocale = null);
}

View File

@ -11,6 +11,11 @@
namespace Symfony\Component\Intl\ResourceBundle;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
use Symfony\Component\Intl\Data\Provider\LocaleDataProvider;
use Symfony\Component\Intl\Exception\MissingResourceException;
use Symfony\Component\Intl\Intl;
/**
* Default implementation of {@link LocaleBundleInterface}.
*
@ -18,37 +23,41 @@ namespace Symfony\Component\Intl\ResourceBundle;
*
* @internal
*/
class LocaleBundle extends AbstractBundle implements LocaleBundleInterface
class LocaleBundle extends LocaleDataProvider implements LocaleBundleInterface
{
/**
* {@inheritdoc}
*/
public function getLocaleName($ofLocale, $locale = null)
public function getLocales()
{
if (null === $locale) {
$locale = \Locale::getDefault();
try {
return parent::getLocales();
} catch (MissingResourceException $e) {
return null;
}
return $this->readEntry($locale, array('Locales', $ofLocale), true);
}
/**
* {@inheritdoc}
*/
public function getLocaleNames($locale = null)
public function getLocaleName($locale, $displayLocale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
try {
return $this->getName($locale, $displayLocale);
} catch (MissingResourceException $e) {
return null;
}
}
if (null === ($locales = $this->readEntry($locale, array('Locales'), true))) {
return array();
/**
* {@inheritdoc}
*/
public function getLocaleNames($displayLocale = null)
{
try {
return $this->getNames($displayLocale);
} catch (MissingResourceException $e) {
return null;
}
if ($locales instanceof \Traversable) {
$locales = iterator_to_array($locales);
}
return $locales;
}
}

View File

@ -21,21 +21,21 @@ interface LocaleBundleInterface extends ResourceBundleInterface
/**
* Returns the name of a locale.
*
* @param string $ofLocale The locale to return the name of (e.g. "de_AT").
* @param string $locale Optional. The locale to return the name in.
* @param string $locale The locale to return the name of (e.g. "de_AT").
* @param string $displayLocale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the locale or NULL if not found.
*/
public function getLocaleName($ofLocale, $locale = null);
public function getLocaleName($locale, $displayLocale = null);
/**
* Returns the names of all known locales.
*
* @param string $locale Optional. The locale to return the names in.
* @param string $displayLocale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of locale names indexed by locale codes.
*/
public function getLocaleNames($locale = null);
public function getLocaleNames($displayLocale = null);
}

View File

@ -11,6 +11,12 @@
namespace Symfony\Component\Intl\ResourceBundle;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
use Symfony\Component\Intl\Data\Provider\LocaleDataProvider;
use Symfony\Component\Intl\Data\Provider\RegionDataProvider;
use Symfony\Component\Intl\Exception\MissingResourceException;
use Symfony\Component\Intl\Intl;
/**
* Default implementation of {@link RegionBundleInterface}.
*
@ -18,37 +24,60 @@ namespace Symfony\Component\Intl\ResourceBundle;
*
* @internal
*/
class RegionBundle extends AbstractBundle implements RegionBundleInterface
class RegionBundle extends RegionDataProvider implements RegionBundleInterface
{
/**
* {@inheritdoc}
* @var LocaleDataProvider
*/
public function getCountryName($country, $locale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
}
private $localeProvider;
return $this->readEntry($locale, array('Countries', $country), true);
/**
* Creates a new region bundle.
*
* @param string $path
* @param BundleEntryReaderInterface $reader
* @param LocaleDataProvider $localeProvider
*/
public function __construct($path, BundleEntryReaderInterface $reader, LocaleDataProvider $localeProvider)
{
parent::__construct($path, $reader);
$this->localeProvider = $localeProvider;
}
/**
* {@inheritdoc}
*/
public function getCountryNames($locale = null)
public function getCountryName($country, $displayLocale = null)
{
if (null === $locale) {
$locale = \Locale::getDefault();
try {
return $this->getName($country, $displayLocale);
} catch (MissingResourceException $e) {
return null;
}
}
if (null === ($countries = $this->readEntry($locale, array('Countries'), true))) {
return array();
/**
* {@inheritdoc}
*/
public function getCountryNames($displayLocale = null)
{
try {
return $this->getNames($displayLocale);
} catch (MissingResourceException $e) {
return null;
}
}
if ($countries instanceof \Traversable) {
$countries = iterator_to_array($countries);
/**
* {@inheritdoc}
*/
public function getLocales()
{
try {
return $this->localeProvider->getLocales();
} catch (MissingResourceException $e) {
return null;
}
return $countries;
}
}

View File

@ -22,20 +22,20 @@ interface RegionBundleInterface extends ResourceBundleInterface
* Returns the name of a country.
*
* @param string $country A country code (e.g. "US").
* @param string $locale Optional. The locale to return the name in.
* @param string $displayLocale Optional. The locale to return the name in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string|null The name of the country or NULL if not found.
*/
public function getCountryName($country, $locale = null);
public function getCountryName($country, $displayLocale = null);
/**
* Returns the names of all known countries.
*
* @param string $locale Optional. The locale to return the names in.
* @param string $displayLocale Optional. The locale to return the names in.
* Defaults to {@link \Locale::getDefault()}.
*
* @return string[] A list of country names indexed by country codes.
*/
public function getCountryNames($locale = null);
public function getCountryNames($displayLocale = null);
}

View File

@ -1,98 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
use Symfony\Component\Intl\Exception\RuntimeException;
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\TransformationRuleInterface;
use Symfony\Component\Intl\ResourceBundle\Writer\PhpBundleWriter;
/**
* Compiles a number of resource bundles based on predefined compilation rules.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class BundleTransformer
{
/**
* @var TransformationRuleInterface[]
*/
private $rules = array();
/**
* Adds a new compilation rule.
*
* @param TransformationRuleInterface $rule The compilation rule.
*/
public function addRule(TransformationRuleInterface $rule)
{
$this->rules[] = $rule;
}
/**
* Runs the compilation with the given compilation context.
*
* @param CompilationContextInterface $context The context storing information
* needed to run the compilation.
*
* @throws RuntimeException If any of the files to be compiled by the loaded
* compilation rules does not exist.
*/
public function compileBundles(CompilationContextInterface $context)
{
$filesystem = $context->getFilesystem();
$compiler = $context->getCompiler();
$filesystem->remove($context->getBinaryDir());
$filesystem->mkdir($context->getBinaryDir());
foreach ($this->rules as $rule) {
$filesystem->mkdir($context->getBinaryDir().'/'.$rule->getBundleName());
$resources = (array) $rule->beforeCompile($context);
foreach ($resources as $resource) {
if (!file_exists($resource)) {
throw new RuntimeException(sprintf(
'The file "%s" to be compiled by %s does not exist.',
$resource,
get_class($rule)
));
}
$compiler->compile($resource, $context->getBinaryDir().'/'.$rule->getBundleName());
}
$rule->afterCompile($context);
}
}
public function createStubs(StubbingContextInterface $context)
{
$filesystem = $context->getFilesystem();
$phpWriter = new PhpBundleWriter();
$filesystem->remove($context->getStubDir());
$filesystem->mkdir($context->getStubDir());
foreach ($this->rules as $rule) {
$filesystem->mkdir($context->getStubDir().'/'.$rule->getBundleName());
$data = $rule->beforeCreateStub($context);
$phpWriter->write($context->getStubDir().'/'.$rule->getBundleName(), 'en', $data);
$rule->afterCreateStub($context);
}
}
}

View File

@ -1,99 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Intl\ResourceBundle\Compiler\BundleCompilerInterface;
/**
* Default implementation of {@link CompilationContextInterface}.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class CompilationContext implements CompilationContextInterface
{
/**
* @var string
*/
private $sourceDir;
/**
* @var string
*/
private $binaryDir;
/**
* @var FileSystem
*/
private $filesystem;
/**
* @var BundleCompilerInterface
*/
private $compiler;
/**
* @var string
*/
private $icuVersion;
public function __construct($sourceDir, $binaryDir, Filesystem $filesystem, BundleCompilerInterface $compiler, $icuVersion)
{
$this->sourceDir = $sourceDir;
$this->binaryDir = $binaryDir;
$this->filesystem = $filesystem;
$this->compiler = $compiler;
$this->icuVersion = $icuVersion;
}
/**
* {@inheritdoc}
*/
public function getSourceDir()
{
return $this->sourceDir;
}
/**
* {@inheritdoc}
*/
public function getBinaryDir()
{
return $this->binaryDir;
}
/**
* {@inheritdoc}
*/
public function getFilesystem()
{
return $this->filesystem;
}
/**
* {@inheritdoc}
*/
public function getCompiler()
{
return $this->compiler;
}
/**
* {@inheritdoc}
*/
public function getIcuVersion()
{
return $this->icuVersion;
}
}

View File

@ -1,58 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
/**
* Stores contextual information for resource bundle compilation.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
interface CompilationContextInterface
{
/**
* Returns the directory where the source versions of the resource bundles
* are stored.
*
* @return string An absolute path to a directory.
*/
public function getSourceDir();
/**
* Returns the directory where the binary resource bundles are stored.
*
* @return string An absolute path to a directory.
*/
public function getBinaryDir();
/**
* Returns a tool for manipulating the filesystem.
*
* @return \Symfony\Component\Filesystem\Filesystem The filesystem manipulator.
*/
public function getFilesystem();
/**
* Returns a resource bundle compiler.
*
* @return \Symfony\Component\Intl\ResourceBundle\Compiler\BundleCompilerInterface The loaded resource bundle compiler.
*/
public function getCompiler();
/**
* Returns the ICU version of the bundles being converted.
*
* @return string The ICU version string.
*/
public function getIcuVersion();
}

View File

@ -1,96 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\ResourceBundle\CurrencyBundle;
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
use Symfony\Component\Intl\Util\IcuVersion;
/**
* The rule for compiling the currency bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class CurrencyBundleTransformationRule implements TransformationRuleInterface
{
/**
* {@inheritdoc}
*/
public function getBundleName()
{
return 'curr';
}
/**
* {@inheritdoc}
*/
public function beforeCompile(CompilationContextInterface $context)
{
// The currency data is contained in the locales and misc bundles
// in ICU <= 4.2
if (IcuVersion::compare($context->getIcuVersion(), '4.2', '<=', 1)) {
return array(
$context->getSourceDir().'/misc/supplementalData.txt',
$context->getSourceDir().'/locales',
);
}
return $context->getSourceDir().'/curr';
}
/**
* {@inheritdoc}
*/
public function afterCompile(CompilationContextInterface $context)
{
// \ResourceBundle does not like locale names with uppercase chars, so rename
// the resource file
// See: http://bugs.php.net/bug.php?id=54025
$fileName = $context->getBinaryDir().'/curr/supplementalData.res';
$fileNameLower = $context->getBinaryDir().'/curr/supplementaldata.res';
$context->getFilesystem()->rename($fileName, $fileNameLower);
}
/**
* {@inheritdoc}
*/
public function beforeCreateStub(StubbingContextInterface $context)
{
$currencies = array();
$currencyBundle = Intl::getCurrencyBundle();
foreach ($currencyBundle->getCurrencyNames('en') as $code => $name) {
$currencies[$code] = array(
CurrencyBundle::INDEX_NAME => $name,
CurrencyBundle::INDEX_SYMBOL => $currencyBundle->getCurrencySymbol($code, 'en'),
CurrencyBundle::INDEX_FRACTION_DIGITS => $currencyBundle->getFractionDigits($code),
CurrencyBundle::INDEX_ROUNDING_INCREMENT => $currencyBundle->getRoundingIncrement($code),
);
}
return array(
'Currencies' => $currencies,
);
}
/**
* {@inheritdoc}
*/
public function afterCreateStub(StubbingContextInterface $context)
{
}
}

View File

@ -1,73 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
use Symfony\Component\Intl\Util\IcuVersion;
/**
* The rule for compiling the language bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class LanguageBundleTransformationRule implements TransformationRuleInterface
{
/**
* {@inheritdoc}
*/
public function getBundleName()
{
return 'lang';
}
/**
* {@inheritdoc}
*/
public function beforeCompile(CompilationContextInterface $context)
{
// The language data is contained in the locales bundle in ICU <= 4.2
if (IcuVersion::compare($context->getIcuVersion(), '4.2', '<=', 1)) {
return $context->getSourceDir().'/locales';
}
return $context->getSourceDir().'/lang';
}
/**
* {@inheritdoc}
*/
public function afterCompile(CompilationContextInterface $context)
{
}
/**
* {@inheritdoc}
*/
public function beforeCreateStub(StubbingContextInterface $context)
{
return array(
'Languages' => Intl::getLanguageBundle()->getLanguageNames('en'),
'Scripts' => Intl::getLanguageBundle()->getScriptNames('en'),
);
}
/**
* {@inheritdoc}
*/
public function afterCreateStub(StubbingContextInterface $context)
{
}
}

View File

@ -1,258 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
use Symfony\Component\Intl\Exception\RuntimeException;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
use Symfony\Component\Intl\ResourceBundle\Writer\TextBundleWriter;
/**
* The rule for compiling the locale bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class LocaleBundleTransformationRule implements TransformationRuleInterface
{
/**
* @var \Symfony\Component\Intl\ResourceBundle\LanguageBundleInterface
*/
private $languageBundle;
/**
* @var \Symfony\Component\Intl\ResourceBundle\RegionBundleInterface
*/
private $regionBundle;
public function __construct()
{
$this->languageBundle = Intl::getLanguageBundle();
$this->regionBundle = Intl::getRegionBundle();
}
/**
* {@inheritdoc}
*/
public function getBundleName()
{
return 'locales';
}
/**
* {@inheritdoc}
*/
public function beforeCompile(CompilationContextInterface $context)
{
$tempDir = sys_get_temp_dir().'/icu-data-locales';
$context->getFilesystem()->remove($tempDir);
$context->getFilesystem()->mkdir($tempDir);
$this->generateTextFiles($tempDir, $this->scanLocales($context));
return $tempDir;
}
/**
* {@inheritdoc}
*/
public function afterCompile(CompilationContextInterface $context)
{
$context->getFilesystem()->remove(sys_get_temp_dir().'/icu-data-locales');
}
/**
* {@inheritdoc}
*/
public function beforeCreateStub(StubbingContextInterface $context)
{
return array(
'Locales' => Intl::getLocaleBundle()->getLocaleNames('en'),
);
}
/**
* {@inheritdoc}
*/
public function afterCreateStub(StubbingContextInterface $context)
{
}
private function scanLocales(CompilationContextInterface $context)
{
$tempDir = sys_get_temp_dir().'/icu-data-locales-source';
$context->getFilesystem()->remove($tempDir);
$context->getFilesystem()->mkdir($tempDir);
// Temporarily generate the resource bundles
$context->getCompiler()->compile($context->getSourceDir().'/locales', $tempDir);
// Discover the list of supported locales, which are the names of the resource
// bundles in the "locales" directory
$locales = glob($tempDir.'/*.res');
// Remove file extension and sort
array_walk($locales, function (&$locale) { $locale = basename($locale, '.res'); });
sort($locales);
// Delete unneeded locales
foreach ($locales as $key => $locale) {
// Delete all aliases from the list
// i.e., "az_AZ" is an alias for "az_Latn_AZ"
$content = file_get_contents($context->getSourceDir().'/locales/'.$locale.'.txt');
// The key "%%ALIAS" is not accessible through the \ResourceBundle class,
// so look in the original .txt file instead
if (strpos($content, '%%ALIAS') !== false) {
unset($locales[$key]);
}
// Delete locales that have no content (i.e. only "Version" key)
try {
$bundle = new \ResourceBundle($locale, $tempDir);
} catch (\Exception $e) {
// HHVM compatibility: constructor throws on invalid resource
$bundle = null;
}
if (null === $bundle) {
throw new RuntimeException('The resource bundle for locale '.$locale.' could not be loaded from directory '.$tempDir);
}
// There seems to be no other way for identifying all keys in this specific
// resource bundle
if (array_keys(iterator_to_array($bundle)) === array('Version')) {
unset($locales[$key]);
}
}
$context->getFilesystem()->remove($tempDir);
return $locales;
}
private function generateTextFiles($targetDirectory, array $locales)
{
$displayLocales = array_unique(array_merge(
$this->languageBundle->getLocales(),
$this->regionBundle->getLocales()
));
$txtWriter = new TextBundleWriter();
// Generate a list of locale names in the language of each display locale
// Each locale name has the form: "Language (Script, Region, Variant1, ...)
// Script, Region and Variants are optional. If none of them is available,
// the braces are not printed.
foreach ($displayLocales as $displayLocale) {
// Don't include ICU's root resource bundle
if ('root' === $displayLocale) {
continue;
}
$names = array();
foreach ($locales as $locale) {
// Don't include ICU's root resource bundle
if ($locale === 'root') {
continue;
}
if (null !== ($name = $this->generateLocaleName($locale, $displayLocale))) {
$names[$locale] = $name;
}
}
// If no names could be generated for the current locale, skip it
if (0 === count($names)) {
continue;
}
$txtWriter->write($targetDirectory, $displayLocale, array('Locales' => $names));
}
}
private function generateLocaleName($locale, $displayLocale)
{
$name = null;
$lang = \Locale::getPrimaryLanguage($locale);
$script = \Locale::getScript($locale);
$region = \Locale::getRegion($locale);
$variants = \Locale::getAllVariants($locale);
// Currently the only available variant is POSIX, which we don't want
// to include in the list
if (count($variants) > 0) {
return;
}
// Some languages are translated together with their region,
// i.e. "en_GB" is translated as "British English"
// we don't include these languages though because they mess up
// the name sorting
// $name = $this->langBundle->getLanguageName($displayLocale, $lang, $region);
// Some languages are simply not translated
// Example: "az" (Azerbaijani) has no translation in "af" (Afrikaans)
if (null === ($name = $this->languageBundle->getLanguageName($lang, null, $displayLocale))) {
return;
}
// "as" (Assamese) has no "Variants" block
//if (!$langBundle->get('Variants')) {
// continue;
//}
$extras = array();
// Discover the name of the script part of the locale
// i.e. in zh_Hans_MO, "Hans" is the script
if ($script) {
// Some scripts are not translated into every language
if (null === ($scriptName = $this->languageBundle->getScriptName($script, $lang, $displayLocale))) {
return;
}
$extras[] = $scriptName;
}
// Discover the name of the region part of the locale
// i.e. in de_AT, "AT" is the region
if ($region) {
// Some regions are not translated into every language
if (null === ($regionName = $this->regionBundle->getCountryName($region, $displayLocale))) {
return;
}
$extras[] = $regionName;
}
if (count($extras) > 0) {
// Remove any existing extras
// For example, in German, zh_Hans is "Chinesisch (vereinfacht)".
// The latter is the script part which is already included in the
// extras and will be appended again with the other extras.
if (preg_match('/^(.+)\s+\([^\)]+\)$/', $name, $matches)) {
$name = $matches[1];
}
$name .= ' ('.implode(', ', $extras).')';
}
return $name;
}
}

View File

@ -1,72 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
use Symfony\Component\Intl\Util\IcuVersion;
/**
* The rule for compiling the region bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class RegionBundleTransformationRule implements TransformationRuleInterface
{
/**
* {@inheritdoc}
*/
public function getBundleName()
{
return 'region';
}
/**
* {@inheritdoc}
*/
public function beforeCompile(CompilationContextInterface $context)
{
// The region data is contained in the locales bundle in ICU <= 4.2
if (IcuVersion::compare($context->getIcuVersion(), '4.2', '<=', 1)) {
return $context->getSourceDir().'/locales';
}
return $context->getSourceDir().'/region';
}
/**
* {@inheritdoc}
*/
public function afterCompile(CompilationContextInterface $context)
{
}
/**
* {@inheritdoc}
*/
public function beforeCreateStub(StubbingContextInterface $context)
{
return array(
'Countries' => Intl::getRegionBundle()->getCountryNames('en'),
);
}
/**
* {@inheritdoc}
*/
public function afterCreateStub(StubbingContextInterface $context)
{
}
}

View File

@ -1,72 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
/**
* Contains instruction for compiling a resource bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
interface TransformationRuleInterface
{
/**
* Returns the name of the compiled resource bundle.
*
* @return string The name of the bundle.
*/
public function getBundleName();
/**
* Runs instructions to be executed before compiling the sources of the
* resource bundle.
*
* @param CompilationContextInterface $context The contextual information of
* the compilation.
*
* @return string[] The source directories/files of the bundle.
*/
public function beforeCompile(CompilationContextInterface $context);
/**
* Runs instructions to be executed after compiling the sources of the
* resource bundle.
*
* @param CompilationContextInterface $context The contextual information of
* the compilation.
*/
public function afterCompile(CompilationContextInterface $context);
/**
* Runs instructions to be executed before creating the stub version of the
* resource bundle.
*
* @param StubbingContextInterface $context The contextual information of
* the compilation.
*
* @return mixed The data to include in the stub version.
*/
public function beforeCreateStub(StubbingContextInterface $context);
/**
* Runs instructions to be executed after creating the stub version of the
* resource bundle.
*
* @param StubbingContextInterface $context The contextual information of
* the compilation.
*/
public function afterCreateStub(StubbingContextInterface $context);
}

View File

@ -1,82 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
use Symfony\Component\Filesystem\Filesystem;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class StubbingContext implements StubbingContextInterface
{
/**
* @var string
*/
private $binaryDir;
/**
* @var string
*/
private $stubDir;
/**
* @var Filesystem
*/
private $filesystem;
/**
* @var string
*/
private $icuVersion;
public function __construct($binaryDir, $stubDir, Filesystem $filesystem, $icuVersion)
{
$this->binaryDir = $binaryDir;
$this->stubDir = $stubDir;
$this->filesystem = $filesystem;
$this->icuVersion = $icuVersion;
}
/**
* {@inheritdoc}
*/
public function getBinaryDir()
{
return $this->binaryDir;
}
/**
* {@inheritdoc}
*/
public function getStubDir()
{
return $this->stubDir;
}
/**
* {@inheritdoc}
*/
public function getFilesystem()
{
return $this->filesystem;
}
/**
* {@inheritdoc}
*/
public function getIcuVersion()
{
return $this->icuVersion;
}
}

View File

@ -1,48 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\ResourceBundle\Transformer;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
interface StubbingContextInterface
{
/**
* Returns the directory where the binary resource bundles are stored.
*
* @return string An absolute path to a directory.
*/
public function getBinaryDir();
/**
* Returns the directory where the stub resource bundles are stored.
*
* @return string An absolute path to a directory.
*/
public function getStubDir();
/**
* Returns a tool for manipulating the filesystem.
*
* @return \Symfony\Component\Filesystem\Filesystem The filesystem manipulator.
*/
public function getFilesystem();
/**
* Returns the ICU version of the bundles being converted.
*
* @return string The ICU version string.
*/
public function getIcuVersion();
}

View File

@ -15,4 +15,4 @@ if (!file_exists($autoload)) {
bailout('You should run "composer install --dev" in the component before running this script.');
}
require_once realpath($autoload);
require_once $autoload;

View File

@ -1,62 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Icu\IcuData;
require_once __DIR__.'/common.php';
require_once __DIR__.'/autoload.php';
if (1 !== $GLOBALS['argc']) {
bailout(<<<MESSAGE
Usage: php copy-stubs-to-component.php
Copies stub files created with create-stubs.php to the Icu component.
For running this script, the intl extension must be loaded and all vendors
must have been installed through composer:
composer install --dev
MESSAGE
);
}
echo LINE;
echo centered("ICU Resource Bundle Stub Update")."\n";
echo LINE;
if (!class_exists('\Symfony\Component\Icu\IcuData')) {
bailout('You must run "composer update --dev" before running this script.');
}
$stubBranch = '1.0.x';
if (!IcuData::isStubbed()) {
bailout("Please switch to the Icu component branch $stubBranch.");
}
$filesystem = new Filesystem();
$sourceDir = sys_get_temp_dir().'/icu-stubs';
$targetDir = IcuData::getResourceDirectory();
if (!$filesystem->exists($sourceDir)) {
bailout("The directory $sourceDir does not exist. Please run create-stubs.php first.");
}
$filesystem->remove($targetDir);
echo "Copying files from $sourceDir to $targetDir...\n";
$filesystem->mirror($sourceDir, $targetDir);
echo "Done.\n";

View File

@ -1,112 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Icu\IcuData;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\ResourceBundle\Transformer\BundleTransformer;
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\CurrencyBundleTransformationRule;
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\LanguageBundleTransformationRule;
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\LocaleBundleTransformationRule;
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\RegionBundleTransformationRule;
use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContext;
require_once __DIR__.'/common.php';
require_once __DIR__.'/autoload.php';
if (1 !== $GLOBALS['argc']) {
bailout(<<<MESSAGE
Usage: php create-stubs.php
Creates resource bundle stubs from the resource bundles in the Icu component.
For running this script, the intl extension must be loaded and all vendors
must have been installed through composer:
composer install --dev
MESSAGE
);
}
echo LINE;
echo centered("ICU Resource Bundle Stub Creation")."\n";
echo LINE;
if (!Intl::isExtensionLoaded()) {
bailout('The intl extension for PHP is not installed.');
}
if (!class_exists('\Symfony\Component\Icu\IcuData')) {
bailout('You must run "composer update --dev" before running this script.');
}
$stubBranch = '1.0.x';
if (IcuData::isStubbed()) {
bailout("Please switch to a branch of the Icu component that contains .res files (anything but $stubBranch).");
}
$shortIcuVersionInPhp = strip_minor_versions(Intl::getIcuVersion());
$shortIcuVersionInIntlComponent = strip_minor_versions(Intl::getIcuStubVersion());
$shortIcuVersionInIcuComponent = strip_minor_versions(IcuData::getVersion());
if ($shortIcuVersionInPhp !== $shortIcuVersionInIcuComponent) {
bailout("The ICU version of the component ($shortIcuVersionInIcuComponent) does not match the ICU version in the intl extension ($shortIcuVersionInPhp).");
}
if ($shortIcuVersionInIntlComponent !== $shortIcuVersionInIcuComponent) {
bailout("The ICU version of the component ($shortIcuVersionInIcuComponent) does not match the ICU version of the stub classes in the Intl component ($shortIcuVersionInIntlComponent).");
}
echo wordwrap("Make sure that you don't have any ICU development files ".
"installed. If the build fails, try to run:\n", LINE_WIDTH);
echo "\n sudo apt-get remove libicu-dev\n\n";
$icuVersionInIcuComponent = IcuData::getVersion();
echo "Compiling stubs for ICU version $icuVersionInIcuComponent.\n";
echo "Preparing stub creation...\n";
$targetDir = sys_get_temp_dir().'/icu-stubs';
$context = new StubbingContext(
IcuData::getResourceDirectory(),
$targetDir,
new Filesystem(),
$icuVersionInIcuComponent
);
$transformer = new BundleTransformer();
$transformer->addRule(new LanguageBundleTransformationRule());
$transformer->addRule(new RegionBundleTransformationRule());
$transformer->addRule(new CurrencyBundleTransformationRule());
$transformer->addRule(new LocaleBundleTransformationRule());
echo "Starting stub creation...\n";
$transformer->createStubs($context);
echo "Wrote stubs to $targetDir.\n";
$versionFile = $context->getStubDir().'/version.txt';
file_put_contents($versionFile, "$icuVersionInIcuComponent\n");
echo "Wrote $versionFile.\n";
echo "Done.\n";
echo wordwrap("Please change the Icu component to branch $stubBranch now and run:\n", LINE_WIDTH);
echo "\n php copy-stubs-to-component.php\n";

View File

@ -1,18 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\Component\Intl\Intl;
require_once __DIR__.'/common.php';
require_once __DIR__.'/autoload.php';
echo "ICU version: ";
echo Intl::getIcuVersion()."\n";

View File

@ -10,3 +10,4 @@
51 = http://source.icu-project.org/repos/icu/icu/tags/release-51-2/source
52 = http://source.icu-project.org/repos/icu/icu/tags/release-52-1/source
53 = http://source.icu-project.org/repos/icu/icu/tags/release-53-1/source
54 = http://source.icu-project.org/repos/icu/icu/tags/release-54-rc/source

View File

@ -1,56 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\Component\Intl\Intl;
require_once __DIR__.'/common.php';
require_once __DIR__.'/autoload.php';
if (1 !== $GLOBALS['argc']) {
bailout(<<<MESSAGE
Usage: php test-compat.php
Tests the compatibility of the current ICU version (bundled in ext/intl) with
different versions of symfony/icu.
For running this script, the intl extension must be loaded and all vendors
must have been installed through composer:
composer install --dev
MESSAGE
);
}
echo LINE;
echo centered("ICU Compatibility Test")."\n";
echo LINE;
echo "Your ICU version: ".Intl::getIcuVersion()."\n";
echo "Compatibility with symfony/icu:\n";
$branches = array(
'1.1.x',
'1.2.x',
);
cd(__DIR__.'/../../vendor/symfony/icu/Symfony/Component/Icu');
foreach ($branches as $branch) {
run('git checkout '.$branch.' 2>&1');
exec('php '.__DIR__.'/util/test-compat-helper.php > /dev/null 2> /dev/null', $output, $status);
echo "$branch: ".(0 === $status ? "YES" : "NO")."\n";
}
echo "Done.\n";

View File

@ -0,0 +1,295 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\Component\Intl\Data\Bundle\Reader\JsonBundleReader;
use Symfony\Component\Intl\Data\Bundle\Writer\JsonBundleWriter;
use Symfony\Component\Intl\Data\Generator\CurrencyDataGenerator;
use Symfony\Component\Intl\Data\Generator\GeneratorConfig;
use Symfony\Component\Intl\Data\Generator\LanguageDataGenerator;
use Symfony\Component\Intl\Data\Generator\LocaleDataGenerator;
use Symfony\Component\Intl\Data\Generator\RegionDataGenerator;
use Symfony\Component\Intl\Data\Generator\ScriptDataGenerator;
use Symfony\Component\Intl\Data\Provider\LanguageDataProvider;
use Symfony\Component\Intl\Data\Provider\RegionDataProvider;
use Symfony\Component\Intl\Data\Provider\ScriptDataProvider;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\Data\Bundle\Compiler\GenrbCompiler;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReader;
use Symfony\Component\Intl\Locale;
use Symfony\Component\Intl\Util\IcuVersion;
use Symfony\Component\Intl\Util\SvnRepository;
use Symfony\Component\Filesystem\Filesystem;
require_once __DIR__.'/common.php';
require_once __DIR__.'/autoload.php';
$argc = $_SERVER['argc'];
$argv = $_SERVER['argv'];
if ($argc > 3 || 2 === $argc && '-h' === $argv[1]) {
bailout(<<<MESSAGE
Usage: php update-icu-component.php <path/to/icu/source> <path/to/icu/build>
Updates the ICU data for Symfony2 to the latest version of ICU.
If you downloaded the SVN repository before, you can pass the path to the
repository source in the first optional argument.
If you also built the repository before, you can pass the directory where that
build is stored in the second parameter. The build directory needs to contain
the subdirectories bin/ and lib/.
For running this script, the intl extension must be loaded and all vendors
must have been installed through composer:
composer install --dev
MESSAGE
);
}
echo LINE;
echo centered("ICU Resource Bundle Compilation")."\n";
echo LINE;
if (!Intl::isExtensionLoaded()) {
bailout('The intl extension for PHP is not installed.');
}
$filesystem = new Filesystem();
$urls = parse_ini_file(__DIR__.'/icu.ini');
echo "icu.ini parsed. Available versions:\n";
$maxVersion = 0;
foreach ($urls as $urlVersion => $url) {
$maxVersion = IcuVersion::compare($maxVersion, $urlVersion, '<')
? $urlVersion
: $maxVersion;
echo " $urlVersion\n";
}
$shortIcuVersion = strip_minor_versions($maxVersion);
if ($argc >= 2) {
$sourceDir = $argv[1];
$svn = new SvnRepository($sourceDir);
echo "Using existing SVN repository at {$sourceDir}.\n";
} else {
echo "Starting SVN checkout for version $shortIcuVersion. This may take a while...\n";
$sourceDir = sys_get_temp_dir().'/icu-data/'.$shortIcuVersion.'/source';
$svn = SvnRepository::download($urls[$shortIcuVersion], $sourceDir);
echo "SVN checkout to {$sourceDir} complete.\n";
}
if ($argc >= 3) {
$buildDir = $argv[2];
} else {
// Always build genrb so that we can determine the ICU version of the
// download by running genrb --version
echo "Building genrb.\n";
cd($sourceDir);
echo "Running configure...\n";
$buildDir = sys_get_temp_dir().'/icu-data/'.$shortIcuVersion.'/build';
$filesystem->remove($buildDir);
$filesystem->mkdir($buildDir);
run('./configure --prefix='.$buildDir.' 2>&1');
echo "Running make...\n";
// If the directory "lib" does not exist in the download, create it or we
// will run into problems when building libicuuc.so.
$filesystem->mkdir($sourceDir.'/lib');
// If the directory "bin" does not exist in the download, create it or we
// will run into problems when building genrb.
$filesystem->mkdir($sourceDir.'/bin');
echo "[1/6] libicudata.so...";
cd($sourceDir.'/stubdata');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
echo "[2/6] libicuuc.so...";
cd($sourceDir.'/common');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
echo "[3/6] libicui18n.so...";
cd($sourceDir.'/i18n');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
echo "[4/6] libicutu.so...";
cd($sourceDir.'/tools/toolutil');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
echo "[5/6] libicuio.so...";
cd($sourceDir.'/io');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
echo "[6/6] genrb...";
cd($sourceDir.'/tools/genrb');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
}
$genrb = $buildDir.'/bin/genrb';
$genrbEnv = 'LD_LIBRARY_PATH='.$buildDir.'/lib ';
echo "Using $genrb.\n";
$icuVersionInDownload = get_icu_version_from_genrb($genrbEnv.' '.$genrb);
echo "Preparing resource bundle compilation (version $icuVersionInDownload)...\n";
$compiler = new GenrbCompiler($genrb, $genrbEnv);
$config = new GeneratorConfig($sourceDir.'/data', $icuVersionInDownload);
// Don't wrap "/data" in realpath(), in case the directory does not exist
$baseDir = realpath(__DIR__.'/..').'/data';
//$txtDir = $baseDir.'/txt';
$jsonDir = $baseDir;
//$phpDir = $baseDir.'/'.Intl::PHP;
//$resDir = $baseDir.'/'.Intl::RB_V2;
$targetDirs = array($jsonDir/*, $resDir*/);
$workingDirs = array($jsonDir/*, $txtDir, $resDir*/);
//$config->addBundleWriter($txtDir, new TextBundleWriter());
$config->addBundleWriter($jsonDir, new JsonBundleWriter());
echo "Starting resource bundle compilation. This may take a while...\n";
$filesystem->remove($workingDirs);
foreach ($workingDirs as $targetDir) {
$filesystem->mkdir(array(
$targetDir.'/'.Intl::CURRENCY_DIR,
$targetDir.'/'.Intl::LANGUAGE_DIR,
$targetDir.'/'.Intl::LOCALE_DIR,
$targetDir.'/'.Intl::REGION_DIR,
$targetDir.'/'.Intl::SCRIPT_DIR,
));
}
// We don't want to use fallback to English during generation
Locale::setDefaultFallback(null);
echo "Generating language data...\n";
$generator = new LanguageDataGenerator($compiler, Intl::LANGUAGE_DIR);
$generator->generateData($config);
//echo "Compiling...\n";
//
//$compiler->compile($txtDir.'/'.Intl::LANGUAGE_DIR, $resDir.'/'.Intl::LANGUAGE_DIR);
echo "Generating script data...\n";
$generator = new ScriptDataGenerator($compiler, Intl::SCRIPT_DIR);
$generator->generateData($config);
//echo "Compiling...\n";
//
//$compiler->compile($txtDir.'/'.Intl::SCRIPT_DIR, $resDir.'/'.Intl::SCRIPT_DIR);
echo "Generating region data...\n";
$generator = new RegionDataGenerator($compiler, Intl::REGION_DIR);
$generator->generateData($config);
//echo "Compiling...\n";
//
//$compiler->compile($txtDir.'/'.Intl::REGION_DIR, $resDir.'/'.Intl::REGION_DIR);
echo "Generating currency data...\n";
$generator = new CurrencyDataGenerator($compiler, Intl::CURRENCY_DIR);
$generator->generateData($config);
//echo "Compiling...\n";
//
//$compiler->compile($txtDir.'/'.Intl::CURRENCY_DIR, $resDir.'/'.Intl::CURRENCY_DIR);
echo "Generating locale data...\n";
$reader = new BundleEntryReader(new JsonBundleReader());
$generator = new LocaleDataGenerator(
Intl::LOCALE_DIR,
new LanguageDataProvider($jsonDir.'/'.Intl::LANGUAGE_DIR, $reader),
new ScriptDataProvider($jsonDir.'/'.Intl::SCRIPT_DIR, $reader),
new RegionDataProvider($jsonDir.'/'.Intl::REGION_DIR, $reader)
);
$generator->generateData($config);
//echo "Compiling...\n";
//
//$compiler->compile($txtDir.'/'.Intl::LOCALE_DIR, $resDir.'/'.Intl::LOCALE_DIR);
//
//$filesystem->remove($txtDir);
echo "Resource bundle compilation complete.\n";
$svnInfo = <<<SVN_INFO
SVN information
===============
URL: {$svn->getUrl()}
Revision: {$svn->getLastCommit()->getRevision()}
Author: {$svn->getLastCommit()->getAuthor()}
Date: {$svn->getLastCommit()->getDate()}
SVN_INFO;
foreach ($targetDirs as $targetDir) {
$svnInfoFile = $targetDir.'/svn-info.txt';
file_put_contents($svnInfoFile, $svnInfo);
echo "Wrote $svnInfoFile.\n";
$versionFile = $targetDir.'/version.txt';
file_put_contents($versionFile, "$icuVersionInDownload\n");
echo "Wrote $versionFile.\n";
}
echo "Done.\n";

View File

@ -1,212 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\Component\Icu\IcuData;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Intl\ResourceBundle\Compiler\BundleCompiler;
use Symfony\Component\Intl\ResourceBundle\Transformer\BundleTransformer;
use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContext;
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\CurrencyBundleTransformationRule;
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\LanguageBundleTransformationRule;
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\LocaleBundleTransformationRule;
use Symfony\Component\Intl\ResourceBundle\Transformer\Rule\RegionBundleTransformationRule;
use Symfony\Component\Intl\Util\SvnRepository;
use Symfony\Component\Filesystem\Filesystem;
require_once __DIR__.'/common.php';
require_once __DIR__.'/autoload.php';
if ($GLOBALS['argc'] > 3 || 2 === $GLOBALS['argc'] && '-h' === $GLOBALS['argv'][1]) {
bailout(<<<MESSAGE
Usage: php update-icu-component.php <path/to/icu/source> <path/to/icu/build>
Updates the ICU data for Symfony2 to the latest version of the ICU version
included in the intl extension. For example, if your intl extension includes
ICU 4.8, the script will download the latest data available for ICU 4.8.
If you downloaded the SVN repository before, you can pass the path to the
repository source in the first optional argument.
If you also built the repository before, you can pass the directory where that
build is stored in the second parameter. The build directory needs to contain
the subdirectories bin/ and lib/.
For running this script, the intl extension must be loaded and all vendors
must have been installed through composer:
composer install --dev
MESSAGE
);
}
echo LINE;
echo centered("ICU Resource Bundle Compilation")."\n";
echo LINE;
if (!Intl::isExtensionLoaded()) {
bailout('The intl extension for PHP is not installed.');
}
if (!class_exists('\Symfony\Component\Icu\IcuData')) {
bailout('You must run "composer update --dev" before running this script.');
}
$filesystem = new Filesystem();
$icuVersionInPhp = Intl::getIcuVersion();
echo "Found intl extension with ICU version $icuVersionInPhp.\n";
$shortIcuVersion = strip_minor_versions($icuVersionInPhp);
$urls = parse_ini_file(__DIR__.'/icu.ini');
if (!isset($urls[$shortIcuVersion])) {
bailout('The version '.$shortIcuVersion.' is not available in the icu.ini file.');
}
echo "icu.ini parsed. Available versions:\n";
foreach ($urls as $urlVersion => $url) {
echo " $urlVersion\n";
}
if ($GLOBALS['argc'] >= 2) {
$sourceDir = $GLOBALS['argv'][1];
$svn = new SvnRepository($sourceDir);
echo "Using existing SVN repository at {$sourceDir}.\n";
} else {
echo "Starting SVN checkout for version $shortIcuVersion. This may take a while...\n";
$sourceDir = sys_get_temp_dir().'/icu-data/'.$shortIcuVersion.'/source';
$svn = SvnRepository::download($urls[$shortIcuVersion], $sourceDir);
echo "SVN checkout to {$sourceDir} complete.\n";
}
if ($GLOBALS['argc'] >= 3) {
$buildDir = $GLOBALS['argv'][2];
} else {
// Always build genrb so that we can determine the ICU version of the
// download by running genrb --version
echo "Building genrb.\n";
cd($sourceDir);
echo "Running configure...\n";
$buildDir = sys_get_temp_dir().'/icu-data/'.$shortIcuVersion.'/build';
$filesystem->remove($buildDir);
$filesystem->mkdir($buildDir);
run('./configure --prefix='.$buildDir.' 2>&1');
echo "Running make...\n";
// If the directory "lib" does not exist in the download, create it or we
// will run into problems when building libicuuc.so.
$filesystem->mkdir($sourceDir.'/lib');
// If the directory "bin" does not exist in the download, create it or we
// will run into problems when building genrb.
$filesystem->mkdir($sourceDir.'/bin');
echo "[1/5] libicudata.so...";
cd($sourceDir.'/stubdata');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
echo "[2/5] libicuuc.so...";
cd($sourceDir.'/common');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
echo "[3/5] libicui18n.so...";
cd($sourceDir.'/i18n');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
echo "[4/5] libicutu.so...";
cd($sourceDir.'/tools/toolutil');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
echo "[5/5] genrb...";
cd($sourceDir.'/tools/genrb');
run('make 2>&1 && make install 2>&1');
echo " ok.\n";
}
$genrb = $buildDir.'/bin/genrb';
$genrbEnv = 'LD_LIBRARY_PATH='.$buildDir.'/lib ';
echo "Using $genrb.\n";
$icuVersionInDownload = get_icu_version_from_genrb($genrbEnv.' '.$genrb);
echo "Preparing resource bundle compilation (version $icuVersionInDownload)...\n";
$context = new CompilationContext(
$sourceDir.'/data',
IcuData::getResourceDirectory(),
$filesystem,
new BundleCompiler($genrb, $genrbEnv),
$icuVersionInDownload
);
$transformer = new BundleTransformer();
$transformer->addRule(new LanguageBundleTransformationRule());
$transformer->addRule(new RegionBundleTransformationRule());
$transformer->addRule(new CurrencyBundleTransformationRule());
$transformer->addRule(new LocaleBundleTransformationRule());
echo "Starting resource bundle compilation. This may take a while...\n";
$transformer->compileBundles($context);
echo "Resource bundle compilation complete.\n";
$svnInfo = <<<SVN_INFO
SVN information
===============
URL: {$svn->getUrl()}
Revision: {$svn->getLastCommit()->getRevision()}
Author: {$svn->getLastCommit()->getAuthor()}
Date: {$svn->getLastCommit()->getDate()}
SVN_INFO;
$svnInfoFile = $context->getBinaryDir().'/svn-info.txt';
file_put_contents($svnInfoFile, $svnInfo);
echo "Wrote $svnInfoFile.\n";
$versionFile = $context->getBinaryDir().'/version.txt';
file_put_contents($versionFile, "$icuVersionInDownload\n");
echo "Wrote $versionFile.\n";
echo "Done.\n";

View File

@ -1,23 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\Component\Icu\IcuData;
use Symfony\Component\Intl\ResourceBundle\Reader\BinaryBundleReader;
require_once __DIR__.'/../common.php';
require_once __DIR__.'/../autoload.php';
$reader = new BinaryBundleReader();
$reader->read(IcuData::getResourceDirectory().'/curr', 'en');
$reader->read(IcuData::getResourceDirectory().'/lang', 'en');
$reader->read(IcuData::getResourceDirectory().'/locales', 'en');
$reader->read(IcuData::getResourceDirectory().'/region', 'en');

View File

@ -0,0 +1,665 @@
{
"Version": "2.1.8.9",
"Names": {
"AED": [
"AED",
"Verenigde Arabiese Emirate dirham"
],
"AFN": [
"AFN",
"Afgaanse afgani"
],
"ALL": [
"ALL",
"Albanese lek"
],
"AMD": [
"AMD",
"Armeense dram"
],
"ANG": [
"ANG",
"Nederlands-Antilliaanse gulde"
],
"AOA": [
"AOA",
"Angolese kwanza"
],
"ARS": [
"ARS",
"Argentynse peso"
],
"AUD": [
"A$",
"Australiese dollar"
],
"AWG": [
"AWG",
"Arubaanse floryn"
],
"AZN": [
"AZN",
"Azerbeidjaanse manat"
],
"BAM": [
"BAM",
"Bosnies-Herzegowiniese omskakelbare marka"
],
"BBD": [
"BBD",
"Barbados-dollar"
],
"BDT": [
"BDT",
"Bangladesjiese taka"
],
"BGN": [
"BGN",
"Bulgaarse lev"
],
"BHD": [
"BHD",
"Bahreinse dinar"
],
"BIF": [
"BIF",
"Burundiese frank"
],
"BMD": [
"BMD",
"Bermuda-dollar"
],
"BND": [
"BND",
"Broeneise dollar"
],
"BOB": [
"BOB",
"Boliviaanse boliviano"
],
"BRL": [
"R$",
"Brasilliaanse reaal"
],
"BSD": [
"BSD",
"Bahamiaanse dollar"
],
"BTN": [
"BTN",
"Bhoetanese ngoeltroem"
],
"BWP": [
"BWP",
"Botswana pula"
],
"BYR": [
"BYR",
"Belo-Russiese roebel"
],
"BZD": [
"BZD",
"Beliziese dollar"
],
"CAD": [
"CA$",
"Kanadese dollar"
],
"CDF": [
"CDF",
"Kongolese frank"
],
"CHF": [
"CHF",
"Switserse frank"
],
"CLP": [
"CLP",
"Chileense peso"
],
"CNY": [
"CN¥",
"Sjinese joean renminbi"
],
"COP": [
"COP",
"Colombiaanse peso"
],
"CRC": [
"CRC",
"Costa Ricaanse colón"
],
"CUC": [
"CUC",
"Kubaanse omskakelbare peso"
],
"CUP": [
"CUP",
"Kubaanse peso"
],
"CVE": [
"CVE",
"Kaap Verdiese escudo"
],
"CZK": [
"CZK",
"Tsjeggiese kroon"
],
"DJF": [
"DJF",
"Djiboeti frank"
],
"DKK": [
"DKK",
"Deense kroon"
],
"DOP": [
"DOP",
"Dominikaanse peso"
],
"DZD": [
"DZD",
"Algeriese dinar"
],
"EGP": [
"EGP",
"Egiptiese pond"
],
"ERN": [
"ERN",
"Eritrese nakfa"
],
"ETB": [
"ETB",
"Etiopiese birr"
],
"EUR": [
"€",
"Euro"
],
"FJD": [
"FJD",
"Fidjiaanse dollar"
],
"FKP": [
"FKP",
"Falkland-eilande pond"
],
"GBP": [
"£",
"Britse pond"
],
"GEL": [
"GEL",
"Georgiese lari"
],
"GHC": [
"GHC",
"Ghanese cedi (19792007)"
],
"GHS": [
"GHS",
"Ghanese cedi"
],
"GIP": [
"GIP",
"Gibraltarese pond"
],
"GMD": [
"GMD",
"Gambiese dalasi"
],
"GNF": [
"GNF",
"Guinese frank"
],
"GNS": [
"GNS",
"Guinese syli"
],
"GTQ": [
"GTQ",
"Guatemalaanse quetzal"
],
"GYD": [
"GYD",
"Guyanese dollar"
],
"HKD": [
"HK$",
"Hong Kong dollar"
],
"HNL": [
"HNL",
"Hondurese lempira"
],
"HRK": [
"HRK",
"Kroatiese kuna"
],
"HTG": [
"HTG",
"Haïtiaanse gourde"
],
"HUF": [
"HUF",
"Hongaarse florint"
],
"IDR": [
"IDR",
"Indonesiese roepia"
],
"ILS": [
"₪",
"Israeliese nuwe sikkel"
],
"INR": [
"₹",
"Indiese roepee"
],
"IQD": [
"IQD",
"Irakse dinar"
],
"IRR": [
"IRR",
"Iranse rial"
],
"ISK": [
"ISK",
"Yslandse kroon"
],
"ITL": [
"ITL",
"Italiaanse lier"
],
"JMD": [
"JMD",
"Jamaikaanse dollar"
],
"JOD": [
"JOD",
"Jordaniese dinar"
],
"JPY": [
"JP¥",
"Japannese jen"
],
"KES": [
"KES",
"Keniaanse sjieling"
],
"KGS": [
"KGS",
"Kirgisiese som"
],
"KHR": [
"KHR",
"Kambodjaanse riel"
],
"KMF": [
"KMF",
"Comoraanse frank"
],
"KPW": [
"KPW",
"Noord-Koreaanse won"
],
"KRW": [
"₩",
"Suid-Koreaanse won"
],
"KWD": [
"KWD",
"Koeweitse dinar"
],
"KYD": [
"KYD",
"Cayman-eilande dollar"
],
"KZT": [
"KZT",
"Kazakse tenge"
],
"LAK": [
"LAK",
"Laosiaanse kip"
],
"LBP": [
"LBP",
"Lebanese pond"
],
"LKR": [
"LKR",
"Sri Lankaanse roepee"
],
"LRD": [
"LRD",
"Liberiese dollar"
],
"LSL": [
"LSL",
"Lesotho loti"
],
"LTL": [
"LTL",
"Litause litas"
],
"LVL": [
"LVL",
"Lettiese lats"
],
"LYD": [
"LYD",
"Libiese dinar"
],
"MAD": [
"MAD",
"Marokkaanse dirham"
],
"MDL": [
"MDL",
"Moldowiese leu"
],
"MGA": [
"MGA",
"Malgassiese ariary"
],
"MKD": [
"MKD",
"Macedoniese denar"
],
"MMK": [
"MMK",
"Mianmese kyat"
],
"MNT": [
"MNT",
"Mongoolse toegrik"
],
"MOP": [
"MOP",
"Macaose pataca"
],
"MRO": [
"MRO",
"Mauritaniese ouguiya"
],
"MUR": [
"MUR",
"Mauritiaanse rupee"
],
"MVR": [
"MVR",
"Malediviese rufia"
],
"MWK": [
"MWK",
"Malawiese kwacha"
],
"MXN": [
"MXN",
"Meksikaanse peso"
],
"MYR": [
"MYR",
"Maleisiese ringgit"
],
"MZM": [
"MZM",
"Mosambiekse metical (19802006)"
],
"MZN": [
"MZN",
"Mosambiekse metical"
],
"NAD": [
"NAD",
"Namibiese dollar"
],
"NGN": [
"NGN",
"Nigeriese naira"
],
"NIO": [
"NIO",
"Nicaraguaanse córdoba"
],
"NOK": [
"NOK",
"Noorse kroon"
],
"NPR": [
"NPR",
"Nepalese roepee"
],
"NZD": [
"NZ$",
"Nieu-Seeland dollar"
],
"OMR": [
"OMR",
"Omaanse rial"
],
"PAB": [
"PAB",
"Panamese balboa"
],
"PEN": [
"PEN",
"Peruaanse nuwe sol"
],
"PGK": [
"PGK",
"Papoea-Nieu-Guinese kina"
],
"PHP": [
"PHP",
"Filippynse peso"
],
"PKR": [
"PKR",
"Pakistanse roepee"
],
"PLN": [
"PLN",
"Poolse zloty"
],
"PYG": [
"PYG",
"Paraguaanse guarani"
],
"QAR": [
"QAR",
"Katarrese rial"
],
"RON": [
"RON",
"Roemeense leu"
],
"RSD": [
"RSD",
"Serbiese dinar"
],
"RUB": [
"RUB",
"Russiese roebel"
],
"RWF": [
"RWF",
"Rwandiese frank"
],
"SAR": [
"SAR",
"Saoedi-Arabiese riyal"
],
"SBD": [
"SBD",
"Salomonseilande dollar"
],
"SCR": [
"SCR",
"Seychellese rupee"
],
"SDG": [
"SDG",
"Soedannese pond"
],
"SDP": [
"SDP",
"Soedannese pond (19571998)"
],
"SEK": [
"SEK",
"Sweedse kroon"
],
"SGD": [
"SGD",
"Singapoer dollar"
],
"SHP": [
"SHP",
"Sint Helena pond"
],
"SLL": [
"SLL",
"Sierra Leoniese leone"
],
"SOS": [
"SOS",
"Somaliese sjieling"
],
"SRD": [
"SRD",
"Surinaamse dollar"
],
"SSP": [
"SSP",
"Suid-Soedanese pond"
],
"STD": [
"STD",
"São Tomé en Príncipe dobra"
],
"SYP": [
"SYP",
"Siriese pond"
],
"SZL": [
"SZL",
"Swazilandse lilangeni"
],
"THB": [
"฿",
"Thaise baht"
],
"TJS": [
"TJS",
"Tadjikse roebel"
],
"TMT": [
"TMT",
"Turkmeense manat"
],
"TND": [
"TND",
"Tunisiese dinar"
],
"TOP": [
"TOP",
"Tongaanse paanga"
],
"TRL": [
"TRL",
"Turkse lier (19222005)"
],
"TRY": [
"TRY",
"Turkse lier"
],
"TTD": [
"TTD",
"Trinidad en Tobago dollar"
],
"TWD": [
"NT$",
"Nuwe Taiwanese dollar"
],
"TZS": [
"TZS",
"Tanzaniese sjieling"
],
"UAH": [
"UAH",
"Oekraïnse hriwna"
],
"UGX": [
"UGX",
"Ugandese sjieling"
],
"USD": [
"US$",
"Amerikaanse dollar"
],
"UYU": [
"UYU",
"Uruguaanse peso"
],
"UZS": [
"UZS",
"Oezbekiese som"
],
"VEF": [
"VEF",
"Venezolaanse bolivar"
],
"VND": [
"₫",
"Viëtnamese dong"
],
"VUV": [
"VUV",
"Vanuatuse vatu"
],
"WST": [
"WST",
"Samoaanse tala"
],
"XAF": [
"FCFA",
"CFA frank BEAC"
],
"XCD": [
"EC$",
"Oos-Karibbiese dollar"
],
"XOF": [
"CFA",
"CFA frank BCEAO"
],
"XPF": [
"CFPF",
"CFP-frank"
],
"YER": [
"YER",
"Jemenitiese rial"
],
"ZAR": [
"R",
"Suid-Afrikaanse rand"
],
"ZMK": [
"ZMK",
"Zambiese kwacha (19682012)"
],
"ZMW": [
"ZMW",
"Zambiese kwacha"
],
"ZWD": [
"ZWD",
"Zimbabwiese dollar"
]
}
}

View File

@ -0,0 +1,9 @@
{
"Version": "2.1.8.19",
"Names": {
"NAD": [
"$",
"Namibiese dollar"
]
}
}

View File

@ -0,0 +1,225 @@
{
"Version": "2.1.7.39",
"Names": {
"AED": [
"AED",
"Ɛmirete Arab Nkabɔmu Deram"
],
"AOA": [
"AOA",
"Angola Kwanza"
],
"AUD": [
"A$",
"Ɔstrelia Dɔla"
],
"BHD": [
"BHD",
"Baren Dina"
],
"BIF": [
"BIF",
"Burundi Frank"
],
"BWP": [
"BWP",
"Botswana Pula"
],
"CAD": [
"CA$",
"Kanada Dɔla"
],
"CDF": [
"CDF",
"Kongo Frank"
],
"CNY": [
"CN¥",
"Yuan"
],
"CVE": [
"CVE",
"Ɛskudo"
],
"DJF": [
"DJF",
"Gyebuti Frank"
],
"DZD": [
"DZD",
"Ɔlgyeria Dina"
],
"EGP": [
"EGP",
"Egypt Pɔn"
],
"ERN": [
"ERN",
"Ɛretereya Nakfa"
],
"ETB": [
"ETB",
"Itiopia Bir"
],
"EUR": [
"€",
"Iro"
],
"GBP": [
"£",
"Breten Pɔn"
],
"GHC": [
"GHC",
"Ghana Sidi (19792007)"
],
"GHS": [
"GH₵",
"Ghana Sidi"
],
"GMD": [
"GMD",
"Gambia Dalasi"
],
"GNS": [
"GNS",
"Gini Frank"
],
"INR": [
"₹",
"India Rupi"
],
"JPY": [
"JP¥",
"Gyapan Yɛn"
],
"KES": [
"KES",
"Kenya Hyelen"
],
"KMF": [
"KMF",
"Komoro Frank"
],
"LRD": [
"LRD",
"Laeberia Dɔla"
],
"LSL": [
"LSL",
"Lesoto Loti"
],
"LYD": [
"LYD",
"Libya Dina"
],
"MAD": [
"MAD",
"Moroko Diram"
],
"MGA": [
"MGA",
"Madagasi Frank"
],
"MRO": [
"MRO",
"Mɔretenia Ouguiya"
],
"MUR": [
"MUR",
"Mɔrehyeɔs Rupi"
],
"MWK": [
"MWK",
"Malawi Kwacha"
],
"MZM": [
"MZM",
"Mozambik Metical"
],
"NAD": [
"NAD",
"Namibia Dɔla"
],
"NGN": [
"NGN",
"Naegyeria Naira"
],
"RWF": [
"RWF",
"Rewanda Frank"
],
"SAR": [
"SAR",
"Saudi Riyal"
],
"SCR": [
"SCR",
"Seyhyɛls Rupi"
],
"SDG": [
"SDG",
"Sudan Dina"
],
"SDP": [
"SDP",
"Sudan Pɔn"
],
"SHP": [
"SHP",
"St Helena Pɔn"
],
"SLL": [
"SLL",
"Leone"
],
"SOS": [
"SOS",
"Somailia Hyelen"
],
"STD": [
"STD",
"Sao Tome ne Principe Dobra"
],
"SZL": [
"SZL",
"Lilangeni"
],
"TND": [
"TND",
"Tunisia Dina"
],
"TZS": [
"TZS",
"Tanzania Hyelen"
],
"UGX": [
"UGX",
"Uganda Hyelen"
],
"USD": [
"US$",
"Amɛrika Dɔla"
],
"XAF": [
"FCFA",
"Sefa"
],
"ZAR": [
"ZAR",
"Afrika Anaafo Rand"
],
"ZMK": [
"ZMK",
"Zambia Kwacha (19682012)"
],
"ZMW": [
"ZMW",
"Zambia Kwacha"
],
"ZWD": [
"ZWD",
"Zimbabwe Dɔla"
]
}
}

View File

@ -0,0 +1,649 @@
{
"Version": "2.1.8.9",
"Names": {
"AED": [
"AED",
"የተባበሩት የአረብ ኤምረትስ ዲርሀም"
],
"AFN": [
"AFN",
"የአፍጋን አፍጋኒ"
],
"ALL": [
"ALL",
"የአልባንያ ሌክ"
],
"AMD": [
"AMD",
"የአርመን ድራም"
],
"ANG": [
"ANG",
"ኔዘርላንድስ አንቲሊአን ጊልደር"
],
"AOA": [
"AOA",
"የአንጎላ ኩዋንዛ"
],
"ARS": [
"ARS",
"የአርጀንቲና ፔሶ"
],
"AUD": [
"AU$",
"የአውስትራሊያ ዶላር"
],
"AWG": [
"AWG",
"አሩባን ፍሎሪን"
],
"AZN": [
"AZN",
"የአዛርባጃን ማናት"
],
"BAM": [
"BAM",
"የቦስኒያ ሄርዞጎቪና የሚመነዘር ማርክ"
],
"BBD": [
"BBD",
"የባርቤዶስ ዶላር"
],
"BDT": [
"BDT",
"የባንግላዲሽ ታካ"
],
"BGN": [
"BGN",
"የቡልጋሪያ ሌቭ"
],
"BHD": [
"BHD",
"የባኽሬን ዲናር"
],
"BIF": [
"BIF",
"የብሩንዲ ፍራንክ"
],
"BMD": [
"BMD",
"የቤርሙዳ ዶላር"
],
"BND": [
"BND",
"የብሩኔ ዶላር"
],
"BOB": [
"BOB",
"የቦሊቪያ ቦሊቪያኖ"
],
"BRL": [
"R$",
"የብራዚል ሪል"
],
"BSD": [
"BSD",
"የባሃማስ ዶላር"
],
"BTN": [
"BTN",
"ብሁታኒዝ ንጉልትረም"
],
"BWP": [
"BWP",
"የቦትስዋና ፑላ"
],
"BYR": [
"BYR",
"የቤላሩስያ ሩብል"
],
"BZD": [
"BZD",
"የቤሊዝ ዶላር"
],
"CAD": [
"CA$",
"የካናዳ ዶላር"
],
"CDF": [
"CDF",
"የኮንጐ ፍራንክ ኮንጐሌዝ"
],
"CHF": [
"CHF",
"የስዊስ ፍራንክ"
],
"CLP": [
"CLP",
"የቺሊ ፔሶ"
],
"CNY": [
"CN¥",
"የቻይና የን"
],
"COP": [
"COP",
"የኮሎምቢያ ፔሶ"
],
"CRC": [
"CRC",
"የኮስታሪካ ኮሎን"
],
"CUC": [
"CUC",
"የኩባ የሚመነዘር ፔሶ"
],
"CUP": [
"CUP",
"የኩባ ፔሶ"
],
"CVE": [
"CVE",
"የኬፕ ቫርዲ ኤስኩዶ"
],
"CZK": [
"CZK",
"ቼክ ሪፐብሊክ ኮሩና"
],
"DJF": [
"DJF",
"የጅቡቲ ፍራንክ"
],
"DKK": [
"DKK",
"የዴንማርክ ክሮን"
],
"DOP": [
"DOP",
"የዶሚኒክ ፔሶ"
],
"DZD": [
"DZD",
"የአልጄሪያ ዲናር"
],
"EGP": [
"EGP",
"የግብጽ ፓውንድ"
],
"ERN": [
"ERN",
"የኤርትራ ናቅፋ"
],
"ETB": [
"ብር",
"የኢትዮጵያ ብር"
],
"EUR": [
"€",
"ዩሮ"
],
"FJD": [
"FJD",
"የፊጂ ዶላር"
],
"FKP": [
"FKP",
"የፎክላንድ ደሴቶች ፓውንድ"
],
"GBP": [
"£",
"የእንግሊዝ ፓውንድ ስተርሊንግ"
],
"GEL": [
"GEL",
"የጆርጅያ ላሪ"
],
"GHC": [
"GHC",
"የጋና ሴዲ"
],
"GHS": [
"GHS",
"የጋና ሲዲ"
],
"GIP": [
"GIP",
"ጂብራልተር ፓውንድ"
],
"GMD": [
"GMD",
"የጋምቢያ ዳላሲ"
],
"GNF": [
"GNF",
"የጊኒ ፍራንክ"
],
"GTQ": [
"GTQ",
"ጓቲማላን ኩቲዛል"
],
"GYD": [
"GYD",
"የጉየና ዶላር"
],
"HKD": [
"HK$",
"የሆንግኮንግ ዶላር"
],
"HNL": [
"HNL",
"የሃንዱራ ሌምፓአይራ"
],
"HRK": [
"HRK",
"የክሮሽያ ኩና"
],
"HTG": [
"HTG",
"የሃያቲ ጓርዴ"
],
"HUF": [
"HUF",
"የሁንጋሪ ፎሪንት"
],
"IDR": [
"IDR",
"የኢንዶኔዥያ ሩፒሃ"
],
"ILS": [
"₪",
"የእስራኤል አዲስ ሽቅል"
],
"INR": [
"₹",
"የሕንድ ሩፒ"
],
"IQD": [
"IQD",
"የኢራቅ ዲናር"
],
"IRR": [
"IRR",
"የኢራን ሪአል"
],
"ISK": [
"ISK",
"የአይስላንድ ክሮና"
],
"JMD": [
"JMD",
"የጃማይካ ዶላር"
],
"JOD": [
"JOD",
"የጆርዳን ዲናር"
],
"JPY": [
"JP¥",
"የጃፓን የን"
],
"KES": [
"KES",
"የኬኒያ ሺሊንግ"
],
"KGS": [
"KGS",
"የኪርጊስታን ሶም"
],
"KHR": [
"KHR",
"የካምቦዲያ ሬል"
],
"KMF": [
"KMF",
"የኮሞሮ ፍራንክ"
],
"KPW": [
"KPW",
"የሰሜን ኮሪያ ዎን"
],
"KRW": [
"₩",
"የደቡብ ኮሪያ ዎን"
],
"KWD": [
"KWD",
"የኩዌት ዲናር"
],
"KYD": [
"KYD",
"የካይማን ደሴቶች ዶላር"
],
"KZT": [
"KZT",
"የካዛኪስታን ተንጌ"
],
"LAK": [
"LAK",
"የላኦቲ ኪፕ"
],
"LBP": [
"LBP",
"የሊባኖስ ፓውንድ"
],
"LKR": [
"LKR",
"የሲሪላንካ ሩፒ"
],
"LRD": [
"LRD",
"የላይቤሪያ ዶላር"
],
"LSL": [
"LSL",
"የሌሶቶ ሎቲ"
],
"LTL": [
"LTL",
"ሊቱዌንያን ሊታስ"
],
"LVL": [
"LVL",
"የላቲቫ ላትስ"
],
"LYD": [
"LYD",
"የሊቢያ ዲናር"
],
"MAD": [
"MAD",
"የሞሮኮ ዲርሀም"
],
"MDL": [
"MDL",
"ሞልዶቫን ሊኡ"
],
"MGA": [
"MGA",
"የማደጋስካር ማላጋስይ አሪያርይ"
],
"MKD": [
"MKD",
"የሜቆድንያ ዲናር"
],
"MMK": [
"MMK",
"ምያንማ ክያት"
],
"MNT": [
"MNT",
"የሞንጎሊያን ቱግሪክ"
],
"MOP": [
"MOP",
"የማካኔዝ ፓታካ"
],
"MRO": [
"MRO",
"የሞሪቴኒያ ኦውጉያ"
],
"MUR": [
"MUR",
"የሞሪሸስ ሩፒ"
],
"MVR": [
"MVR",
"የማልዲቫ ሩፊያ"
],
"MWK": [
"MWK",
"የማላዊ ኩዋቻ"
],
"MXN": [
"MX$",
"የሜክሲኮ ፔሶ"
],
"MYR": [
"MYR",
"የማሌዥያ ሪንጊት"
],
"MZN": [
"MZN",
"የሞዛምቢክ ሜቲካል"
],
"NAD": [
"NAD",
"የናሚቢያ ዶላር"
],
"NGN": [
"NGN",
"የናይጄሪያ ናይራ"
],
"NIO": [
"NIO",
"የኒካራጓ ኮርዶባ"
],
"NOK": [
"NOK",
"የኖርዌይ ክሮን"
],
"NPR": [
"NPR",
"የኔፓል ሩፒ"
],
"NZD": [
"NZ$",
"የኒውዚላንድ ዶላር"
],
"OMR": [
"OMR",
"የኦማን ሪአል"
],
"PAB": [
"PAB",
"ፓናማኒአን ባልቦአ"
],
"PEN": [
"PEN",
"የፔሩቪያ ኑኤቮ ሶል"
],
"PGK": [
"PGK",
"የፓፕዋ ኒው ጊኒ ኪና"
],
"PHP": [
"PHP",
"የፊሊፒንስ ፔሶ"
],
"PKR": [
"PKR",
"የፓኪስታን ሩፒ"
],
"PLN": [
"PLN",
"የፖላንድ ዝሎቲ"
],
"PYG": [
"PYG",
"የፓራጓይ ጉአራኒ"
],
"QAR": [
"QAR",
"የኳታር ሪአል"
],
"RON": [
"RON",
"የሮማኒያ ለው"
],
"RSD": [
"RSD",
"የሰርቢያ ዲናር"
],
"RUB": [
"RUB",
"የሩስያ ሩብል"
],
"RWF": [
"RWF",
"የሩዋንዳ ፍራንክ"
],
"SAR": [
"SAR",
"የሳውዲ ሪያል"
],
"SBD": [
"SBD",
"የሰለሞን ደሴቶች ዶላር"
],
"SCR": [
"SCR",
"የሲሼል ሩፒ"
],
"SDG": [
"SDG",
"የሱዳን ዲናር"
],
"SDP": [
"SDP",
"የሱዳን ፓውንድ"
],
"SEK": [
"SEK",
"የስዊድን ክሮና"
],
"SGD": [
"SGD",
"የሲንጋፖር ዶላር"
],
"SHP": [
"SHP",
"የሴይንት ሔሌና ፓውንድ"
],
"SLL": [
"SLL",
"የሴራሊዎን ሊዎን"
],
"SOS": [
"SOS",
"የሶማሌ ሺሊንግ"
],
"SRD": [
"SRD",
"የሰርናሜዝ ዶላር"
],
"SSP": [
"SSP",
"የደቡብ ሱዳን ፓውንድ"
],
"STD": [
"STD",
"የሳኦ ቶመ እና ፕሪንሲፐ ዶብራ"
],
"SYP": [
"SYP",
"የሲሪያ ፓውንድ"
],
"SZL": [
"SZL",
"የስዋዚላንድ ሊላንገኒ"
],
"THB": [
"฿",
"የታይላንድ ባህት"
],
"TJS": [
"TJS",
"የታጂክስታን ሶሞኒ"
],
"TMT": [
"TMT",
"ቱርክሜኒስታኒ ማናት"
],
"TND": [
"TND",
"የቱኒዚያ ዲናር"
],
"TOP": [
"TOP",
"ቶንጋን ፓ’አንጋ"
],
"TRY": [
"TRY",
"የቱርክ ሊራ"
],
"TTD": [
"TTD",
"የትሪንዳድ እና ቶቤጎዶላር"
],
"TWD": [
"NT$",
"የአዲሷ ታይዋን ዶላር"
],
"TZS": [
"TZS",
"የታንዛኒያ ሺሊንግ"
],
"UAH": [
"UAH",
"የዩክሬን ሀሪይቭኒአ"
],
"UGX": [
"UGX",
"የዩጋንዳ ሺሊንግ"
],
"USD": [
"US$",
"የአሜሪካን ዶላር"
],
"UYU": [
"UYU",
"የኡራጓይ ፔሶ"
],
"UZS": [
"UZS",
"የኡዝፔኪስታን ሶም"
],
"VEF": [
"VEF",
"የቬንዝዌላ ቦሊቫር"
],
"VND": [
"₫",
"የቭየትናም ዶንግ"
],
"VUV": [
"VUV",
"የቫንዋንቱ ቫቱ"
],
"WST": [
"WST",
"ሳሞአን ታላ"
],
"XAF": [
"FCFA",
"ሴኤፍአ ፍራንክ ቤእአሴ"
],
"XCD": [
"EC$",
"የምዕራብ ካሪብያን ዶላር"
],
"XOF": [
"CFA",
"ሴኤፍአ ፍራንክ ቤሴእአኦ"
],
"XPF": [
"CFPF",
"ሲ ኤፍ ፒ ፍራንክ"
],
"YER": [
"YER",
"የየመን ሪአል"
],
"ZAR": [
"ZAR",
"የደቡብ አፍሪካ ራንድ"
],
"ZMK": [
"ZMK",
"የዛምቢያ ክዋቻ (19682012)"
],
"ZMW": [
"ZMW",
"የዛምቢያ ክዋቻ"
],
"ZWD": [
"ZWD",
"የዚምቧቡዌ ዶላር"
]
}
}

View File

@ -0,0 +1,977 @@
{
"Version": "2.1.8.9",
"Names": {
"ADP": [
"ADP",
"بيستا أندوري"
],
"AED": [
"د.إ.",
"درهم إماراتي"
],
"AFA": [
"AFA",
"أفغاني - 1927-2002"
],
"AFN": [
"AFN",
"أفغاني"
],
"ALL": [
"ALL",
"ليك ألباني"
],
"AMD": [
"AMD",
"درام أرميني"
],
"ANG": [
"ANG",
"غيلدر هولندي أنتيلي"
],
"AOA": [
"AOA",
"كوانزا أنجولي"
],
"AOK": [
"AOK",
"كوانزا أنجولي - 1977-1990"
],
"AON": [
"AON",
"كوانزا أنجولي جديدة - 1990-2000"
],
"AOR": [
"AOR",
"كوانزا أنجولي معدلة - 1995 - 1999"
],
"ARA": [
"ARA",
"استرال أرجنتيني"
],
"ARP": [
"ARP",
"بيزو أرجنتيني - 1983-1985"
],
"ARS": [
"ARS",
"بيزو أرجنتيني"
],
"ATS": [
"ATS",
"شلن نمساوي"
],
"AUD": [
"AU$",
"دولار أسترالي"
],
"AWG": [
"AWG",
"فلورن أروبي"
],
"AZM": [
"AZM",
"مانات أذريبجاني"
],
"AZN": [
"AZN",
"مانات أذربيجان"
],
"BAD": [
"BAD",
"دينار البوسنة والهرسك"
],
"BAM": [
"BAM",
"مارك البوسنة والهرسك قابل للتحويل"
],
"BBD": [
"BBD",
"دولار بربادوسي"
],
"BDT": [
"BDT",
"تاكا بنجلاديشي"
],
"BEC": [
"BEC",
"فرنك بلجيكي قابل للتحويل"
],
"BEF": [
"BEF",
"فرنك بلجيكي"
],
"BEL": [
"BEL",
"فرنك بلجيكي مالي"
],
"BGN": [
"BGN",
"ليف بلغاري"
],
"BHD": [
"د.ب.",
"دينار بحريني"
],
"BIF": [
"BIF",
"فرنك بروندي"
],
"BMD": [
"BMD",
"دولار برمودي"
],
"BND": [
"BND",
"دولار بروناي"
],
"BOB": [
"BOB",
"بوليفيانو بوليفي"
],
"BOP": [
"BOP",
"بيزو بوليفي"
],
"BOV": [
"BOV",
"مفدول بوليفي"
],
"BRB": [
"BRB",
"نوفو كروزايرو برازيلي - 1967-1986"
],
"BRC": [
"BRC",
"كروزادو برازيلي"
],
"BRE": [
"BRE",
"كروزايرو برازيلي - 1990-1993"
],
"BRL": [
"R$",
"ريال برازيلي"
],
"BSD": [
"BSD",
"دولار باهامي"
],
"BTN": [
"BTN",
"نولتوم بوتاني"
],
"BUK": [
"BUK",
"كيات بورمي"
],
"BWP": [
"BWP",
"بولا بتسواني"
],
"BYB": [
"BYB",
"روبل بيلاروسي جديد - 1994-1999"
],
"BYR": [
"BYR",
"روبل بيلاروسي"
],
"BZD": [
"BZD",
"دولار بليزي"
],
"CAD": [
"CA$",
"دولار كندي"
],
"CDF": [
"CDF",
"فرنك كونغولي"
],
"CHF": [
"CHF",
"فرنك سويسري"
],
"CLP": [
"CLP",
"بيزو شيلي"
],
"CNY": [
"ي.ص",
"يوان صيني"
],
"COP": [
"COP",
"بيزو كولومبي"
],
"CRC": [
"CRC",
"كولن كوستا ريكي"
],
"CSD": [
"CSD",
"دينار صربي قديم"
],
"CSK": [
"CSK",
"كرونة تشيكوسلوفاكيا"
],
"CUC": [
"CUC",
"بيزو كوبي قابل للتحويل"
],
"CUP": [
"CUP",
"بيزو كوبي"
],
"CVE": [
"CVE",
"اسكودو الرأس الخضراء"
],
"CYP": [
"CYP",
"جنيه قبرصي"
],
"CZK": [
"CZK",
"كرونة تشيكية"
],
"DDM": [
"DDM",
"أوستمارك ألماني شرقي"
],
"DEM": [
"DEM",
"مارك ألماني"
],
"DJF": [
"DJF",
"فرنك جيبوتي"
],
"DKK": [
"DKK",
"كرونة دانماركي"
],
"DOP": [
"DOP",
"بيزو الدومنيكان"
],
"DZD": [
"د.ج.",
"دينار جزائري"
],
"EEK": [
"EEK",
"كرونة استونية"
],
"EGP": [
"ج.م.",
"جنيه مصري"
],
"ERN": [
"ERN",
"ناكفا أريتري"
],
"ESP": [
"ESP",
"بيزيتا إسباني"
],
"ETB": [
"ETB",
"بير أثيوبي"
],
"EUR": [
"€",
"يورو"
],
"FIM": [
"FIM",
"ماركا فنلندي"
],
"FJD": [
"FJD",
"دولار فيجي"
],
"FKP": [
"FKP",
"جنيه جزر فوكلاند"
],
"FRF": [
"FRF",
"فرنك فرنسي"
],
"GBP": [
"£",
"جنيه إسترليني"
],
"GEL": [
"GEL",
"لارى جورجي"
],
"GHC": [
"GHC",
"سيدي غاني"
],
"GHS": [
"GHS",
"سيدي غانا"
],
"GIP": [
"GIP",
"جنيه جبل طارق"
],
"GMD": [
"GMD",
"دلاسي جامبي"
],
"GNF": [
"GNF",
"فرنك غينيا"
],
"GNS": [
"GNS",
"سيلي غينيا"
],
"GQE": [
"GQE",
"اكويل جونينا غينيا الاستوائيّة"
],
"GRD": [
"GRD",
"دراخما يوناني"
],
"GTQ": [
"GTQ",
"كوتزال جواتيمالا"
],
"GWE": [
"GWE",
"اسكود برتغالي غينيا"
],
"GWP": [
"GWP",
"بيزو غينيا بيساو"
],
"GYD": [
"GYD",
"دولار غيانا"
],
"HKD": [
"HK$",
"دولار هونج كونج"
],
"HNL": [
"HNL",
"ليمبيرا هنداروس"
],
"HRD": [
"HRD",
"دينار كرواتي"
],
"HRK": [
"HRK",
"كونا كرواتي"
],
"HTG": [
"HTG",
"جوردى هايتي"
],
"HUF": [
"HUF",
"فورينت مجري"
],
"IDR": [
"ر.إن.",
"روبية إندونيسية"
],
"IEP": [
"IEP",
"جنيه إيرلندي"
],
"ILP": [
"ILP",
"جنيه إسرائيلي"
],
"ILS": [
"₪",
"شيكل إسرائيلي جديد"
],
"INR": [
"ر.ه.",
"روبيه هندي"
],
"IQD": [
"د.ع.",
"دينار عراقي"
],
"IRR": [
"ر.إ.",
"ريال إيراني"
],
"ISK": [
"ISK",
"كرونه أيسلندي"
],
"ITL": [
"ITL",
"ليرة إيطالية"
],
"JMD": [
"JMD",
"دولار جامايكي"
],
"JOD": [
"د.أ.",
"دينار أردني"
],
"JPY": [
"JP¥",
"ين ياباني"
],
"KES": [
"KES",
"شلن كينيي"
],
"KGS": [
"KGS",
"سوم قيرغستاني"
],
"KHR": [
"KHR",
"رييال كمبودي"
],
"KMF": [
"ف.ج.ق.",
"فرنك جزر القمر"
],
"KPW": [
"KPW",
"وون كوريا الشمالية"
],
"KRW": [
"₩",
"وون كوريا الجنوبية"
],
"KWD": [
"د.ك.",
"دينار كويتي"
],
"KYD": [
"KYD",
"دولار جزر كيمن"
],
"KZT": [
"KZT",
"تينغ كازاخستاني"
],
"LAK": [
"LAK",
"كيب لاوسي"
],
"LBP": [
"ل.ل.",
"جنية لبناني"
],
"LKR": [
"LKR",
"روبية سريلانكية"
],
"LRD": [
"LRD",
"دولار ليبيري"
],
"LSL": [
"LSL",
"لوتي ليسوتو"
],
"LTL": [
"LTL",
"ليتا ليتوانية"
],
"LTT": [
"LTT",
"تالوناس ليتواني"
],
"LUC": [
"LUC",
"فرنك لوكسمبرج قابل للتحويل"
],
"LUF": [
"LUF",
"فرنك لوكسمبرج"
],
"LUL": [
"LUL",
"فرنك لوكسمبرج المالي"
],
"LVL": [
"LVL",
"لاتس لاتفيا"
],
"LVR": [
"LVR",
"روبل لاتفيا"
],
"LYD": [
"د.ل.",
"دينار ليبي"
],
"MAD": [
"د.م.",
"درهم مغربي"
],
"MAF": [
"MAF",
"فرنك مغربي"
],
"MDL": [
"MDL",
"ليو مولدوفي"
],
"MGA": [
"MGA",
"أرياري مدغشقر"
],
"MGF": [
"MGF",
"فرنك مدغشقر"
],
"MKD": [
"MKD",
"دينار مقدوني"
],
"MLF": [
"MLF",
"فرنك مالي"
],
"MMK": [
"MMK",
"كيات ميانمار"
],
"MNT": [
"MNT",
"توغروغ منغولي"
],
"MOP": [
"MOP",
"باتاكا ماكاوي"
],
"MRO": [
"أ.م.",
"أوقية موريتانية"
],
"MTL": [
"MTL",
"ليرة مالطية"
],
"MTP": [
"MTP",
"جنيه مالطي"
],
"MUR": [
"MUR",
"روبية موريشيوسية"
],
"MVR": [
"MVR",
"روفيه جزر المالديف"
],
"MWK": [
"MWK",
"كواشا مالاوي"
],
"MXN": [
"MX$",
"بيزو مكسيكي"
],
"MXP": [
"MXP",
"بيزو فضي مكسيكي - 1861-1992"
],
"MYR": [
"MYR",
"رينغيت ماليزي"
],
"MZE": [
"MZE",
"اسكود موزمبيقي"
],
"MZN": [
"MZN",
"متكال موزمبيقي"
],
"NAD": [
"NAD",
"دولار ناميبي"
],
"NGN": [
"NGN",
"نايرا نيجيري"
],
"NIC": [
"NIC",
"كوردوبة نيكاراجوا"
],
"NIO": [
"NIO",
"قرطبة نيكاراغوا"
],
"NLG": [
"NLG",
"جلدر هولندي"
],
"NOK": [
"NOK",
"كرونة نرويجية"
],
"NPR": [
"NPR",
"روبية نيبالي"
],
"NZD": [
"NZ$",
"دولار نيوزيلندي"
],
"OMR": [
"ر.ع.",
"ريال عماني"
],
"PAB": [
"PAB",
"بالبوا بنمي"
],
"PEN": [
"PEN",
"سول جديد البيرو"
],
"PGK": [
"PGK",
"كينا بابوا غينيا الجديدة"
],
"PHP": [
"PHP",
"بيزو فلبيني"
],
"PKR": [
"ر.ب.",
"روبية باكستاني"
],
"PLN": [
"PLN",
"زلوتي بولندي"
],
"PLZ": [
"PLZ",
"زلوتي بولندي - 1950-1995"
],
"PTE": [
"PTE",
"اسكود برتغالي"
],
"PYG": [
"PYG",
"جواراني باراجواي"
],
"QAR": [
"ر.ق.",
"ريال قطري"
],
"RHD": [
"RHD",
"دولار روديسي"
],
"ROL": [
"ROL",
"ليو روماني قديم"
],
"RON": [
"RON",
"ليو روماني"
],
"RSD": [
"RSD",
"دينار صربي"
],
"RUB": [
"RUB",
"روبل روسي"
],
"RUR": [
"RUR",
"روبل روسي - 1991-1998"
],
"RWF": [
"RWF",
"فرنك رواندي"
],
"SAR": [
"ر.س.",
"ريال سعودي"
],
"SBD": [
"SBD",
"دولار جزر سليمان"
],
"SCR": [
"SCR",
"روبية سيشيلية"
],
"SDD": [
"د.س.",
"دينار سوداني"
],
"SDG": [
"ج.س.",
"جنيه سوداني"
],
"SDP": [
"SDP",
"جنيه سوداني قديم"
],
"SEK": [
"SEK",
"كرونة سويدية"
],
"SGD": [
"SGD",
"دولار سنغافوري"
],
"SHP": [
"SHP",
"جنيه سانت هيلين"
],
"SIT": [
"SIT",
"تولار سلوفيني"
],
"SKK": [
"SKK",
"كرونة سلوفاكية"
],
"SLL": [
"SLL",
"ليون سيراليوني"
],
"SOS": [
"SOS",
"شلن صومالي"
],
"SRD": [
"SRD",
"دولار سورينامي"
],
"SRG": [
"SRG",
"جلدر سورينامي"
],
"SSP": [
"ج.ج.س.",
"جنيه جنوب السودان"
],
"STD": [
"STD",
"دوبرا ساو تومي وبرينسيبي"
],
"SUR": [
"SUR",
"روبل سوفيتي"
],
"SVC": [
"SVC",
"كولون سلفادوري"
],
"SYP": [
"ل.س.",
"ليرة سورية"
],
"SZL": [
"SZL",
"ليلانجيني سوازيلندي"
],
"THB": [
"฿",
"باخت تايلاندي"
],
"TJR": [
"TJR",
"روبل طاجيكستاني"
],
"TJS": [
"TJS",
"سوموني طاجيكستاني"
],
"TMM": [
"TMM",
"مانات تركمنستاني"
],
"TMT": [
"TMT",
"مانات تركمانستان"
],
"TND": [
"د.ت.",
"دينارتونسي"
],
"TOP": [
"TOP",
"بانغا تونغا"
],
"TPE": [
"TPE",
"اسكود تيموري"
],
"TRL": [
"TRL",
"ليرة تركي"
],
"TRY": [
"ل.ت.",
"ليرة تركية"
],
"TTD": [
"TTD",
"دولار ترينداد وتوباجو"
],
"TWD": [
"NT$",
"دولار تايواني"
],
"TZS": [
"TZS",
"شلن تنزاني"
],
"UAH": [
"UAH",
"هريفنيا أوكراني"
],
"UGS": [
"UGS",
"شلن أوغندي - 1966-1987"
],
"UGX": [
"UGX",
"شلن أوغندي"
],
"USD": [
"US$",
"دولار أمريكي"
],
"USN": [
"USN",
"دولار أمريكي (اليوم التالي)"
],
"USS": [
"USS",
"دولار أمريكي (نفس اليوم)"
],
"UYP": [
"UYP",
"بيزو أوروجواي - 1975-1993"
],
"UYU": [
"UYU",
"بيزو اوروغواي"
],
"UZS": [
"UZS",
"سوم أوزبكستاني"
],
"VEB": [
"VEB",
"بوليفار فنزويلي - 1871-2008"
],
"VEF": [
"VEF",
"بوليفار فنزويلي"
],
"VND": [
"₫",
"دونج فيتنامي"
],
"VUV": [
"VUV",
"فاتو فانواتو"
],
"WST": [
"WST",
"تالا ساموا"
],
"XAF": [
"FCFA",
"فرنك أفريقي"
],
"XCD": [
"EC$",
"دولار شرق الكاريبي"
],
"XEU": [
"XEU",
"وحدة النقد الأوروبية"
],
"XFO": [
"XFO",
"فرنك فرنسي ذهبي"
],
"XFU": [
"XFU",
"(UIC)فرنك فرنسي"
],
"XOF": [
"CFA",
"فرنك سي إف إيه غرب إفريقيا"
],
"XPF": [
"CFPF",
"فرنك سي إف بي"
],
"YDD": [
"YDD",
"دينار يمني"
],
"YER": [
"ر.ي.",
"ريال يمني"
],
"YUD": [
"YUD",
"دينار يوغسلافي"
],
"YUN": [
"YUN",
"دينار يوغسلافي قابل للتحويل"
],
"ZAL": [
"ZAL",
"راند جنوب أفريقيا -مالي"
],
"ZAR": [
"ZAR",
"راند جنوب أفريقيا"
],
"ZMK": [
"ZMK",
"كواشا زامبي - 1968-2012"
],
"ZMW": [
"ZMW",
"كواشا زامبي"
],
"ZRN": [
"ZRN",
"زائير زائيري جديد"
],
"ZRZ": [
"ZRZ",
"زائير زائيري"
],
"ZWD": [
"ZWD",
"دولار زمبابوي"
],
"ZWL": [
"ZWL",
"دولار زمبابوي 2009"
]
}
}

View File

@ -0,0 +1,9 @@
{
"Version": "2.1.6.69",
"Names": {
"DJF": [
"Fdj",
"فرنك جيبوتي"
]
}
}

View File

@ -0,0 +1,9 @@
{
"Version": "2.1.6.69",
"Names": {
"ERN": [
"Nfk",
"ناكفا أريتري"
]
}
}

View File

@ -0,0 +1,9 @@
{
"Version": "2.1.8.19",
"Names": {
"SDG": [
"SDG",
"جنيه سوداني"
]
}
}

View File

@ -0,0 +1,9 @@
{
"Version": "2.1.6.69",
"Names": {
"SOS": [
"S",
"شلن صومالي"
]
}
}

View File

@ -0,0 +1,13 @@
{
"Version": "2.1.6.69",
"Names": {
"GBP": [
"GB£",
"جنيه إسترليني"
],
"SSP": [
"£",
"جنيه جنوب السودان"
]
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More