+ * @version $Revision: 1.66 $ $Date: ${DATE} ${TIME} $
+ * @package System.I18N
+ * @since 3.0
+ */
+class TGlobalization extends TModule
+{
+ /**
+ * Default character set is 'UTF-8'.
+ * @var string
+ */
+ private $_defaultCharset = 'UTF-8';
+
+ /**
+ * Default culture is 'en'.
+ * @var string
+ */
+ private $_defaultCulture = 'en';
+
+ /**
+ * Default content type is 'text/html'
+ * @var ${type}
+ */
+ private $_defaultContentType = 'text/html';
+
+ /**
+ * Translation source parameters.
+ * @var TMap
+ */
+ private $_translation;
+
+ /**
+ * The current charset.
+ * @var string
+ */
+ public $Charset='UTF-8';
+
+ /**
+ * The current culture.
+ * @var string
+ */
+ public $Culture='en';
+
+ /**
+ * The content type for the http header
+ * @var string
+ */
+ public $ContentType='text/html';
+
+ /**
+ * Initialize the Culture and Charset for this application.
+ * You should override this method if you want a different way of
+ * setting the Culture and/or Charset for your application.
+ * If you override this method, call parent::init($xml) first.
+ * @param TXmlElement application configuration
+ */
+ public function init($xml)
+ {
+ $this->Culture = str_replace('-','_',$this->Culture);
+ $this->_defaultContentType = $this->ContentType;
+ $this->_defaultCharset = $this->Charset;
+ $this->_defaultCulture = $this->Culture;
+
+ $config = $xml->getElementByTagName('translation')->getAttributes();
+ $this->setTranslationConfiguration($config);
+ $this->getApplication()->setGlobalization($this);
+ }
+
+ /**
+ * @return TMap translation source configuration.
+ */
+ public function getTranslationConfiguration()
+ {
+ return $this->_translation;
+ }
+
+ /**
+ * Sets the translation configuration. Example configuration:
+ *
+ * $config['type'] = 'XLIFF'; //XLIFF, gettext, mysql or sqlite
+ * $config['source'] = 'Path.to.directory'; //or database connection string
+ * $config['catalogue'] = 'messages'; //default catalog
+ * $config['autosave'] = 'true'; //save untranslated message
+ * $config['cache'] = 'true'; //cache translated message
+ *
+ * Throws exception is source is not found.
+ * @param TMap configuration options
+ * @return ${return}
+ */
+ protected function setTranslationConfiguration(TMap $config)
+ {
+ if($config['type'] == 'XLIFF' || $config['type'] == 'gettext')
+ {
+ $config['source'] = Prado::getPathOfNamespace($config['source']);
+ if(!is_dir($config['source']))
+ throw new TException("invalid source dir '{$config['source']}'");
+ }
+ if($config['cache'])
+ $config['cache'] = $this->getApplication()->getRunTimePath().'/i18n';
+ $this->_translation = $config;
+ }
+
+ /**
+ * @return string default charset set in application.xml
+ */
+ public function getDefaultCharset()
+ {
+ return $this->_defaultCharset;
+ }
+
+ /**
+ * @return string default culture set in application.xml
+ */
+ public function getDefaultCulture()
+ {
+ return $this->_defaultCulture;
+ }
+
+ /**
+ * @return string default content-type set in application.xml
+ */
+ public function getDefaultContentType()
+ {
+ return $this->_defaultContentType;
+ }
+
+ /**
+ * Gets all the variants of a specific culture. If the parameter
+ * $culture is null, the current culture is used.
+ * @param string $culture the Culture string
+ * @return array variants of the culture.
+ */
+ public function getCultureVariants($culture=null)
+ {
+ if(is_null($culture)) $culture = $this->Culture;
+ $variants = explode('_', $culture);
+ $result = array();
+ for(; count($variants) > 0; array_pop($variants))
+ $result[] = implode('_', $variants);
+ return $result;
+ }
+
+ /**
+ * Returns a list of possible localized files. Example
+ *
+ * $files = $app->getLocalizedResource("path/to/Home.page","en_US");
+ *
+ * will return
+ *
+ * array
+ * 0 => 'path/to/en_US/Home.page'
+ * 1 => 'path/to/en/Home.page'
+ * 2 => 'path/to/Home.en_US.page'
+ * 3 => 'path/to/Home.en.page'
+ * 4 => 'path/to/Home.page'
+ *
+ * Note that you still need to verify the existance of these files.
+ * @param string filename
+ * @param string culture string, null to use current culture
+ * @return array list of possible localized resource files.
+ */
+ public function getLocalizedResource($file,$culture=null)
+ {
+ $files = array();
+ $variants = $this->getCultureVariants($culture);
+ $path = pathinfo($file);
+ foreach($variants as $variant)
+ $files[] = $path['dirname'].'/'.$variant.'/'.$path['basename'];
+ $filename = substr($path['basename'],0,strrpos($path['basename'],'.'));
+ foreach($variants as $variant)
+ $files[] = $path['dirname'].'/'.$filename.'.'.$variant.'.'.$path['extension'];
+ $files[] = $file;
+ return $files;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/TGlobalizationAutoDetect.php b/framework/I18N/TGlobalizationAutoDetect.php
new file mode 100644
index 00000000..6cf17bcb
--- /dev/null
+++ b/framework/I18N/TGlobalizationAutoDetect.php
@@ -0,0 +1,28 @@
+
+ * @version $Revision: 1.66 $ $Date: ${DATE} ${TIME} $
+ * @package ${package}
+ */
+class TGlobalizationAutoDetect extends TGlobalization
+{
+ public function init($xml)
+ {
+ parent::init($xml);
+
+ //set the culture according to browser language settings
+ $http = new HTTPNegotiator();
+ $languages = $http->getLanguages();
+ if(count($languages) > 0)
+ $this->Culture = $languages[0];
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/TI18NControl.php b/framework/I18N/TI18NControl.php
new file mode 100644
index 00000000..01df1332
--- /dev/null
+++ b/framework/I18N/TI18NControl.php
@@ -0,0 +1,94 @@
+
+ * @version $Revision: 1.1 $ $Date: 2005/08/27 03:21:12 $
+ * @package System.I18N
+ */
+
+
+/**
+ * Base class for I18N components, providing Culture and Charset properties.
+ * Namespace: System.I18N
+ *
+ * Properties
+ * - Culture, string,
+ *
Gets or sets the culture for formatting. If the Culture property
+ * is not specified. The culture from the Application/Page is used.
+ * - Charset, string,
+ *
Gets or sets the charset for both input and output.
+ * If the Charset property is not specified. The charset from the
+ * Application/Page is used. The default is UTF-8.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Sat Dec 11 15:25:11 EST 2004
+ * @package System.I18N
+ */
+class TI18NControl extends TControl
+{
+
+ /**
+ * Sets the charset for message output
+ * @param string the charset, e.g. UTF-8
+ */
+ public function setCharset($value)
+ {
+ $this->setViewState('Charset',$value,'');
+ }
+
+
+ /**
+ * Get the specific culture for this control.
+ * @param parameter
+ * @return string culture identifier.
+ */
+ public function getCulture()
+ {
+ return $this->getViewState('Culture','');
+ }
+
+ /**
+ * Get the custom culture identifier.
+ * @param string culture identifier.
+ */
+ public function setCulture($culture)
+ {
+ $this->setViewState('Culture',$culture,'');
+ }
+
+ /**
+ * Gets the charset, with fall back to the application charset,
+ * then the default charset in globalization, and finally UTF-8
+ * @return string charset
+ */
+ public function getCharset()
+ {
+ $app = $this->Application->getGlobalization();
+
+ //instance charset
+ $charset = $this->getViewState('Charset','');
+
+ //fall back to globalization charset
+ if(empty($charset))
+ $charset = is_null($app) ? '' : $app->Charset;
+
+ //fall back to default charset
+ if(empty($charset))
+ $charset = (is_null($app)) ? 'UTF-8' : $app->getDefaultCharset();
+
+ return $charset;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/TNumberFormat.php b/framework/I18N/TNumberFormat.php
new file mode 100644
index 00000000..712f548b
--- /dev/null
+++ b/framework/I18N/TNumberFormat.php
@@ -0,0 +1,209 @@
+
+ * @version $Revision: 1.7 $ $Date: 2005/12/15 07:14:49 $
+ * @package System.I18N
+ */
+
+ /**
+ * Get the NumberFormat class.
+ */
+Prado::using('System.I18N.core.NumberFormat');
+
+
+/**
+ * To format numbers in locale sensitive manner use
+ *
+ *
+ *
+ *
+ * Numbers can be formatted as currency, percentage, decimal or scientific
+ * numbers by specifying the Type attribute. The known types are
+ * "currency", "percentage", "decimal" and "scientific".
+ *
+ * If someone from US want to see sales figures from a store in
+ * Germany (say using the EURO currency), formatted using the german
+ * currency, you would need to use the attribute Culture="de_DE" to get
+ * the currency right, e.g. 100,00 â‚?. The decimal and grouping separator is
+ * then also from the de_DE locale. This may lead to some confusion because
+ * people from US know the "," as thousand separator. Therefore a "Currency"
+ * attribute is available, so that the output from the following example
+ * results in â‚?100.00
+ *
+ *
+ *
+ *
+ * Namespace: System.I18N
+ *
+ * Properties
+ * - Value, number,
+ *
Gets or sets the number to format. The tag content is used as Value
+ * if the Value property is not specified.
+ * - Type, string,
+ *
Gets or sets the formatting type. The valid types are
+ * 'decimal', 'currency', 'percentage' and 'scientific'.
+ * - Currency, string,
+ *
Gets or sets the currency symbol for the currency format.
+ * The default is 'USD' if the Currency property is not specified.
+ * - Pattern, string,
+ *
Gets or sets the custom number formatting pattern.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Sat Dec 11 17:49:56 EST 2004
+ * @package System.I18N
+ */
+class TNumberFormat extends TI18NControl
+{
+ /**
+ * Default NumberFormat, set to the application culture.
+ * @var NumberFormat
+ */
+ protected static $formatter;
+
+ /**
+ * Get the number formatting pattern.
+ * @return string format pattern.
+ */
+ function getPattern()
+ {
+ return $this->getViewState('Pattern','');
+ }
+
+ /**
+ * Set the number format pattern.
+ * @param string format pattern.
+ */
+ function setPattern($pattern)
+ {
+ $this->setViewState('Pattern',$pattern,'');
+ }
+
+ /**
+ * Get the numberic value for this control.
+ * @return string number
+ */
+ function getValue()
+ {
+ return $this->getViewState('Value','');
+ }
+
+ /**
+ * Set the numberic value for this control.
+ * @param string the number value
+ */
+ function setValue($value)
+ {
+ $this->setViewState('Value',$value,'');
+ }
+
+ /**
+ * Get the formatting type for this control.
+ * @return string formatting type.
+ */
+ function getType()
+ {
+ $type = $this->getViewState('Type','');
+ if(empty($type))
+ return 'd';
+ return $type;
+ }
+
+ /**
+ * Set the formatting type for this control.
+ * @param string formatting type, either "decimal", "currency","percentage"
+ * or "scientific"
+ * @throws TPropertyTypeInvalidException
+ */
+ function setType($type)
+ {
+ $type = strtolower($type);
+
+ switch($type)
+ {
+ case 'decimal':
+ $this->setViewState('Type','d',''); break;
+ case 'currency':
+ $this->setViewState('Type','c',''); break;
+ case 'percentage':
+ $this->setViewState('Type','p',''); break;
+ case 'scientific':
+ $this->setViewState('Type','e',''); break;
+ default:
+ throw new TPropertyTypeInvalidException($this,'Type',$type);
+ }
+
+ }
+
+ /**
+ * Get the currency for this control.
+ * @param parameter
+ * @return string 3 letter currency code.
+ */
+ function getCurrency()
+ {
+ $currency = $this->getViewState('Currency','');
+ if(empty($currency))
+ return 'USD';
+ return $currency;
+ }
+
+ /**
+ * Set the 3-letter ISO 4217 code. For example, the code
+ * "USD" represents the US Dollar and "EUR" represents the Euro currency.
+ * @param string currency code.
+ */
+ function setCurrency($currency)
+ {
+ $this->setViewState('Currency', $currency,'');
+ }
+
+ /**
+ * Formats the localized number, be it currency or decimal, or percentage.
+ * If the culture is not specified, the default application
+ * culture will be used.
+ * @return string formatted number
+ */
+ protected function getFormattedValue()
+ {
+ $app = $this->Application->getGlobalization();
+ //initialized the default class wide formatter
+ if(is_null(self::$formatter))
+ self::$formatter = new NumberFormat($app->Culture);
+
+ $pattern = strlen($this->getPattern()) > 0
+ ? $this->getPattern() : $this->getType();
+
+ $culture = $this->getCulture();
+ //return the specific cultural formatted number
+ if(!empty($culture) && $app->Culture != $culture)
+ {
+ $formatter = new NumberFormat($culture);
+ return $formatter->format($this->getValue(),$pattern,
+ $this->getCurrency(),
+ $this->getCharset());
+ }
+
+ //return the application wide culture formatted number.
+ return self::$formatter->format($this->getValue(),$pattern,
+ $this->getCurrency(),
+ $this->getCharset());
+ }
+
+ protected function render($writer)
+ {
+ $writer->write($this->getFormattedValue());
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/TTranslate.php b/framework/I18N/TTranslate.php
new file mode 100644
index 00000000..ac708191
--- /dev/null
+++ b/framework/I18N/TTranslate.php
@@ -0,0 +1,196 @@
+
+ * @version $Revision: 1.11 $ $Date: 2005/10/09 10:24:12 $
+ * @package System.I18N
+ */
+
+ Prado::using('System.IO.TTextWriter');
+
+/**
+ * TTranslate class.
+ *
+ * This component performs message/string translation. The translation
+ * source is set in the TGlobalization handler. The following example
+ * demonstrated a simple message translation.
+ *
+ *
+ *
+ *
+ * Depending on the culture set on the page, the phrase "Goodbye" will
+ * be translated.
+ *
+ * The values of any attribute in TTranslate are consider as values for
+ * substitution. Strings enclosed with "{" and "}" are consider as the
+ * parameters. The following example will substitution the string
+ * "{time}" with the value of the attribute "time="#time()". Note that
+ * the value of the attribute time is evaluated.
+ *
+ *
+ * The unix-time is "{time}".
+ *
+ *
+ *
+ * More complex string substitution can be applied using the
+ * TParam component.
+ *
+ * Namespace: System.I18N
+ *
+ * Properties
+ * - Text, string,
+ *
Gets or sets the string to translate.
+ * - Catalogue, string,
+ *
Gets or sets the catalogue for message translation. The
+ * default catalogue can be set by the @Page directive.
+ * - Key, string,
+ *
Gets or sets the key used to message look up.
+ * - Trim, boolean,
+ *
Gets or sets an option to trim the contents.
+ * Default is to trim the contents.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 21:38:49 EST 2004
+ * @package System.I18N
+ */
+class TTranslate extends TI18NControl
+{
+ /**
+ * @return string the text to be localized/translated.
+ */
+ function getText()
+ {
+ return $this->getViewState('Text','');
+ }
+
+ /**
+ * Sets the text for localization.
+ * @param string the text for translation.
+ */
+ function setText($value)
+ {
+ $this->setViewState('Text',$value,'');
+ }
+
+ /**
+ * Set the key for message lookup.
+ * @param string key
+ */
+ function setKey($value)
+ {
+ $this->setViewState('Key',$value,'');
+ }
+
+ /**
+ * Get the key for message lookup.
+ * @return string key
+ */
+ function getKey()
+ {
+ return $this->getViewState('Key','');
+ }
+
+ /**
+ * Get the message catalogue.
+ * @return string catalogue.
+ */
+ function getCatalogue()
+ {
+ return $this->getViewState('Catalogue','');
+ }
+
+ /**
+ * Set the message catalogue.
+ * @param string catalogue.
+ */
+ function setCatalogue($value)
+ {
+ $this->setViewState('Catalogue',$value,'');
+ }
+
+ /**
+ * Set the option to trim the contents.
+ * @param boolean trim or not.
+ */
+ function setTrim($value)
+ {
+ $this->setViewState('Trim',TPropertyValue::ensureBoolean($value),true);
+ }
+
+ /**
+ * Trim the content or not.
+ * @return boolean trim or not.
+ */
+ function getTrim()
+ {
+ return $this->getViewState('Trim',true);
+ }
+
+ /**
+ * renders the translated string.
+ */
+ protected function render($writer)
+ {
+ $textWriter=new TTextWriter;
+ $htmlWriter=new THtmlWriter($textWriter);
+ $subs = array();
+ foreach($this->getControls() as $control)
+ {
+ if($control instanceof TTranslateParameter)
+ $subs['{'.$control->getKey().'}'] = $control->getParameter();
+ elseif($control instanceof TControl)
+ $control->render($htmlWriter);
+ elseif(is_string($control))
+ $textWriter->write($control);
+ }
+
+ $text = $this->getText();
+ if(strlen($text)==0)
+ $text = $textWriter->flush();
+ if($this->getTrim())
+ $text = trim($text);
+
+ $writer->write($this->translateText($text, $subs));
+ }
+
+ /**
+ * Translates the text with subsititution.
+ * @param string text for translation
+ * @param array list of substitutions
+ * @return string translated text
+ */
+ protected function translateText($text, $subs)
+ {
+ $app = $this->Application->getGlobalization();
+
+ //no translation handler provided
+ if(is_null($config = $app->getTranslationConfiguration()))
+ return strtr($text, $subs);
+
+ Translation::init();
+
+ $catalogue = $this->getCatalogue();
+ if(empty($catalogue) && isset($config['catalogue']))
+ $catalogue = $config['catalogue'];
+
+ $key = $this->getKey();
+ if(!empty($key)) $text = $key;
+
+ //translate it
+ return Translation::formatter()->format($text,
+ $subs, $catalogue, $this->getCharset());
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/TTranslateParameter.php b/framework/I18N/TTranslateParameter.php
new file mode 100644
index 00000000..f162d642
--- /dev/null
+++ b/framework/I18N/TTranslateParameter.php
@@ -0,0 +1,113 @@
+
+ * @version $Revision: 1.2 $ $Date: 2005/01/05 03:15:13 $
+ * @package System.I18N
+ */
+
+/**
+ * TTranslateParameter component should be used inside the TTranslate component to
+ * allow parameter substitution.
+ *
+ * For example, the strings "{greeting}" and "{name}" will be replace
+ * with the values of "Hello" and "World", respectively.
+ * The substitution string must be enclose with "{" and "}".
+ * The parameters can be further translated by using TTranslate.
+ *
+ *
+ * {greeting} {name}!
+ * World
+ * Hello
+ *
+ *
+ *
+ * Namespace: System.I18N
+ *
+ * Properties
+ * - Key, string, required.
+ *
Gets or sets the string in TTranslate to substitute.
+ * - Trim, boolean,
+ *
Gets or sets an option to trim the contents of the TParam.
+ * Default is to trim the contents.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v3.0, last update on Friday, 6 January 2006
+ * @package System.I18N
+ */
+class TTranslateParameter extends TControl
+{
+ /**
+ * The substitution key.
+ * @var string
+ */
+ protected $key;
+
+ /**
+ * To trim or not to trim the contents.
+ * @var boolean
+ */
+ protected $trim = true;
+
+ /**
+ * Get the parameter substitution key.
+ * @return string substitution key.
+ */
+ public function getKey()
+ {
+ if(empty($this->key))
+ throw new TException('The Key property must be specified.');
+ return $this->key;
+ }
+
+ /**
+ * Set the parameter substitution key.
+ * @param string substitution key.
+ */
+ public function setKey($value)
+ {
+ $this->key = $value;
+ }
+
+ /**
+ * Set the option to trim the contents.
+ * @param boolean trim or not.
+ */
+ public function setTrim($value)
+ {
+ $this->trim = TPropertyValue::ensureBoolean($value);
+ }
+
+ /**
+ * Trim the content or not.
+ * @return boolean trim or not.
+ */
+ public function getTrim()
+ {
+ return $this->trim;
+ }
+
+ /**
+ * @return string parameter contents.
+ */
+ public function getParameter()
+ {
+ $textWriter = new TTextWriter;
+ $this->renderControl(new THtmlWriter($textWriter));
+ return $this->getTrim() ?
+ trim($textWriter->flush()) : $textWriter->flush();
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/Translation.php b/framework/I18N/Translation.php
new file mode 100644
index 00000000..8b420bbf
--- /dev/null
+++ b/framework/I18N/Translation.php
@@ -0,0 +1,144 @@
+
+ * @version $Revision: 1.9 $ $Date: 2005/12/17 06:11:28 $
+ * @package System.I18N
+ */
+
+ /**
+ * Get the MessageFormat class.
+ */
+Prado::using('System.I18N.core.MessageFormat');
+
+
+/**
+ * Translation class.
+ *
+ * Provides translation using a static MessageFormatter.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Tue Dec 28 11:54:48 EST 2004
+ * @package System.I18N
+ */
+class Translation extends TComponent
+{
+
+
+ /**
+ * The string formatter. This is a class static variable.
+ * @var MessageFormat
+ */
+ protected static $formatter;
+
+ /**
+ * Initialize the TTranslate translation components
+ */
+ public static function init()
+ {
+ //initialized the default class wide formatter
+ if(is_null(self::$formatter))
+ {
+ $app = Prado::getApplication()->getGlobalization();
+ $config = $app->getTranslationConfiguration();
+ $source = MessageSource::factory($config['type'],
+ $config['source'],
+ $config['filename']);
+
+ $source->setCulture($app->Culture);
+
+ if($config['cache'])
+ $source->setCache(new MessageCache($config['cache']));
+
+ self::$formatter = new MessageFormat($source, $app->Charset);
+
+ //save the message on end request
+ Prado::getApplication()->attachEventHandler(
+ 'EndRequest', array('Translation', 'saveMessages'));
+ }
+ }
+
+ /**
+ * Get the static formatter from this component.
+ * @return MessageFormat formattter.
+ * @see localize()
+ */
+ public static function formatter()
+ {
+ return self::$formatter;
+ }
+
+ /**
+ * Save untranslated messages to the catalogue.
+ */
+ public static function saveMessages()
+ {
+ static $onceonly = true;
+
+ if($onceonly && !is_null($formatter = self::$formatter))
+ {
+ $app = Prado::getApplication()->getGlobalization();
+ $config = $app->getTranslationConfiguration();
+ if(isset($config['autosave']))
+ {
+ $formatter->getSource()->setCulture($app->Culture);
+ $formatter->getSource()->save($config['catalogue']);
+ }
+ $onceonly = false;
+ }
+ }
+}
+
+/**
+ * Localize a text to the locale/culture specified in the globalization handler.
+ * @param string text to be localized.
+ * @param array a set of parameters to substitute.
+ * @param string a different catalogue to find the localize text.
+ * @param string the input AND output charset.
+ * @return string localized text.
+ * @see TTranslate::formatter()
+ * @see TTranslate::init()
+ */
+function localize($text, $parameters=array(), $catalogue=null, $charset=null)
+{
+
+ $app = Prado::getApplication()->getGlobalization();
+
+ $params = array();
+ foreach($parameters as $key => $value)
+ $params['{'.$key.'}'] = $value;
+
+ //no translation handler provided
+ if(is_null($config = $app->getTranslationConfiguration()))
+ return strtr($text, $params);
+
+ Translation::init();
+
+ if(empty($catalogue) && isset($config['catalogue']))
+ $catalogue = $config['catalogue'];
+
+ //globalization charset
+ $appCharset = is_null($app) ? '' : $app->Charset;
+
+ //default charset
+ $defaultCharset = (is_null($app)) ? 'UTF-8' : $app->getDefaultCharset();
+
+ //fall back
+ if(empty($charset)) $charset = $appCharset;
+ if(empty($charset)) $charset = $defaultCharset;
+
+ return Translation::formatter()->format($text,$params,$catalogue,$charset);
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/ChoiceFormat.php b/framework/I18N/core/ChoiceFormat.php
new file mode 100644
index 00000000..29391135
--- /dev/null
+++ b/framework/I18N/core/ChoiceFormat.php
@@ -0,0 +1,186 @@
+
+ * @version $Revision: 1.1 $ $Date: 2005/01/11 07:19:39 $
+ * @package System.I18N.core
+ */
+
+
+/**
+ * ChoiceFormat class.
+ *
+ * ChoiceFormat converts between ranges of numeric values and string
+ * names for those ranges.
+ *
+ * A ChoiceFormat splits the real number line -Inf to +Inf into two or
+ * more contiguous ranges. Each range is mapped to a string.
+ * ChoiceFormat is generally used in a MessageFormat for displaying
+ * grammatically correct plurals such as "There are 2 files."
+ *
+ *
+ * $string = '[0] are no files |[1] is one file |(1,Inf] are {number} files';
+ *
+ * $formatter = new MessageFormat(...); //init for a source
+ * $translated = $formatter->format($string);
+ *
+ * $choice = new ChoiceFormat();
+ * echo $choice->format($translated, 0); //shows "are no files"
+ *
+ *
+ * The message/string choices are separated by the pipe "|" followed
+ * by a set notation of the form
+ * # [1,2] -- accepts values between 1 and 2, inclusive.
+ * # (1,2) -- accepts values between 1 and 2, excluding 1 and 2.
+ * # {1,2,3,4} -- only values defined in the set are accepted.
+ * # [-Inf,0) -- accepts value greater or equal to negative infinity
+ * and strictly less than 0
+ * Any non-empty combinations of the delimiters of square and round brackets
+ * are acceptable.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 20:46:16 EST 2004
+ * @package System.I18N.core
+ */
+class ChoiceFormat
+{
+ /**
+ * The pattern to validate a set notation
+ * @var string
+ */
+ protected $validate = '/[\(\[\{]|[-Inf\d]+|,|[\+Inf\d]+|[\)\]\}]/ms';
+
+ /**
+ * The pattern to parse the formatting string.
+ * @var string
+ */
+ protected $parse = '/\s?\|?([\(\[\{]([-Inf\d]+,?[\+Inf\d]*)+[\)\]\}])\s?/';
+
+ /**
+ * The value for positive infinity.
+ * @var float
+ */
+ protected $inf;
+
+
+ /**
+ * Constructor.
+ */
+ function __construct()
+ {
+ $this->inf = -log(0);
+ }
+
+
+ /**
+ * Determine if the given number belongs to a given set
+ * @param float the number to test.
+ * @param string the set, in set notation.
+ * @return boolean true if number is in the set, false otherwise.
+ */
+ function isValid($number, $set)
+ {
+ $n = preg_match_all($this->validate,$set,$matches,PREG_SET_ORDER);
+
+ if($n < 3) throw new Exception("Invalid set \"{$set}\"");
+
+ $leftBracket = $matches[0][0];
+ $rightBracket = $matches[$n-1][0];
+
+ $i = 0;
+ $elements = array();
+
+ foreach($matches as $match)
+ {
+ $string = $match[0];
+ if($i != 0 && $i != $n-1 && $string !== ',')
+ {
+ if($string == '-Inf')
+ $elements[] = -1*$this->inf;
+ else if ($string == '+Inf' || $string == 'Inf')
+ $elements[] = $this->inf;
+ else
+ $elements[] = floatval($string);
+ }
+ $i++;
+ }
+ $total = count($elements);
+ $number = floatval($number);
+
+ if($leftBracket == '{' && $rightBracket == '}')
+ return in_array($number, $elements);
+
+ $left = false;
+ if($leftBracket == '[')
+ $left = $number >= $elements[0];
+ else if ($leftBracket == '(')
+ $left = $number > $elements[0];
+
+ $right = false;
+ if($rightBracket==']')
+ $right = $number <= $elements[$total-1];
+ else if($rightBracket == ')')
+ $right = $number < $elements[$total-1];
+
+ if($left && $right) return true;
+
+ return false;
+ }
+
+
+ /**
+ * Parse a choice string and get a list of sets and a list of strings
+ * corresponding to the sets.
+ * @param string the string containing the choices
+ * @return array array($sets, $strings)
+ */
+ function parse($string)
+ {
+ $n = preg_match_all($this->parse,$string,$matches, PREG_OFFSET_CAPTURE);
+ $sets = array();
+ foreach($matches[1] as $match)
+ $sets[] = $match[0];
+ $offset = $matches[0];
+ $strings = array();
+ for($i = 0; $i < $n; $i++)
+ {
+ $len = strlen($offset[$i][0]);
+ $begin = $i == 0? $len : $offset[$i][1] + $len;
+ $end = $i == $n-1 ? strlen($string) : $offset[$i+1][1];
+ $strings[] = substr($string, $begin, $end - $begin);
+ }
+ return array($sets, $strings);
+ }
+
+ /**
+ * For the choice string, and a number, find and return the
+ * string that satisfied the set within the choices.
+ * @param string the choices string.
+ * @param float the number to test.
+ * @return string the choosen string.
+ */
+ public function format($string, $number)
+ {
+ list($sets, $strings) = $this->parse($string);
+ $total = count($sets);
+ for($i = 0; $i < $total; $i++)
+ {
+ if($this->isValid($number, $sets[$i]))
+ return $strings[$i];
+ }
+ return false;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/CultureInfo.php b/framework/I18N/core/CultureInfo.php
new file mode 100644
index 00000000..b03f794f
--- /dev/null
+++ b/framework/I18N/core/CultureInfo.php
@@ -0,0 +1,618 @@
+
+ * @version $Revision: 1.6 $ $Date: 2005/12/16 05:26:17 $
+ * @package System.I18N.core
+ */
+
+/**
+ * CultureInfo class.
+ *
+ * Represents information about a specific culture including the
+ * names of the culture, the calendar used, as well as access to
+ * culture-specific objects that provide methods for common operations,
+ * such as formatting dates, numbers, and currency.
+ *
+ * The CultureInfo class holds culture-specific information, such as the
+ * associated language, sublanguage, country/region, calendar, and cultural
+ * conventions. This class also provides access to culture-specific
+ * instances of DateTimeFormatInfo and NumberFormatInfo. These objects
+ * contain the information required for culture-specific operations,
+ * such as formatting dates, numbers and currency.
+ *
+ * The culture names follow the format "_",
+ * where is a lowercase two-letter code derived from ISO 639
+ * codes. You can find a full list of the ISO-639 codes at
+ * http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt
+ *
+ * The is an uppercase two-letter code derived from
+ * ISO 3166. A copy of ISO-3166 can be found at
+ * http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
+ *
+ * For example, Australian English is "en_AU".
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Sat Dec 04 13:41:46 EST 2004
+ * @package System.I18N.core
+ */
+class CultureInfo
+{
+ /**
+ * ICU data filename extension.
+ * @var string
+ */
+ private $dataFileExt = '.dat';
+
+ /**
+ * The ICU data array.
+ * @var array
+ */
+ private $data = array();
+
+ /**
+ * The current culture.
+ * @var string
+ */
+ private $culture;
+
+ /**
+ * Directory where the ICU data is stored.
+ * @var string
+ */
+ private $dataDir;
+
+ /**
+ * A list of ICU date files loaded.
+ * @var array
+ */
+ private $dataFiles = array();
+
+ /**
+ * The current date time format info.
+ * @var DateTimeFormatInfo
+ */
+ private $dateTimeFormat;
+
+ /**
+ * The current number format info.
+ * @var NumberFormatInfo
+ */
+ private $numberFormat;
+
+ /**
+ * A list of properties that are accessable/writable.
+ * @var array
+ */
+ protected $properties = array();
+
+ /**
+ * Culture type, all.
+ * @see getCultures()
+ * @var int
+ */
+ const ALL = 0;
+
+ /**
+ * Culture type, neutral.
+ * @see getCultures()
+ * @var int
+ */
+ const NEUTRAL = 1;
+
+ /**
+ * Culture type, specific.
+ * @see getCultures()
+ * @var int
+ */
+ const SPECIFIC = 2;
+
+ /**
+ * Display the culture name.
+ * @return string the culture name.
+ * @see getName()
+ */
+ function __toString()
+ {
+ return $this->getName();
+ }
+
+
+ /**
+ * Allow functions that begins with 'set' to be called directly
+ * as an attribute/property to retrieve the value.
+ * @return mixed
+ */
+ function __get($name)
+ {
+ $getProperty = 'get'.$name;
+ if(in_array($getProperty, $this->properties))
+ return $this->$getProperty();
+ else
+ throw new Exception('Property '.$name.' does not exists.');
+ }
+
+ /**
+ * Allow functions that begins with 'set' to be called directly
+ * as an attribute/property to set the value.
+ */
+ function __set($name, $value)
+ {
+ $setProperty = 'set'.$name;
+ if(in_array($setProperty, $this->properties))
+ $this->$setProperty($value);
+ else
+ throw new Exception('Property '.$name.' can not be set.');
+ }
+
+
+ /**
+ * Initializes a new instance of the CultureInfo class based on the
+ * culture specified by name. E.g. new CultureInfo('en_AU');
+ * The culture indentifier must be of the form
+ * "_(country/region/variant)".
+ * @param string a culture name, e.g. "en_AU".
+ * @return return new CultureInfo.
+ */
+ function __construct($culture='en')
+ {
+ $this->properties = get_class_methods($this);
+
+ if(empty($culture))
+ $culture = 'en';
+
+ $this->dataDir = $this->dataDir();
+ $this->dataFileExt = $this->fileExt();
+
+ $this->setCulture($culture);
+
+ $this->loadCultureData('root');
+ $this->loadCultureData($culture);
+ }
+
+ /**
+ * Get the default directory for the ICU data.
+ * The default is the "data" directory for this class.
+ * @return string directory containing the ICU data.
+ */
+ protected static function dataDir()
+ {
+ return dirname(__FILE__).'/data/';
+ }
+
+ /**
+ * Get the filename extension for ICU data. Default is ".dat".
+ * @return string filename extension for ICU data.
+ */
+ protected static function fileExt()
+ {
+ return '.dat';
+ }
+
+ /**
+ * Determine if a given culture is valid. Simply checks that the
+ * culture data exists.
+ * @param string a culture
+ * @return boolean true if valid, false otherwise.
+ */
+ public function validCulture($culture)
+ {
+ if(preg_match('/^[a-z]{2}(_[A-Z]{2,5}){0,2}$/', $culture))
+ return is_file(self::dataDir().$culture.self::fileExt());
+
+ return false;
+ }
+
+ /**
+ * Set the culture for the current instance. The culture indentifier
+ * must be of the form "_(country/region)".
+ * @param string culture identifier, e.g. "fr_FR_EURO".
+ */
+ protected function setCulture($culture)
+ {
+ if(!empty($culture))
+ {
+ if (!preg_match('/^[a-z]{2}(_[A-Z]{2,5}){0,2}$/', $culture))
+ throw new Exception('Invalid culture supplied: ' . $culture);
+ }
+
+ $this->culture = $culture;
+ }
+
+ /**
+ * Load the ICU culture data for the specific culture identifier.
+ * @param string the culture identifier.
+ */
+ protected function loadCultureData($culture)
+ {
+ $file_parts = explode('_',$culture);
+ $current_part = $file_parts[0];
+
+ $files = array($current_part);
+
+ for($i = 1; $i < count($file_parts); $i++)
+ {
+ $current_part .= '_'.$file_parts[$i];
+ $files[] = $current_part;
+ }
+
+ foreach($files as $file)
+ {
+ $filename = $this->dataDir.$file.$this->dataFileExt;
+
+ if(is_file($filename) == false)
+ throw new Exception('Data file for "'.$file.'" was not found.');
+
+ if(in_array($filename, $this->dataFiles) == false)
+ {
+ array_unshift($this->dataFiles, $file);
+
+ $data = &$this->getData($filename);
+ $this->data[$file] = &$data;
+
+ if(isset($data['__ALIAS']))
+ $this->loadCultureData($data['__ALIAS'][0]);
+ unset($data);
+ }
+ }
+ }
+
+ /**
+ * Get the data by unserializing the ICU data from disk.
+ * The data files are cached in a static variable inside
+ * this function.
+ * @param string the ICU data filename
+ * @return array ICU data
+ */
+ protected function &getData($filename)
+ {
+ static $data = array();
+ static $files = array();
+
+ if(!in_array($filename, $files))
+ {
+ $data[$filename] = unserialize(file_get_contents($filename));
+ $files[] = $filename;
+ }
+
+ return $data[$filename];
+ }
+
+ /**
+ * Find the specific ICU data information from the data.
+ * The path to the specific ICU data is separated with a slash "/".
+ * E.g. To find the default calendar used by the culture, the path
+ * "calendar/default" will return the corresponding default calendar.
+ * Use merge=true to return the ICU including the parent culture.
+ * E.g. The currency data for a variant, say "en_AU" contains one
+ * entry, the currency for AUD, the other currency data are stored
+ * in the "en" data file. Thus to retrieve all the data regarding
+ * currency for "en_AU", you need to use findInfo("Currencies,true);.
+ * @param string the data you want to find.
+ * @param boolean merge the data from its parents.
+ * @return mixed the specific ICU data.
+ */
+ protected function findInfo($path='/', $merge=false)
+ {
+ $result = array();
+ foreach($this->dataFiles as $section)
+ {
+ $info = $this->searchArray($this->data[$section], $path);
+
+ if($info)
+ {
+ if($merge)
+ $result = array_merge($info,$result);
+ else
+ return $info;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Search the array for a specific value using a path separated using
+ * slash "/" separated path. e.g to find $info['hello']['world'],
+ * the path "hello/world" will return the corresponding value.
+ * @param array the array for search
+ * @param string slash "/" separated array path.
+ * @return mixed the value array using the path
+ */
+ private function searchArray($info, $path='/')
+ {
+ $index = explode('/',$path);
+
+ $array = $info;
+
+ for($i = 0; $i < count($index); $i++)
+ {
+ $k = $index[$i];
+ if($i < count($index)-1 && isset($array[$k]))
+ $array = $array[$k];
+ else if ($i == count($index)-1 && isset($array[$k]))
+ return $array[$k];
+ }
+ }
+
+ /**
+ * Gets the culture name in the format
+ * "_(country/regioncode2)".
+ * @return string culture name.
+ */
+ function getName()
+ {
+ return $this->culture;
+ }
+
+ /**
+ * Gets the DateTimeFormatInfo that defines the culturally appropriate
+ * format of displaying dates and times.
+ * @return DateTimeFormatInfo date time format information for the culture.
+ */
+ function getDateTimeFormat()
+ {
+ if(is_null($this->dateTimeFormat))
+ {
+ $calendar = $this->getCalendar();
+ $info = $this->findInfo("calendar/{$calendar}", true);
+ $this->setDateTimeFormat(new DateTimeFormatInfo($info));
+ }
+
+ return $this->dateTimeFormat;
+ }
+
+ /**
+ * Set the date time format information.
+ * @param DateTimeFormatInfo the new date time format info.
+ */
+ function setDateTimeFormat($dateTimeFormat)
+ {
+ $this->dateTimeFormat = $dateTimeFormat;
+ }
+
+ /**
+ * Gets the default calendar used by the culture, e.g. "gregorian".
+ * @return string the default calendar.
+ */
+ function getCalendar()
+ {
+ $info = $this->findInfo('calendar/default');
+ return $info[0];
+ }
+
+ /**
+ * Gets the culture name in the language that the culture is set
+ * to display. Returns array('Language','Country');
+ * 'Country' is omitted if the culture is neutral.
+ * @return array array with language and country as elements, localized.
+ */
+ function getNativeName()
+ {
+ $lang = substr($this->culture,0,2);
+ $reg = substr($this->culture,3,2);
+ $language = $this->findInfo("Languages/{$lang}");
+ $region = $this->findInfo("Countries/{$reg}");
+ if($region)
+ return $language[0].' ('.$region[0].')';
+ else
+ return $language[0];
+ }
+
+ /**
+ * Gets the culture name in English.
+ * Returns array('Language','Country');
+ * 'Country' is omitted if the culture is neutral.
+ * @return array array with language and country as elements.
+ */
+ function getEnglishName()
+ {
+ $lang = substr($this->culture,0,2);
+ $reg = substr($this->culture,3,2);
+ $culture = $this->getInvariantCulture();
+
+ $language = $culture->findInfo("Languages/{$lang}");
+ $region = $culture->findInfo("Countries/{$reg}");
+ if($region)
+ return $language[0].' ('.$region[0].')';
+ else
+ return $language[0];
+ }
+
+ /**
+ * Gets the CultureInfo that is culture-independent (invariant).
+ * Any changes to the invariant culture affects all other
+ * instances of the invariant culture.
+ * The invariant culture is assumed to be "en";
+ * @return CultureInfo invariant culture info is "en".
+ */
+ static function getInvariantCulture()
+ {
+ static $invariant;
+ if(is_null($invariant))
+ $invariant = new CultureInfo();
+ return $invariant;
+ }
+
+ /**
+ * Gets a value indicating whether the current CultureInfo
+ * represents a neutral culture. Returns true if the culture
+ * only contains two characters.
+ * @return boolean true if culture is neutral, false otherwise.
+ */
+ function getIsNeutralCulture()
+ {
+ return strlen($this->culture) == 2;
+ }
+
+ /**
+ * Gets the NumberFormatInfo that defines the culturally appropriate
+ * format of displaying numbers, currency, and percentage.
+ * @return NumberFormatInfo the number format info for current culture.
+ */
+ function getNumberFormat()
+ {
+ if(is_null($this->numberFormat))
+ {
+ $elements = $this->findInfo('NumberElements');
+ $patterns = $this->findInfo('NumberPatterns');
+ $currencies = $this->getCurrencies();
+ $data = array( 'NumberElements'=>$elements,
+ 'NumberPatterns'=>$patterns,
+ 'Currencies' => $currencies);
+
+ $this->setNumberFormat(new NumberFormatInfo($data));
+ }
+ return $this->numberFormat;
+ }
+
+ /**
+ * Set the number format information.
+ * @param NumberFormatInfo the new number format info.
+ */
+ function setNumberFormat($numberFormat)
+ {
+ $this->numberFormat = $numberFormat;
+ }
+
+ /**
+ * Gets the CultureInfo that represents the parent culture of the
+ * current CultureInfo
+ * @return CultureInfo parent culture information.
+ */
+ function getParent()
+ {
+ if(strlen($this->culture) == 2)
+ return $this->getInvariantCulture();
+
+ $lang = substr($this->culture,0,2);
+ return new CultureInfo($lang);
+ }
+
+ /**
+ * Gets the list of supported cultures filtered by the specified
+ * culture type. This is an EXPENSIVE function, it needs to traverse
+ * a list of ICU files in the data directory.
+ * This function can be called statically.
+ * @param int culture type, CultureInfo::ALL, CultureInfo::NEUTRAL
+ * or CultureInfo::SPECIFIC.
+ * @return array list of culture information available.
+ */
+ static function getCultures($type=CultureInfo::ALL)
+ {
+ $dataDir = CultureInfo::dataDir();
+ $dataExt = CultureInfo::fileExt();
+ $dir = dir($dataDir);
+
+ $neutral = array();
+ $specific = array();
+
+ while (false !== ($entry = $dir->read()))
+ {
+ if(is_file($dataDir.$entry)
+ && substr($entry,-4) == $dataExt
+ && $entry != 'root'.$dataExt)
+ {
+ $culture = substr($entry,0,-4);
+ if(strlen($culture) == 2)
+ $neutral[] = $culture;
+ else
+ $specific[] = $culture;
+ }
+ }
+ $dir->close();
+
+ switch($type)
+ {
+ case CultureInfo::ALL :
+ $all = array_merge($neutral, $specific);
+ sort($all);
+ return $all;
+ break;
+ case CultureInfo::NEUTRAL :
+ return $neutral;
+ break;
+ case CultureInfo::SPECIFIC :
+ return $specific;
+ break;
+ }
+ }
+
+ /**
+ * Simplify a single element array into its own value.
+ * E.g. array(0 => array('hello'), 1 => 'world');
+ * becomes array(0 => 'hello', 1 => 'world');
+ * @param array with single elements arrays
+ * @return array simplified array.
+ */
+ private function simplify($array)
+ {
+ for($i = 0; $isimplify($this->findInfo('Countries',true));
+ }
+
+ /**
+ * Get a list of currencies in the language of the localized version.
+ * @return array a list of localized currencies.
+ */
+ function getCurrencies()
+ {
+ return $this->findInfo('Currencies',true);
+ }
+
+ /**
+ * Get a list of languages in the language of the localized version.
+ * @return array list of localized language names.
+ */
+ function getLanguages()
+ {
+ return $this->simplify($this->findInfo('Languages',true));
+ }
+
+ /**
+ * Get a list of scripts in the language of the localized version.
+ * @return array list of localized script names.
+ */
+ function getScripts()
+ {
+ return $this->simplify($this->findInfo('Scripts',true));
+ }
+
+ /**
+ * Get a list of timezones in the language of the localized version.
+ * @return array list of localized timezones.
+ */
+ function getTimeZones()
+ {
+ return $this->simplify($this->findInfo('zoneStrings',true));
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/DateFormat.php b/framework/I18N/core/DateFormat.php
new file mode 100644
index 00000000..1e340d95
--- /dev/null
+++ b/framework/I18N/core/DateFormat.php
@@ -0,0 +1,645 @@
+
+ * @version $Revision: 1.8 $ $Date: 2005/12/15 07:14:49 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the DateTimeFormatInfo class.
+ */
+require_once(dirname(__FILE__).'/DateTimeFormatInfo.php');
+
+/**
+ * Get the encoding utilities
+ */
+require_once(dirname(__FILE__).'/util.php');
+
+/**
+ * DateFormat class.
+ *
+ * The DateFormat class allows you to format dates and times with
+ * predefined styles in a locale-sensitive manner. Formatting times
+ * with the DateFormat class is similar to formatting dates.
+ *
+ * Formatting dates with the DateFormat class is a two-step process.
+ * First, you create a formatter with the getDateInstance method.
+ * Second, you invoke the format method, which returns a string containing
+ * the formatted date.
+ *
+ * DateTime values are formatted using standard or custom patterns stored
+ * in the properties of a DateTimeFormatInfo.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Sat Dec 04 14:10:49 EST 2004
+ * @package System.I18N.core
+ */
+class DateFormat
+{
+ /**
+ * A list of tokens and their function call.
+ * @var array
+ */
+ protected $tokens = array(
+ 'G'=>'Era',
+ 'y'=>'Year',
+ 'M'=>'Month',
+ 'd'=>'Day',
+ 'h'=>'Hour12',
+ 'H'=>'Hour24',
+ 'm'=>'Minutes',
+ 's'=>'Seconds',
+ 'E'=>'DayInWeek',
+ 'D'=>'DayInYear',
+ 'F'=>'DayInMonth',
+ 'w'=>'WeekInYear',
+ 'W'=>'WeekInMonth',
+ 'a'=>'AMPM',
+ 'k'=>'HourInDay',
+ 'K'=>'HourInAMPM',
+ 'z'=>'TimeZone'
+ );
+
+ /**
+ * A list of methods, to be used by the token function calls.
+ * @var array
+ */
+ protected $methods = array();
+
+ /**
+ * The DateTimeFormatInfo, containing culture specific patterns and names.
+ * @var DateTimeFormatInfo
+ */
+ protected $formatInfo;
+
+ /**
+ * Initialize a new DateFormat.
+ * @param mixed either, null, a CultureInfo instance,
+ * a DateTimeFormatInfo instance, or a locale.
+ * @return DateFormat instance
+ */
+ function __construct($formatInfo=null)
+ {
+ if(is_null($formatInfo))
+ $this->formatInfo = DateTimeFormatInfo::getInvariantInfo();
+ else if($formatInfo instanceof CultureInfo)
+ $this->formatInfo = $formatInfo->DateTimeFormat;
+ else if($formatInfo instanceof DateTimeFormatInfo)
+ $this->formatInfo = $formatInfo;
+ else
+ $this->formatInfo = DateTimeFormatInfo::getInstance($formatInfo);
+
+ $this->methods = get_class_methods($this);
+ }
+
+ /**
+ * Format a date according to the pattern.
+ * @param mixed the time as integer or string in strtotime format.
+ * @return string formatted date time.
+ */
+ public function format($time, $pattern='F', $charset='UTF-8')
+ {
+ if(is_string($time))
+ $time = @strtotime($time);
+
+ if(is_null($pattern))
+ $pattern = 'F';
+
+ $date = @getdate($time);
+
+ $pattern = $this->getPattern($pattern);
+
+ $tokens = $this->getTokens($pattern);
+
+ for($i = 0; $igetFunctionName($pattern);
+ if($function != null)
+ {
+ $fName = 'get'.$function;
+ if(in_array($fName, $this->methods))
+ {
+ $rs = $this->$fName($date, $pattern);
+ $tokens[$i] = $rs;
+ }
+ else
+ throw new
+ Exception('function '.$function.' not found.');
+ }
+ }
+ }
+
+ return I18N_toEncoding(implode('',$tokens), $charset);
+ }
+
+ /**
+ * For a particular token, get the corresponding function to call.
+ * @param string token
+ * @return mixed the function if good token, null otherwise.
+ */
+ protected function getFunctionName($token)
+ {
+ if(isset($this->tokens[$token{0}]))
+ return $this->tokens[$token{0}];
+ }
+
+ /**
+ * Get the pattern from DateTimeFormatInfo or some predefined patterns.
+ * If the $pattern parameter is an array of 2 element, it will assume
+ * that the first element is the date, and second the time
+ * and try to find an appropriate pattern and apply
+ * DateTimeFormatInfo::formatDateTime
+ * See the tutorial documentation for futher details on the patterns.
+ * @param mixed a pattern.
+ * @return string a pattern.
+ * @see DateTimeFormatInfo::formatDateTime()
+ */
+ protected function getPattern($pattern)
+ {
+ if(is_array($pattern) && count($pattern) == 2)
+ {
+ return $this->formatInfo->formatDateTime(
+ $this->getPattern($pattern[0]),
+ $this->getPattern($pattern[1]));
+ }
+
+ switch($pattern)
+ {
+ case 'd':
+ return $this->formatInfo->ShortDatePattern;
+ break;
+ case 'D':
+ return $this->formatInfo->LongDatePattern;
+ break;
+ case 'p':
+ return $this->formatInfo->MediumDatePattern;
+ break;
+ case 'P':
+ return $this->formatInfo->FullDatePattern;
+ break;
+ case 't':
+ return $this->formatInfo->ShortTimePattern;
+ break;
+ case 'T':
+ return $this->formatInfo->LongTimePattern;
+ break;
+ case 'q':
+ return $this->formatInfo->MediumTimePattern;
+ break;
+ case 'Q':
+ return $this->formatInfo->FullTimePattern;
+ break;
+ case 'f':
+ return $this->formatInfo->formatDateTime(
+ $this->formatInfo->LongDatePattern,
+ $this->formatInfo->ShortTimePattern);
+ break;
+ case 'F':
+ return $this->formatInfo->formatDateTime(
+ $this->formatInfo->LongDatePattern,
+ $this->formatInfo->LongTimePattern);
+ break;
+ case 'g':
+ return $this->formatInfo->formatDateTime(
+ $this->formatInfo->ShortDatePattern,
+ $this->formatInfo->ShortTimePattern);
+ break;
+ case 'G':
+ return $this->formatInfo->formatDateTime(
+ $this->formatInfo->ShortDatePattern,
+ $this->formatInfo->LongTimePattern);
+ break;
+ case 'M':
+ case 'm':
+ return 'MMMM dd';
+ break;
+ case 'R':
+ case 'r':
+ return 'EEE, dd MMM yyyy HH:mm:ss';
+ break;
+ case 's':
+ return 'yyyy-MM-ddTHH:mm:ss';
+ break;
+ case 'u':
+ return 'yyyy-MM-dd HH:mm:ss z';
+ break;
+ case 'U':
+ return 'EEEE dd MMMM yyyy HH:mm:ss';
+ break;
+ case 'Y':
+ case 'y':
+ return 'yyyy MMMM';
+ break;
+ default :
+ return $pattern;
+ }
+ }
+
+ /**
+ * Tokenize the pattern. The tokens are delimited by group of
+ * similar characters, e.g. 'aabb' will form 2 tokens of 'aa' and 'bb'.
+ * Any substrings, starting and ending with a single quote (')
+ * will be treated as a single token.
+ * @param string pattern.
+ * @return array string tokens in an array.
+ */
+ protected function getTokens($pattern)
+ {
+ $char = null;
+ $tokens = array();
+ $token = null;
+
+ $text = false;
+
+ for($i = 0; $i < strlen($pattern); $i++)
+ {
+ if($char==null || $pattern{$i} == $char || $text)
+ {
+ $token .= $pattern{$i};
+ }
+ else
+ {
+ $tokens[] = str_replace("''","'",$token);
+ $token = $pattern{$i};
+ }
+
+ if($pattern{$i} == "'" && $text == false)
+ $text = true;
+ else if($text && $pattern{$i} == "'" && $char == "'")
+ $text = true;
+ else if($text && $char != "'" && $pattern{$i} == "'")
+ $text = false;
+
+ $char = $pattern{$i};
+
+ }
+ $tokens[] = $token;
+ return $tokens;
+ }
+
+ /**
+ * Get the year.
+ * "yy" will return the last two digits of year.
+ * "yyyy" will return the full integer year.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string year
+ */
+ protected function getYear($date, $pattern='yyyy')
+ {
+ $year = $date['year'];
+ switch($pattern)
+ {
+ case 'yy':
+ return substr($year,2);
+ case 'yyyy':
+ return $year;
+ default:
+ throw new Exception('The pattern for year is either "yy" or "yyyy".');
+ }
+ }
+
+ /**
+ * Get the month.
+ * "M" will return integer 1 through 12
+ * "MM" will return the narrow month name, e.g. "J"
+ * "MMM" will return the abrreviated month name, e.g. "Jan"
+ * "MMMM" will return the month name, e.g. "January"
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string month name
+ */
+ protected function getMonth($date, $pattern='M')
+ {
+ $month = $date['mon'];
+
+ switch($pattern)
+ {
+ case 'M':
+ return $month;
+ case 'MM':
+ return str_pad($month, 2,'0',STR_PAD_LEFT);
+ case 'MMM':
+ return $this->formatInfo->AbbreviatedMonthNames[$month-1];
+ break;
+ case 'MMMM':
+ return $this->formatInfo->MonthNames[$month-1];
+ default:
+ throw new Exception('The pattern for month '.
+ 'is "M", "MM", "MMM", or "MMMM".');
+ }
+ }
+
+ /**
+ * Get the day of the week.
+ * "E" will return integer 0 (for Sunday) through 6 (for Saturday).
+ * "EE" will return the narrow day of the week, e.g. "M"
+ * "EEE" will return the abrreviated day of the week, e.g. "Mon"
+ * "EEEE" will return the day of the week, e.g. "Monday"
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string day of the week.
+ */
+ protected function getDayInWeek($date, $pattern='EEEE')
+ {
+ $day = $date['wday'];
+
+ switch($pattern)
+ {
+ case 'E':
+ return $day;
+ break;
+ case 'EE':
+ return $this->formatInfo->NarrowDayNames[$day];
+ case 'EEE':
+ return $this->formatInfo->AbbreviatedDayNames[$day];
+ break;
+ case 'EEEE':
+ return $this->formatInfo->DayNames[$day];
+ break;
+ default:
+ throw new Exception('The pattern for day of the week '.
+ 'is "E", "EE", "EEE", or "EEEE".');
+ }
+ }
+
+ /**
+ * Get the day of the month.
+ * "d" for non-padding, "dd" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string day of the month
+ */
+ protected function getDay($date, $pattern='d')
+ {
+ $day = $date['mday'];
+
+ switch($pattern)
+ {
+ case 'd':
+ return $day;
+ case 'dd':
+ return str_pad($day, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for day of '.
+ 'the month is "d" or "dd".');
+ }
+ }
+
+
+ /**
+ * Get the era. i.e. in gregorian, year > 0 is AD, else BC.
+ * @todo How to support multiple Eras?, e.g. Japanese.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string era
+ */
+ protected function getEra($date, $pattern='G')
+ {
+
+ if($pattern != 'G')
+ throw new Exception('The pattern for era is "G".');
+
+ $year = $date['year'];
+ if($year > 0)
+ return $this->formatInfo->getEra(1);
+ else
+ return $this->formatInfo->getEra(0);
+ }
+
+ /**
+ * Get the hours in 24 hour format, i.e. [0-23].
+ * "H" for non-padding, "HH" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string hours in 24 hour format.
+ */
+ protected function getHour24($date, $pattern='H')
+ {
+ $hour = $date['hours'];
+
+ switch($pattern)
+ {
+ case 'H':
+ return $hour;
+ case 'HH':
+ return str_pad($hour, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for 24 hour '.
+ 'format is "H" or "HH".');
+ }
+ }
+
+ /**
+ * Get the AM/PM designator, 12 noon is PM, 12 midnight is AM.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string AM or PM designator
+ */
+ protected function getAMPM($date, $pattern='a')
+ {
+ if($pattern != 'a')
+ throw new Exception('The pattern for AM/PM marker is "a".');
+
+ $hour = $date['hours'];
+ $ampm = intval($hour/12);
+ return $this->formatInfo->AMPMMarkers[$ampm];
+ }
+
+ /**
+ * Get the hours in 12 hour format.
+ * "h" for non-padding, "hh" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string hours in 12 hour format.
+ */
+ protected function getHour12($date, $pattern='h')
+ {
+ $hour = $date['hours'];
+ $hour = ($hour==12|$hour==0)?12:($hour)%12;
+
+ switch($pattern)
+ {
+ case 'h':
+ return $hour;
+ case 'hh':
+ return str_pad($hour, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for 24 hour '.
+ 'format is "H" or "HH".');
+ }
+ }
+
+ /**
+ * Get the minutes.
+ * "m" for non-padding, "mm" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string minutes.
+ */
+ protected function getMinutes($date, $pattern='m')
+ {
+ $minutes = $date['minutes'];
+
+ switch($pattern)
+ {
+ case 'm':
+ return $minutes;
+ case 'mm':
+ return str_pad($minutes, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for minutes is "m" or "mm".');
+ }
+ }
+
+ /**
+ * Get the seconds.
+ * "s" for non-padding, "ss" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string seconds
+ */
+ protected function getSeconds($date, $pattern='s')
+ {
+ $seconds = $date['seconds'];
+
+ switch($pattern)
+ {
+ case 's':
+ return $seconds;
+ case 'ss':
+ return str_pad($seconds, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for seconds is "s" or "ss".');
+ }
+ }
+
+ /**
+ * Get the timezone from the server machine.
+ * @todo How to get the timezone for a different region?
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string time zone
+ */
+ protected function getTimeZone($date, $pattern='z')
+ {
+ if($pattern != 'z')
+ throw new Exception('The pattern for time zone is "z".');
+
+ return @date('T', @mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year']));
+ }
+
+ /**
+ * Get the day in the year, e.g. [1-366]
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int hours in AM/PM format.
+ */
+ protected function getDayInYear($date, $pattern='D')
+ {
+ if($pattern != 'D')
+ throw new Exception('The pattern for day in year is "D".');
+
+ return $date['yday'];
+ }
+
+ /**
+ * Get day in the month.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int day in month
+ */
+ protected function getDayInMonth($date, $pattern='FF')
+ {
+ switch ($pattern) {
+ case 'F':
+ return @date('j', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
+ break;
+ case 'FF':
+ return @date('d', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
+ break;
+ default:
+ throw new Exception('The pattern for day in month is "F" or "FF".');
+ }
+ }
+
+ /**
+ * Get the week in the year.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int week in year
+ */
+ protected function getWeekInYear($date, $pattern='w')
+ {
+ if($pattern != 'w')
+ throw new Exception('The pattern for week in year is "w".');
+
+ return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
+ }
+
+ /**
+ * Get week in the month.
+ * @param array getdate format.
+ * @return int week in month
+ */
+ protected function getWeekInMonth($date, $pattern='W')
+ {
+ if($pattern != 'W')
+ throw new Exception('The pattern for week in month is "W".');
+
+ return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year'])) - date('W', mktime(0, 0, 0, $date['mon'], 1, $date['year']));
+ }
+
+ /**
+ * Get the hours [1-24].
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int hours [1-24]
+ */
+ protected function getHourInDay($date, $pattern='k')
+ {
+ if(is_null($dateTimeInfo))
+ $dateTimeInfo = $this->dateTimeInfo;
+
+ if($pattern != 'k')
+ throw new Exception('The pattern for hour in day is "k".');
+
+ return $date['hours']+1;
+ }
+
+ /**
+ * Get the hours in AM/PM format, e.g [1-12]
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int hours in AM/PM format.
+ */
+ protected function getHourInAMPM($date, $pattern='K')
+ {
+ if($pattern != 'K')
+ throw new Exception('The pattern for hour in AM/PM is "K".');
+
+ return ($date['hours']+1)%12;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/DateTimeFormatInfo.php b/framework/I18N/core/DateTimeFormatInfo.php
new file mode 100644
index 00000000..ba8507ef
--- /dev/null
+++ b/framework/I18N/core/DateTimeFormatInfo.php
@@ -0,0 +1,513 @@
+
+ * @version $Revision: 1.2 $ $Date: 2005/01/05 03:15:14 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the CultureInfo class.
+ */
+require_once(dirname(__FILE__).'/CultureInfo.php');
+
+
+/**
+ * Defines how DateTime values are formatted and displayed, depending
+ * on the culture.
+ *
+ * This class contains information, such as date patterns, time patterns,
+ * and AM/PM designators.
+ *
+ * To create a DateTimeFormatInfo for a specific culture, create a
+ * CultureInfo for that culture and retrieve the CultureInfo.DateTimeFormat
+ * property. For example:
+ *
+ * $culture = new CultureInfo('en_AU');
+ * $dtfi = $culture->DateTimeFormat;
+ *
+ *
+ * To create a DateTimeFormatInfo for the invariant culture, use
+ *
+ * DateTimeFormatInfo::getInstance($culture=null);
+ *
+ * you may pass a CultureInfo parameter $culture to get the DateTimeFormatInfo
+ * for a specific culture.
+ *
+ * DateTime values are formatted using standard or custom patterns stored in
+ * the properties of a DateTimeFormatInfo.
+ *
+ * The standard patterns can be replaced with custom patterns by setting the
+ * associated properties of DateTimeFormatInfo.
+ *
+ * The following table lists the standard format characters for each standard
+ * pattern and the associated DateTimeFormatInfo property that can be set to
+ * modify the standard pattern. The format characters are case-sensitive;
+ * for example, 'g' and 'G' represent slightly different patterns.
+ *
+ *
+ * Format Character Associated Property Example Format Pattern (en-US)
+ * --------------------------------------------------------------------------
+ * d ShortDatePattern MM/dd/yyyy
+ * D LongDatePattern dddd, dd MMMM yyyy
+ * F FullDateTimePattern dddd, dd MMMM yyyy HH:mm:ss
+ * m, M MonthDayPattern MMMM dd
+ * r, R RFC1123Pattern ddd, dd MMM yyyy HH':'mm':'ss 'GMT'
+ * s SortableDateTimePattern yyyy'-'MM'-'dd'T'HH':'mm':'ss
+ * t ShortTimePattern HH:mm
+ * T LongTimePattern HH:mm:ss
+ * Y YearMonthPattern yyyy MMMM
+ * --------------------------------------------------------------------------
+ *
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 03 22:30:31 EST 2004
+ * @package System.I18N.core
+ */
+class DateTimeFormatInfo
+{
+ /**
+ * ICU date time formatting data.
+ * @var array
+ */
+ private $data = array();
+
+ /**
+ * A list of properties that are accessable/writable.
+ * @var array
+ */
+ protected $properties = array();
+
+ /**
+ * Allow functions that begins with 'set' to be called directly
+ * as an attribute/property to retrieve the value.
+ * @return mixed
+ */
+ function __get($name)
+ {
+ $getProperty = 'get'.$name;
+ if(in_array($getProperty, $this->properties))
+ return $this->$getProperty();
+ else
+ throw new Exception('Property '.$name.' does not exists.');
+ }
+
+ /**
+ * Allow functions that begins with 'set' to be called directly
+ * as an attribute/property to set the value.
+ */
+ function __set($name, $value)
+ {
+ $setProperty = 'set'.$name;
+ if(in_array($setProperty, $this->properties))
+ $this->$setProperty($value);
+ else
+ throw new Exception('Property '.$name.' can not be set.');
+ }
+
+ /**
+ * Initializes a new writable instance of the DateTimeFormatInfo class
+ * that is dependent on the ICU data for date time formatting
+ * information. N.B.You should not initialize this class directly
+ * unless you know what you are doing. Please use use
+ * DateTimeFormatInfo::getInstance() to create an instance.
+ * @param array ICU data for date time formatting.
+ * @see getInstance()
+ */
+ function __construct($data=array())
+ {
+ $this->properties = get_class_methods($this);
+
+ if(empty($data))
+ throw new Exception('Please provide the ICU data to initialize.');
+
+ $this->data = $data;
+ }
+
+ /**
+ * Get the internal ICU data for date time formatting.
+ * @return array ICU date time formatting data.
+ */
+ protected function getData()
+ {
+ return $this->data;
+ }
+
+ /**
+ * Gets the default DateTimeFormatInfo that is culture-independent
+ * (invariant).
+ * @return DateTimeFormatInfo default DateTimeFormatInfo.
+ */
+ static function getInvariantInfo()
+ {
+ static $invariant;
+ if(is_null($invariant))
+ {
+ $culture = CultureInfo::getInvariantCulture();
+ $invariant = $culture->DateTimeFormat;
+ }
+ return $invariant;
+ }
+
+ /**
+ * Returns the DateTimeFormatInfo associated with the specified culture.
+ * @param CultureInfo the culture that gets the DateTimeFormat property.
+ * @return DateTimeFormatInfo DateTimeFormatInfo for the specified
+ * culture.
+ */
+ function getInstance($culture=null)
+ {
+
+ if ($culture instanceof CultureInfo)
+ return $culture->DateTimeFormat;
+ else if(is_string($culture))
+ {
+ $cultureInfo = new CultureInfo($culture);
+ return $cultureInfo->DateTimeFormat;
+ }
+ else
+ {
+ $cultureInfo = CultureInfo::getInvariantCulture();
+ return $cultureInfo->DateTimeFormat;
+ }
+ }
+
+ /**
+ * A one-dimensional array of type String containing
+ * the culture-specific abbreviated names of the days
+ * of the week. The array for InvariantInfo contains
+ * "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", and "Sat".
+ * @return array abbreviated day names
+ */
+ function getAbbreviatedDayNames()
+ {
+ return $this->data['dayNames']['format']['abbreviated'];
+ //return $this->data['dayNames/format/abbreviated'];
+ }
+
+ /**
+ * Set the abbreviated day names. The value should be
+ * an array of string starting with Sunday and ends in Saturady.
+ * For example,
+ * array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
+ * @param array abbreviated day names.
+ */
+ function setAbbreviatedDayNames($value)
+ {
+ $this->data['dayNames']['format']['abbreviated'] = $value;
+ }
+
+ /**
+ * A one-dimensional array of type String containing
+ * the culture-specific narrow names of the days
+ * of the week. The array for InvariantInfo contains
+ * "S", "M", "T", "W", "T", "F", and "S".
+ * @return array narrow day names
+ */
+ function getNarrowDayNames()
+ {
+ return $this->data['dayNames']['format']['narrow'];
+ }
+
+ /**
+ * Set the narrow day names. The value should be
+ * an array of string starting with Sunday and ends in Saturady.
+ * For example,
+ * array("S", "M", "T", "W", "T", "F", "S");
+ * @param array narrow day names.
+ */
+ function setNarrowDayNames($value)
+ {
+ $this->data['dayNames']['format']['narrow'] = $value;
+ }
+
+ /**
+ * A one-dimensional array of type String containing the
+ * culture-specific full names of the days of the week.
+ * The array for InvariantInfo contains "Sunday", "Monday",
+ * "Tuesday", "Wednesday", "Thursday", "Friday", and "Saturday".
+ * @return array day names
+ */
+ function getDayNames()
+ {
+ return $this->data['dayNames']['format']['wide'];
+ }
+
+
+ /**
+ * Set the day names. The value should be
+ * an array of string starting with Sunday and ends in Saturady.
+ * For example,
+ * array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+ * "Friday", "Saturday".);
+ * @param array day names.
+ */
+ function setDayNames($value)
+ {
+ $this->data['dayNames']['format']['wide'] = $value;
+ }
+
+ /**
+ * A one-dimensional array of type String containing the
+ * culture-specific narrow names of the months. The array
+ * for InvariantInfo contains "J", "F", "M", "A", "M", "J",
+ * "J", "A", "S", "O", "N", and "D".
+ * @return array narrow month names.
+ */
+ function getNarrowMonthNames()
+ {
+ return $this->data['monthNames']['format']['narrow'];
+ }
+
+ /**
+ * Set the narrow month names. The value should be
+ * an array of string starting with J and ends in D.
+ * For example,
+ * array("J","F","M","A","M","J","J","A","S","O","N","D");
+ * @param array month names.
+ */
+ function setNarrowMonthNames($value)
+ {
+ $this->data['monthNames']['format']['narrow'] = $value;
+ }
+
+ /**
+ * A one-dimensional array of type String containing the
+ * culture-specific abbreviated names of the months. The array
+ * for InvariantInfo contains "Jan", "Feb", "Mar", "Apr", "May",
+ * "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", and "Dec".
+ * @return array abbreviated month names.
+ */
+ function getAbbreviatedMonthNames()
+ {
+ return $this->data['monthNames']['format']['abbreviated'];
+ }
+
+ /**
+ * Set the abbreviated month names. The value should be
+ * an array of string starting with Jan and ends in Dec.
+ * For example,
+ * array("Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ * "Jul", "Aug", "Sep","Oct","Nov","Dec");
+ * @param array month names.
+ */
+ function setAbbreviatedMonthNames($value)
+ {
+ $this->data['monthNames']['format']['abbreviated'] = $value;
+ }
+
+ /**
+ * A one-dimensional array of type String containing the
+ * culture-specific full names of the months. The array for
+ * InvariantInfo contains "January", "February", "March", "April",
+ * "May", "June", "July", "August", "September", "October", "November",
+ * and "December"
+ * @return array month names.
+ */
+ function getMonthNames()
+ {
+ return $this->data['monthNames']['format']['wide'];
+ }
+
+ /**
+ * Set the month names. The value should be
+ * an array of string starting with Janurary and ends in December.
+ * For example,
+ * array("January", "February", "March", "April", "May", "June",
+ * "July", "August", "September","October","November","December");
+ * @param array month names.
+ */
+ function setMonthNames($value)
+ {
+ $this->data['monthNames']['format']['wide'] = $value;
+ }
+
+ /**
+ * A string containing the name of the era.
+ * @param int era The integer representing the era.
+ * @return string the era name.
+ */
+ function getEra($era)
+ {
+ $eraName = $this->data['eras']['abbreviated'];
+ return $eraName[$era];
+ }
+
+ /**
+ * The string designator for hours that are "ante meridiem" (before noon).
+ * The default for InvariantInfo is "AM".
+ * @return string AM designator.
+ */
+ function getAMDesignator()
+ {
+ $result = $this->getAMPMMarkers();
+ return $result[0];
+ }
+
+ /**
+ * Set the AM Designator. For example, 'AM'.
+ * @param string AM designator.
+ */
+ function setAMDesignator($value)
+ {
+ $markers = $this->getAMPMMarkers();
+ $markers[0] = $value;
+ $this->setAMPMMarkers($markers);
+ }
+
+ /**
+ * The string designator for hours that are "post meridiem" (after noon).
+ * The default for InvariantInfo is "PM".
+ * @return string PM designator.
+ */
+ function getPMDesignator()
+ {
+ $result = $this->getAMPMMarkers();
+ return $result[1];
+ }
+
+ /**
+ * Set the PM Designator. For example, 'PM'.
+ * @param string PM designator.
+ */
+ function setPMDesignator($value)
+ {
+ $markers = $this->getAMPMMarkers();
+ $markers[1] = $value;
+ $this->setAMPMMarkers($markers);
+ }
+
+ /**
+ * Get the AM and PM markers array.
+ * Default InvariantInfo for AM and PM is array('AM','PM');
+ * @return array AM and PM markers
+ */
+ function getAMPMMarkers()
+ {
+ return $this->data['AmPmMarkers'];
+ }
+
+ /**
+ * Set the AM and PM markers array.
+ * For example array('AM','PM');
+ * @param array AM and PM markers
+ */
+ function setAMPMMarkers($value)
+ {
+ $this->data['AmPmMarkers'] = $value;
+ }
+
+ /**
+ * Returns the full time pattern "HH:mm:ss z" (default).
+ * This is culture sensitive.
+ * @return string pattern "HH:mm:ss z".
+ */
+ function getFullTimePattern()
+ {
+ return $this->data['DateTimePatterns'][0];
+ }
+
+ /**
+ * Returns the long time pattern "HH:mm:ss z" (default).
+ * This is culture sensitive.
+ * @return string pattern "HH:mm:ss z".
+ */
+ function getLongTimePattern()
+ {
+ return $this->data['DateTimePatterns'][1];
+ }
+
+ /**
+ * Returns the medium time pattern "HH:mm:ss" (default).
+ * This is culture sensitive.
+ * @return string pattern "HH:mm:ss".
+ */
+ function getMediumTimePattern()
+ {
+ return $this->data['DateTimePatterns'][2];
+ }
+
+ /**
+ * Returns the short time pattern "HH:mm" (default).
+ * This is culture sensitive.
+ * @return string pattern "HH:mm".
+ */
+ function getShortTimePattern()
+ {
+ return $this->data['DateTimePatterns'][3];
+ }
+
+ /**
+ * Returns the full date pattern "EEEE, yyyy MMMM dd" (default).
+ * This is culture sensitive.
+ * @return string pattern "EEEE, yyyy MMMM dd".
+ */
+ function getFullDatePattern()
+ {
+ return $this->data['DateTimePatterns'][4];
+ }
+
+ /**
+ * Returns the long date pattern "yyyy MMMM d" (default).
+ * This is culture sensitive.
+ * @return string pattern "yyyy MMMM d".
+ */
+ function getLongDatePattern()
+ {
+ return $this->data['DateTimePatterns'][5];
+ }
+
+ /**
+ * Returns the medium date pattern "yyyy MMMM d" (default).
+ * This is culture sensitive.
+ * @return string pattern "yyyy MMM d".
+ */
+ function getMediumDatePattern()
+ {
+ return $this->data['DateTimePatterns'][6];
+ }
+
+ /**
+ * Returns the short date pattern "yy/MM/dd" (default).
+ * This is culture sensitive.
+ * @return string pattern "yy/MM/dd".
+ */
+ function getShortDatePattern()
+ {
+ return $this->data['DateTimePatterns'][7];
+ }
+
+ /**
+ * Returns the date time order pattern, "{1} {0}" (default).
+ * This is culture sensitive.
+ * @return string pattern "{1} {0}".
+ */
+ function getDateTimeOrderPattern()
+ {
+ return $this->data['DateTimePatterns'][8];
+ }
+
+ /**
+ * Formats the date and time in a culture sensitive paterrn.
+ * The default is "Date Time".
+ * @return string date and time formated
+ */
+ function formatDateTime($date, $time)
+ {
+ $pattern = $this->getDateTimeOrderPattern();
+ return str_replace(array('{0}','{1}'), array($time, $date), $pattern);
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/Gettext/MO.php b/framework/I18N/core/Gettext/MO.php
new file mode 100644
index 00000000..f3be1a30
--- /dev/null
+++ b/framework/I18N/core/Gettext/MO.php
@@ -0,0 +1,355 @@
+
+ * @version $Revision: 1.3 $ $Date: 2005/08/27 03:21:12 $
+ * @package System.I18N.core
+ */
+
+
+// +----------------------------------------------------------------------+
+// | PEAR :: File :: Gettext :: MO |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 3.0 of the PHP license, |
+// | that is available at http://www.php.net/license/3_0.txt |
+// | If you did not receive a copy of the PHP license and are unable |
+// | to obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2004 Michael Wallner |
+// +----------------------------------------------------------------------+
+//
+// $Id: MO.php,v 1.3 2005/08/27 03:21:12 weizhuo Exp $
+
+/**
+ * File::Gettext::MO
+ *
+ * @author Michael Wallner
+ * @license PHP License
+ */
+
+require_once dirname(__FILE__).'/TGettext.php';
+
+/**
+ * File_Gettext_MO
+ *
+ * GNU MO file reader and writer.
+ *
+ * @author Michael Wallner
+ * @version $Revision: 1.3 $
+ * @access public
+ * @package System.I18N.core
+ */
+class TGettext_MO extends TGettext
+{
+ /**
+ * file handle
+ *
+ * @access private
+ * @var resource
+ */
+ protected $_handle = null;
+
+ /**
+ * big endianess
+ *
+ * Whether to write with big endian byte order.
+ *
+ * @access public
+ * @var bool
+ */
+ protected $writeBigEndian = false;
+
+ /**
+ * Constructor
+ *
+ * @access public
+ * @return object File_Gettext_MO
+ * @param string $file path to GNU MO file
+ */
+ function TGettext_MO($file = '')
+ {
+ $this->file = $file;
+ }
+
+ /**
+ * _read
+ *
+ * @access private
+ * @return mixed
+ * @param int $bytes
+ */
+ function _read($bytes = 1)
+ {
+ if (0 < $bytes = abs($bytes)) {
+ return fread($this->_handle, $bytes);
+ }
+ return null;
+ }
+
+ /**
+ * _readInt
+ *
+ * @access private
+ * @return int
+ * @param bool $bigendian
+ */
+ function _readInt($bigendian = false)
+ {
+ //unpack returns a reference????
+ $unpacked = unpack($bigendian ? 'N' : 'V', $this->_read(4));
+ return array_shift($unpacked);
+ }
+
+ /**
+ * _writeInt
+ *
+ * @access private
+ * @return int
+ * @param int $int
+ */
+ function _writeInt($int)
+ {
+ return $this->_write(pack($this->writeBigEndian ? 'N' : 'V', (int) $int));
+ }
+
+ /**
+ * _write
+ *
+ * @access private
+ * @return int
+ * @param string $data
+ */
+ function _write($data)
+ {
+ return fwrite($this->_handle, $data);
+ }
+
+ /**
+ * _writeStr
+ *
+ * @access private
+ * @return int
+ * @param string $string
+ */
+ function _writeStr($string)
+ {
+ return $this->_write($string . "\0");
+ }
+
+ /**
+ * _readStr
+ *
+ * @access private
+ * @return string
+ * @param array $params associative array with offset and length
+ * of the string
+ */
+ function _readStr($params)
+ {
+ fseek($this->_handle, $params['offset']);
+ return $this->_read($params['length']);
+ }
+
+ /**
+ * Load MO file
+ *
+ * @access public
+ * @return mixed Returns true on success or PEAR_Error on failure.
+ * @param string $file
+ */
+ function load($file = null)
+ {
+ if (!isset($file)) {
+ $file = $this->file;
+ }
+
+ // open MO file
+ if (!is_resource($this->_handle = @fopen($file, 'rb'))) {
+ return false;
+ }
+ // lock MO file shared
+ if (!@flock($this->_handle, LOCK_SH)) {
+ @fclose($this->_handle);
+ return false;
+ }
+
+ // read (part of) magic number from MO file header and define endianess
+
+ //unpack returns a reference????
+ $unpacked = unpack('c', $this->_read(4));
+ switch ($magic = array_shift($unpacked))
+ {
+ case -34:
+ $be = false;
+ break;
+
+ case -107:
+ $be = true;
+ break;
+
+ default:
+ return false;
+ }
+
+ // check file format revision - we currently only support 0
+ if (0 !== ($_rev = $this->_readInt($be))) {
+ return false;
+ }
+
+ // count of strings in this file
+ $count = $this->_readInt($be);
+
+ // offset of hashing table of the msgids
+ $offset_original = $this->_readInt($be);
+ // offset of hashing table of the msgstrs
+ $offset_translat = $this->_readInt($be);
+
+ // move to msgid hash table
+ fseek($this->_handle, $offset_original);
+ // read lengths and offsets of msgids
+ $original = array();
+ for ($i = 0; $i < $count; $i++) {
+ $original[$i] = array(
+ 'length' => $this->_readInt($be),
+ 'offset' => $this->_readInt($be)
+ );
+ }
+
+ // move to msgstr hash table
+ fseek($this->_handle, $offset_translat);
+ // read lengths and offsets of msgstrs
+ $translat = array();
+ for ($i = 0; $i < $count; $i++) {
+ $translat[$i] = array(
+ 'length' => $this->_readInt($be),
+ 'offset' => $this->_readInt($be)
+ );
+ }
+
+ // read all
+ for ($i = 0; $i < $count; $i++) {
+ $this->strings[$this->_readStr($original[$i])] =
+ $this->_readStr($translat[$i]);
+ }
+
+ // done
+ @flock($this->_handle, LOCK_UN);
+ @fclose($this->_handle);
+ $this->_handle = null;
+
+ // check for meta info
+ if (isset($this->strings[''])) {
+ $this->meta = parent::meta2array($this->strings['']);
+ unset($this->strings['']);
+ }
+
+ return true;
+ }
+
+ /**
+ * Save MO file
+ *
+ * @access public
+ * @return mixed Returns true on success or PEAR_Error on failure.
+ * @param string $file
+ */
+ function save($file = null)
+ {
+ if (!isset($file)) {
+ $file = $this->file;
+ }
+
+ // open MO file
+ if (!is_resource($this->_handle = @fopen($file, 'wb'))) {
+ return false;
+ }
+ // lock MO file exclusively
+ if (!@flock($this->_handle, LOCK_EX)) {
+ @fclose($this->_handle);
+ return false;
+ }
+
+ // write magic number
+ if ($this->writeBigEndian) {
+ $this->_write(pack('c*', 0x95, 0x04, 0x12, 0xde));
+ } else {
+ $this->_write(pack('c*', 0xde, 0x12, 0x04, 0x95));
+ }
+
+ // write file format revision
+ $this->_writeInt(0);
+
+ $count = count($this->strings) + ($meta = (count($this->meta) ? 1 : 0));
+ // write count of strings
+ $this->_writeInt($count);
+
+ $offset = 28;
+ // write offset of orig. strings hash table
+ $this->_writeInt($offset);
+
+ $offset += ($count * 8);
+ // write offset transl. strings hash table
+ $this->_writeInt($offset);
+
+ // write size of hash table (we currently ommit the hash table)
+ $this->_writeInt(0);
+
+ $offset += ($count * 8);
+ // write offset of hash table
+ $this->_writeInt($offset);
+
+ // unshift meta info
+ if ($this->meta) {
+ $meta = '';
+ foreach ($this->meta as $key => $val) {
+ $meta .= $key . ': ' . $val . "\n";
+ }
+ $strings = array('' => $meta) + $this->strings;
+ } else {
+ $strings = $this->strings;
+ }
+
+ // write offsets for original strings
+ foreach (array_keys($strings) as $o) {
+ $len = strlen($o);
+ $this->_writeInt($len);
+ $this->_writeInt($offset);
+ $offset += $len + 1;
+ }
+
+ // write offsets for translated strings
+ foreach ($strings as $t) {
+ $len = strlen($t);
+ $this->_writeInt($len);
+ $this->_writeInt($offset);
+ $offset += $len + 1;
+ }
+
+ // write original strings
+ foreach (array_keys($strings) as $o) {
+ $this->_writeStr($o);
+ }
+
+ // write translated strings
+ foreach ($strings as $t) {
+ $this->_writeStr($t);
+ }
+
+ // done
+ @flock($this->_handle, LOCK_UN);
+ @fclose($this->_handle);
+ return true;
+ }
+}
+?>
diff --git a/framework/I18N/core/Gettext/PO.php b/framework/I18N/core/Gettext/PO.php
new file mode 100644
index 00000000..3c69c091
--- /dev/null
+++ b/framework/I18N/core/Gettext/PO.php
@@ -0,0 +1,160 @@
+
+ * @version $Revision: 1.2 $ $Date: 2005/01/05 03:15:14 $
+ * @package System.I18N.core
+ */
+
+// +----------------------------------------------------------------------+
+// | PEAR :: File :: Gettext :: PO |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 3.0 of the PHP license, |
+// | that is available at http://www.php.net/license/3_0.txt |
+// | If you did not receive a copy of the PHP license and are unable |
+// | to obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2004 Michael Wallner |
+// +----------------------------------------------------------------------+
+//
+// $Id: PO.php,v 1.2 2005/01/05 03:15:14 weizhuo Exp $
+
+/**
+ * File::Gettext::PO
+ *
+ * @author Michael Wallner
+ * @license PHP License
+ */
+
+require_once dirname(__FILE__).'/TGettext.php';
+
+/**
+ * File_Gettext_PO
+ *
+ * GNU PO file reader and writer.
+ *
+ * @author Michael Wallner
+ * @version $Revision: 1.2 $
+ * @access public
+ * @package System.I18N.core
+ */
+class TGettext_PO extends TGettext
+{
+ /**
+ * Constructor
+ *
+ * @access public
+ * @return object File_Gettext_PO
+ * @param string path to GNU PO file
+ */
+ function TGettext_PO($file = '')
+ {
+ $this->file = $file;
+ }
+
+ /**
+ * Load PO file
+ *
+ * @access public
+ * @return mixed Returns true on success or PEAR_Error on failure.
+ * @param string $file
+ */
+ function load($file = null)
+ {
+ if (!isset($file)) {
+ $file = $this->file;
+ }
+
+ // load file
+ if (!$contents = @file($file)) {
+ return false;
+ }
+ $contents = implode('', $contents);
+
+ // match all msgid/msgstr entries
+ $matched = preg_match_all(
+ '/(msgid\s+("([^"]|\\\\")*?"\s*)+)\s+' .
+ '(msgstr\s+("([^"]|\\\\")*?"\s*)+)/',
+ $contents, $matches
+ );
+ unset($contents);
+
+ if (!$matched) {
+ return false;
+ }
+
+ // get all msgids and msgtrs
+ for ($i = 0; $i < $matched; $i++) {
+ $msgid = preg_replace(
+ '/\s*msgid\s*"(.*)"\s*/s', '\\1', $matches[1][$i]);
+ $msgstr= preg_replace(
+ '/\s*msgstr\s*"(.*)"\s*/s', '\\1', $matches[4][$i]);
+ $this->strings[parent::prepare($msgid)] = parent::prepare($msgstr);
+ }
+
+ // check for meta info
+ if (isset($this->strings[''])) {
+ $this->meta = parent::meta2array($this->strings['']);
+ unset($this->strings['']);
+ }
+
+ return true;
+ }
+
+ /**
+ * Save PO file
+ *
+ * @access public
+ * @return mixed Returns true on success or PEAR_Error on failure.
+ * @param string $file
+ */
+ function save($file = null)
+ {
+ if (!isset($file)) {
+ $file = $this->file;
+ }
+
+ // open PO file
+ if (!is_resource($fh = @fopen($file, 'w'))) {
+ return false;
+ }
+
+ // lock PO file exclusively
+ if (!flock($fh, LOCK_EX)) {
+ fclose($fh);
+ return false;
+ }
+ // write meta info
+ if (count($this->meta)) {
+ $meta = 'msgid ""' . "\nmsgstr " . '""' . "\n";
+ foreach ($this->meta as $k => $v) {
+ $meta .= '"' . $k . ': ' . $v . '\n"' . "\n";
+ }
+ fwrite($fh, $meta . "\n");
+ }
+ // write strings
+ foreach ($this->strings as $o => $t) {
+ fwrite($fh,
+ 'msgid "' . parent::prepare($o, true) . '"' . "\n" .
+ 'msgstr "' . parent::prepare($t, true) . '"' . "\n\n"
+ );
+ }
+
+ //done
+ @flock($fh, LOCK_UN);
+ @fclose($fh);
+ return true;
+ }
+}
+?>
diff --git a/framework/I18N/core/Gettext/TGettext.php b/framework/I18N/core/Gettext/TGettext.php
new file mode 100644
index 00000000..8e87bee5
--- /dev/null
+++ b/framework/I18N/core/Gettext/TGettext.php
@@ -0,0 +1,287 @@
+
+ * @version $Revision: 1.4 $ $Date: 2005/01/09 23:36:23 $
+ * @package System.I18N.core
+ */
+
+// +----------------------------------------------------------------------+
+// | PEAR :: File :: Gettext |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 3.0 of the PHP license, |
+// | that is available at http://www.php.net/license/3_0.txt |
+// | If you did not receive a copy of the PHP license and are unable |
+// | to obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2004 Michael Wallner |
+// +----------------------------------------------------------------------+
+//
+// $Id: TGettext.php,v 1.4 2005/01/09 23:36:23 qiangxue Exp $
+
+/**
+ * File::Gettext
+ *
+ * @author Michael Wallner
+ * @license PHP License
+ */
+
+/**
+ * Use PHPs builtin error messages
+ */
+//ini_set('track_errors', true);
+
+/**
+ * File_Gettext
+ *
+ * GNU gettext file reader and writer.
+ *
+ * #################################################################
+ * # All protected members of this class are public in its childs. #
+ * #################################################################
+ *
+ * @author Michael Wallner
+ * @version $Revision: 1.4 $
+ * @access public
+ * @package System.I18N.core
+ */
+class TGettext
+{
+ /**
+ * strings
+ *
+ * associative array with all [msgid => msgstr] entries
+ *
+ * @access protected
+ * @var array
+ */
+ protected $strings = array();
+
+ /**
+ * meta
+ *
+ * associative array containing meta
+ * information like project name or content type
+ *
+ * @access protected
+ * @var array
+ */
+ protected $meta = array();
+
+ /**
+ * file path
+ *
+ * @access protected
+ * @var string
+ */
+ protected $file = '';
+
+ /**
+ * Factory
+ *
+ * @static
+ * @access public
+ * @return object Returns File_Gettext_PO or File_Gettext_MO on success
+ * or PEAR_Error on failure.
+ * @param string $format MO or PO
+ * @param string $file path to GNU gettext file
+ */
+ function factory($format, $file = '')
+ {
+ $format = strToUpper($format);
+ $filename = dirname(__FILE__).'/'.$format.'.php';
+ if(is_file($filename) == false)
+ throw new Exception ("Class file $file not found");
+
+ include_once $filename;
+ $class = 'TGettext_' . $format;
+
+ return new $class($file);
+ }
+
+ /**
+ * poFile2moFile
+ *
+ * That's a simple fake of the 'msgfmt' console command. It reads the
+ * contents of a GNU PO file and saves them to a GNU MO file.
+ *
+ * @static
+ * @access public
+ * @return mixed Returns true on success or PEAR_Error on failure.
+ * @param string $pofile path to GNU PO file
+ * @param string $mofile path to GNU MO file
+ */
+ function poFile2moFile($pofile, $mofile)
+ {
+ if (!is_file($pofile)) {
+ throw new Exception("File $pofile doesn't exist.");
+ }
+
+ include_once dirname(__FILE__).'/PO.php';
+
+ $PO = new TGettext_PO($pofile);
+ if (true !== ($e = $PO->load())) {
+ return $e;
+ }
+
+ $MO = $PO->toMO();
+ if (true !== ($e = $MO->save($mofile))) {
+ return $e;
+ }
+ unset($PO, $MO);
+
+ return true;
+ }
+
+ /**
+ * prepare
+ *
+ * @static
+ * @access protected
+ * @return string
+ * @param string $string
+ * @param bool $reverse
+ */
+ function prepare($string, $reverse = false)
+ {
+ if ($reverse) {
+ $smap = array('"', "\n", "\t", "\r");
+ $rmap = array('\"', '\\n"' . "\n" . '"', '\\t', '\\r');
+ return (string) str_replace($smap, $rmap, $string);
+ } else {
+ $string = preg_replace('/"\s+"/', '', $string);
+ $smap = array('\\n', '\\r', '\\t', '\"');
+ $rmap = array("\n", "\r", "\t", '"');
+ return (string) str_replace($smap, $rmap, $string);
+ }
+ }
+
+ /**
+ * meta2array
+ *
+ * @static
+ * @access public
+ * @return array
+ * @param string $meta
+ */
+ function meta2array($meta)
+ {
+ $array = array();
+ foreach (explode("\n", $meta) as $info) {
+ if ($info = trim($info)) {
+ list($key, $value) = explode(':', $info, 2);
+ $array[trim($key)] = trim($value);
+ }
+ }
+ return $array;
+ }
+
+ /**
+ * toArray
+ *
+ * Returns meta info and strings as an array of a structure like that:
+ *
+ * array(
+ * 'meta' => array(
+ * 'Content-Type' => 'text/plain; charset=iso-8859-1',
+ * 'Last-Translator' => 'Michael Wallner ',
+ * 'PO-Revision-Date' => '2004-07-21 17:03+0200',
+ * 'Language-Team' => 'German ',
+ * ),
+ * 'strings' => array(
+ * 'All rights reserved' => 'Alle Rechte vorbehalten',
+ * 'Welcome' => 'Willkommen',
+ * // ...
+ * )
+ * )
+ *
+ *
+ * @see fromArray()
+ * @access protected
+ * @return array
+ */
+ function toArray()
+ {
+ return array('meta' => $this->meta, 'strings' => $this->strings);
+ }
+
+ /**
+ * fromArray
+ *
+ * Assigns meta info and strings from an array of a structure like that:
+ *
+ * array(
+ * 'meta' => array(
+ * 'Content-Type' => 'text/plain; charset=iso-8859-1',
+ * 'Last-Translator' => 'Michael Wallner ',
+ * 'PO-Revision-Date' => date('Y-m-d H:iO'),
+ * 'Language-Team' => 'German ',
+ * ),
+ * 'strings' => array(
+ * 'All rights reserved' => 'Alle Rechte vorbehalten',
+ * 'Welcome' => 'Willkommen',
+ * // ...
+ * )
+ * )
+ *
+ *
+ * @see toArray()
+ * @access protected
+ * @return bool
+ * @param array $array
+ */
+ function fromArray($array)
+ {
+ if (!array_key_exists('strings', $array)) {
+ if (count($array) != 2) {
+ return false;
+ } else {
+ list($this->meta, $this->strings) = $array;
+ }
+ } else {
+ $this->meta = @$array['meta'];
+ $this->strings = @$array['strings'];
+ }
+ return true;
+ }
+
+ /**
+ * toMO
+ *
+ * @access protected
+ * @return object File_Gettext_MO
+ */
+ function toMO()
+ {
+ include_once dirname(__FILE__).'/MO.php';
+ $MO = new TGettext_MO;
+ $MO->fromArray($this->toArray());
+ return $MO;
+ }
+
+ /**
+ * toPO
+ *
+ * @access protected
+ * @return object File_Gettext_PO
+ */
+ function toPO()
+ {
+ include_once dirname(__FILE__).'/PO.php';
+ $PO = new TGettext_PO;
+ $PO->fromArray($this->toArray());
+ return $PO;
+ }
+}
+?>
diff --git a/framework/I18N/core/HTTPNegotiator.php b/framework/I18N/core/HTTPNegotiator.php
new file mode 100644
index 00000000..d9158969
--- /dev/null
+++ b/framework/I18N/core/HTTPNegotiator.php
@@ -0,0 +1,125 @@
+
+ * @version $Revision: 1.2 $ $Date: 2005/01/05 03:15:14 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Include the CultureInfo class.
+ */
+require_once(dirname(__FILE__).'/CultureInfo.php');
+
+/**
+ * HTTPNegotiator class.
+ *
+ * Get the language and charset information from the client browser.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 16:01:35 EST 2004
+ * @package System.I18N.core
+ */
+class HTTPNegotiator
+{
+ /**
+ * A list of languages accepted by the browser.
+ * @var array
+ */
+ protected $languages;
+
+ /**
+ * A list of charsets accepted by the browser
+ * @var array
+ */
+ protected $charsets;
+
+ /**
+ * Get a list of languages acceptable by the client browser
+ * @return array languages ordered in the user browser preferences.
+ */
+ function getLanguages()
+ {
+ if(!is_null($this->languages))
+ return $this->languages;
+
+ $this->languages = array();
+
+ if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
+ return $this->languages;
+
+ //$basedir = CultureInfo::dataDir();
+ //$ext = CultureInfo::fileExt();
+
+ foreach(explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $lang)
+ {
+ // Cut off any q-value that might come after a semi-colon
+ if ($pos = strpos($lang, ';'))
+ $lang = trim(substr($lang, 0, $pos));
+
+ if (strstr($lang, '-'))
+ {
+ $codes = explode('-',$lang);
+ if($codes[0] == 'i')
+ {
+ // Language not listed in ISO 639 that are not variants
+ // of any listed language, which can be registerd with the
+ // i-prefix, such as i-cherokee
+ if(count($codes)>1)
+ $lang = $codes[1];
+ }
+ else
+ {
+ for($i = 0; $ilanguages[] = $lang;
+ }
+
+ return $this->languages;
+ }
+
+ /**
+ * Get a list of charsets acceptable by the client browser.
+ * @return array list of charsets in preferable order.
+ */
+ function getCharsets()
+ {
+ if(!is_null($this->charsets))
+ return $this->charsets;
+
+ $this->charsets = array();
+
+ if (!isset($_SERVER['HTTP_ACCEPT_CHARSET']))
+ return $this->charsets;
+
+ foreach (explode(',', $_SERVER['HTTP_ACCEPT_CHARSET']) as $charset)
+ {
+ if (!empty($charset))
+ $this->charsets[] = preg_replace('/;.*/', '', $charset);
+ }
+
+ return $this->charsets;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/IMessageSource.php b/framework/I18N/core/IMessageSource.php
new file mode 100644
index 00000000..2bdab5fe
--- /dev/null
+++ b/framework/I18N/core/IMessageSource.php
@@ -0,0 +1,123 @@
+
+ * @version $Revision: 1.3 $ $Date: 2005/01/09 22:15:32 $
+ * @package System.I18N.core
+ */
+
+/**
+ * IMessageSource interface.
+ *
+ * All messages source used by MessageFormat must be of IMessageSource.
+ * It defines a set of operations to add and retrive messages from the
+ * message source. In addition, message source can load a particular
+ * catalogue.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 17:40:19 EST 2004
+ * @package System.I18N.core
+ */
+interface IMessageSource
+{
+ /**
+ * Load the translation table for this particular catalogue.
+ * The translation should be loaded in the following order.
+ * # [1] call getCatalogeList($catalogue) to get a list of
+ * variants for for the specified $catalogue.
+ * # [2] for each of the variants, call getSource($variant)
+ * to get the resource, could be a file or catalogue ID.
+ * # [3] verify that this resource is valid by calling isValidSource($source)
+ * # [4] try to get the messages from the cache
+ * # [5] if a cache miss, call load($source) to load the message array
+ * # [6] store the messages to cache.
+ * # [7] continue with the foreach loop, e.g. goto [2].
+ *
+ * @param string a catalogue to load
+ * @return boolean true if loaded, false otherwise.
+ */
+ function load($catalogue = 'messages');
+
+ /**
+ * Get the translation table. This includes all the loaded sections.
+ * It must return a 2 level array of translation strings.
+ * # "catalogue+variant" the catalogue and its variants.
+ * # "source string" translation keys, and its translations.
+ *
+ * array('catalogue+variant' =>
+ * array('source string' => 'target string', ...)
+ * ...),
+ * ...);
+ *
+ *
+ * @return array 2 level array translation table.
+ */
+ function read();
+
+ /**
+ * Save the list of untranslated blocks to the translation source.
+ * If the translation was not found, you should add those
+ * strings to the translation source via the append() method.
+ * @param string the catalogue to add to
+ * @return boolean true if saved successfuly, false otherwise.
+ */
+ function save($catalogue='messages');
+
+ /**
+ * Add a untranslated message to the source. Need to call save()
+ * to save the messages to source.
+ * @param string message to add
+ * @return void
+ */
+ function append($message);
+
+ /**
+ * Delete a particular message from the specified catalogue.
+ * @param string the source message to delete.
+ * @param string the catalogue to delete from.
+ * @return boolean true if deleted, false otherwise.
+ */
+ function delete($message, $catalogue='messages');
+
+ /**
+ * Update the translation.
+ * @param string the source string.
+ * @param string the new translation string.
+ * @param string comments
+ * @param string the catalogue of the translation.
+ * @return boolean true if translation was updated, false otherwise.
+ */
+ function update($text, $target, $comments, $catalogue='messages');
+
+ /**
+ * Returns a list of catalogue as key and all it variants as value.
+ * @return array list of catalogues
+ */
+ function catalogues();
+
+ /**
+ * Set the culture for this particular message source.
+ * @param string the Culture name.
+ */
+ function setCulture($culture);
+
+ /**
+ * Get the culture identifier for the source.
+ * @return string culture identifier.
+ */
+ function getCulture();
+
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/MessageCache.php b/framework/I18N/core/MessageCache.php
new file mode 100644
index 00000000..e39ff63a
--- /dev/null
+++ b/framework/I18N/core/MessageCache.php
@@ -0,0 +1,171 @@
+ $cacheDir,
+ 'lifeTime' => $this->getLifeTime(),
+ 'automaticSerialization' => true
+ );
+
+ $this->cache = new TCache_Lite($options);
+ }
+
+ /**
+ * Get the cache life time.
+ * @return int Cache life time.
+ */
+ public function getLifeTime()
+ {
+ return $this->lifetime;
+ }
+
+ /**
+ * Set the cache life time.
+ * @param int $time Cache life time.
+ */
+ public function setLifeTime($time)
+ {
+ $this->lifetime = intval($time);
+ }
+
+ /**
+ * Get the cache file ID based section and locale.
+ * @param string $catalogue The translation section.
+ * @param string $culture The translation locale, e.g. "en_AU".
+ */
+ protected function getID($catalogue, $culture)
+ {
+ return $catalogue.':'.$culture;
+ }
+
+ /**
+ * Get the cache file GROUP based section and locale.
+ * @param string $catalogue The translation section.
+ * @param string $culture The translation locale, e.g. "en_AU".
+ */
+ protected function getGroup($catalogue, $culture)
+ {
+ return $catalogue.':'.get_class($this);
+ }
+
+ /**
+ * Get the data from the cache.
+ * @param string $catalogue The translation section.
+ * @param string $culture The translation locale, e.g. "en_AU".
+ * @param string $filename If the source is a file, this file's modified
+ * time is newer than the cache's modified time, no cache hit.
+ * @return mixed Boolean FALSE if no cache hit. Otherwise, translation
+ * table data for the specified section and locale.
+ */
+ public function get($catalogue, $culture, $lastmodified=0)
+ {
+ $ID = $this->getID($catalogue, $culture);
+ $group = $this->getGroup($catalogue, $culture);
+
+ $this->cache->_setFileName($ID, $group);
+
+ $cache = $this->cache->getCacheFile();
+
+ if(is_file($cache) == false)
+ return false;
+
+
+ $lastmodified = intval($lastmodified);
+
+ if($lastmodified <= 0 || $lastmodified > filemtime($cache))
+ return false;
+
+ //echo '@@ Cache hit: "'.$ID.'" : "'.$group.'"';
+ //echo "
\n";
+
+ return $this->cache->get($ID, $group);
+ }
+
+ /**
+ * Save the data to cache for the specified section and locale.
+ * @param array $data The data to save.
+ * @param string $catalogue The translation section.
+ * @param string $culture The translation locale, e.g. "en_AU".
+ */
+ public function save($data, $catalogue, $culture)
+ {
+ $ID = $this->getID($catalogue, $culture);
+ $group = $this->getGroup($catalogue, $culture);
+
+ //echo '## Cache save: "'.$ID.'" : "'.$group.'"';
+ //echo "
\n";
+
+ return $this->cache->save($data, $ID, $group);
+ }
+
+ /**
+ * Clean up the cache for the specified section and locale.
+ * @param string $catalogue The translation section.
+ * @param string $culture The translation locale, e.g. "en_AU".
+ */
+ public function clean($catalogue, $culture)
+ {
+ $group = $this->getGroup($catalogue, $culture);
+ $this->cache->clean($group);
+ }
+
+ /**
+ * Flush the cache. Deletes all the cache files.
+ */
+ public function clear()
+ {
+ $this->cache->clean();
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/MessageFormat.php b/framework/I18N/core/MessageFormat.php
new file mode 100644
index 00000000..dab7434c
--- /dev/null
+++ b/framework/I18N/core/MessageFormat.php
@@ -0,0 +1,252 @@
+
+ * @version $Revision: 1.5 $ $Date: 2005/08/27 03:21:12 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the MessageSource classes.
+ */
+require_once(dirname(__FILE__).'/MessageSource.php');
+
+/**
+ * Get the encoding utilities
+ */
+require_once(dirname(__FILE__).'/util.php');
+
+/**
+ * MessageFormat class.
+ *
+ * Format a message, that is, for a particular message find the
+ * translated message. The following is an example using
+ * a SQLite database to store the translation message.
+ * Create a new message format instance and echo "Hello"
+ * in simplified Chinese. This assumes that the world "Hello"
+ * is translated in the database.
+ *
+ *
+ * $source = MessageSource::factory('SQLite', 'sqlite://messages.db');
+ * $source->setCulture('zh_CN');
+ * $source->setCache(new MessageCache('./tmp'));
+ *
+ * $formatter = new MessageFormat($source);
+ *
+ * echo $formatter->format('Hello');
+ *
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 20:46:16 EST 2004
+ * @package System.I18N.core
+ */
+class MessageFormat
+{
+ /**
+ * The message source.
+ * @var MessageSource
+ */
+ protected $source;
+
+ /**
+ * A list of loaded message catalogues.
+ * @var array
+ */
+ protected $catagloues = array();
+
+ /**
+ * The translation messages.
+ * @var array
+ */
+ protected $messages = array();
+
+ /**
+ * A list of untranslated messages.
+ * @var array
+ */
+ protected $untranslated = array();
+
+ /**
+ * The prefix and suffix to append to untranslated messages.
+ * @var array
+ */
+ protected $postscript = array('','');
+
+ /**
+ * Set the default catalogue.
+ * @var string
+ */
+ public $Catalogue;
+
+ /**
+ * Output encoding charset
+ * @var string
+ */
+ protected $charset = 'UTF-8';
+
+ /**
+ * Constructor.
+ * Create a new instance of MessageFormat using the messages
+ * from the supplied message source.
+ * @param MessageSource the source of translation messages.
+ * @param string charset for the message output.
+ */
+ function __construct(IMessageSource $source, $charset='UTF-8')
+ {
+ $this->source = $source;
+ $this->setCharset($charset);
+ }
+
+ /**
+ * Sets the charset for message output.
+ * @param string charset, default is UTF-8
+ */
+ public function setCharset($charset)
+ {
+ $this->charset = $charset;
+ }
+
+ /**
+ * Gets the charset for message output. Default is UTF-8.
+ * @return string charset, default UTF-8
+ */
+ public function getCharset()
+ {
+ return $this->charset;
+ }
+
+ /**
+ * Load the message from a particular catalogue. A listed
+ * loaded catalogues is kept to prevent reload of the same
+ * catalogue. The load catalogue messages are stored
+ * in the $this->message array.
+ * @param string message catalogue to load.
+ */
+ protected function loadCatalogue($catalogue)
+ {
+ if(in_array($catalogue,$this->catagloues))
+ return;
+
+ if($this->source->load($catalogue))
+ {
+ $this->messages[$catalogue] = $this->source->read();
+ $this->catagloues[] = $catalogue;
+ }
+ }
+
+ /**
+ * Format the string. That is, for a particular string find
+ * the corresponding translation. Variable subsitution is performed
+ * for the $args parameter. A different catalogue can be specified
+ * using the $catalogue parameter.
+ * The output charset is determined by $this->getCharset();
+ * @param string the string to translate.
+ * @param array a list of string to substitute.
+ * @param string get the translation from a particular message
+ * @param string charset, the input AND output charset
+ * catalogue.
+ * @return string translated string.
+ */
+ public function format($string,$args=array(), $catalogue=null, $charset=null)
+ {
+ if(empty($charset)) $charset = $this->getCharset();
+ $s = $this->formatString(I18N_toUTF8($string, $charset),$args,$catalogue);
+ return I18N_toEncoding($s, $charset);
+ }
+
+ /**
+ * Do string translation.
+ * @param string the string to translate.
+ * @param array a list of string to substitute.
+ * @param string get the translation from a particular message
+ * catalogue.
+ * @return string translated string.
+ */
+ protected function formatString($string, $args=array(), $catalogue=null)
+ {
+ if(empty($catalogue))
+ {
+ if(empty($this->Catalogue))
+ $catalogue = 'messages';
+ else
+ $catalogue = $this->Catalogue;
+ }
+
+ $this->loadCatalogue($catalogue);
+
+ if(empty($args))
+ $args = array();
+
+ foreach($this->messages[$catalogue] as $variant)
+ {
+ // foreach of the translation units
+ foreach($variant as $source => $result)
+ {
+ // we found it, so return the target translation
+ if($source == $string)
+ {
+ //check if it contains only strings.
+ if(is_string($result))
+ $target = $result;
+ else
+ {
+ $target = $result[0];
+ }
+ //found, but untranslated
+ if(empty($target))
+ {
+ return $this->postscript[0].
+ strtr($string, $args).
+ $this->postscript[1];
+ }
+ else
+ return strtr($target, $args);
+ }
+ }
+ }
+
+ // well we did not find the translation string.
+ $this->source->append($string);
+
+ return $this->postscript[0].
+ strtr($string, $args).
+ $this->postscript[1];
+ }
+
+ /**
+ * Get the message source.
+ * @return MessageSource
+ */
+ function getSource()
+ {
+ return $this->source;
+ }
+
+ /**
+ * Set the prefix and suffix to append to untranslated messages.
+ * e.g. $postscript=array('[T]','[/T]'); will output
+ * "[T]Hello[/T]" if the translation for "Hello" can not be determined.
+ * @param array first element is the prefix, second element the suffix.
+ */
+ function setUntranslatedPS($postscript)
+ {
+ if(is_array($postscript) && count($postscript)>=2)
+ {
+ $this->postscript[0] = $postscript[0];
+ $this->postscript[1] = $postscript[1];
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/MessageSource.php b/framework/I18N/core/MessageSource.php
new file mode 100644
index 00000000..d69a13d9
--- /dev/null
+++ b/framework/I18N/core/MessageSource.php
@@ -0,0 +1,333 @@
+
+ * @version $Revision: 1.4 $ $Date: 2005/12/17 06:11:28 $
+ * @package System.I18N.core
+ */
+
+ /**
+ * Get the IMessageSource interface.
+ */
+require_once(dirname(__FILE__).'/IMessageSource.php');
+
+/**
+ * Get the MessageCache class file.
+ */
+require_once(dirname(__FILE__).'/MessageCache.php');
+
+/**
+ * Abstract MessageSource class.
+ *
+ * The base class for all MessageSources. Message sources must be instantiated
+ * using the factory method. The default valid sources are
+ *
+ * # XLIFF -- using XML XLIFF format to store the translation messages.
+ * # SQLite -- Store the translation messages in a SQLite database.
+ * # MySQL -- Using a MySQL database to store the messages.
+ * # gettext -- Translated messages are stored in the gettext format.
+ *
+ * A custom message source can be instantiated by specifying the filename
+ * parameter to point to the custom class file. E.g.
+ *
+ * $resource = '...'; //custom message source resource
+ * $classfile = '../MessageSource_MySource.php'; //custom message source
+ * $source = MessageSource::factory('MySource', $resource, $classfile);
+ *
+ *
+ * If you are writting your own message sources, pay attention to the
+ * loadCatalogue method. It details how the resources are loaded and cached.
+ * See also the existing message source types as examples.
+ *
+ * The following example instantiates a MySQL message source, set the culture,
+ * set the cache handler, and use the source in a message formatter.
+ * The messages are store in a database named "messages". The source parameter
+ * for the actory method is a PEAR DB style DSN.
+ *
+ * $dsn = 'mysql://username:password@localhost/messages';
+ * $source = MessageSource::factory('MySQL', $dsn);
+ *
+ * //set the culture and cache, store the cache in the /tmp directory.
+ * $source->setCulture('en_AU')l
+ * $source->setCache(new MessageCache('/tmp'));
+ *
+ * $formatter = new MessageFormat($source);
+ *
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 19:55:49 EST 2004
+ * @package System.I18N.core
+ */
+abstract class MessageSource implements IMessageSource
+{
+ /**
+ * The culture name for this message source.
+ * @var string
+ */
+ protected $culture;
+
+ /**
+ * Array of translation messages.
+ * @var array
+ */
+ protected $messages = array();
+
+ /**
+ * The source of message translations.
+ * @var string
+ */
+ protected $source;
+
+ /**
+ * The translation cache.
+ * @var MessageCache
+ */
+ protected $cache;
+
+ protected $untranslated = array();
+
+ /**
+ * Private constructor. MessageSource must be initialized using
+ * the factory method.
+ */
+ private function __construct()
+ {
+ //throw new Exception('Please use the factory method to instantiate.');
+ }
+
+ /**
+ * Factory method to instantiate a new MessageSource depending on the
+ * source type. The allowed source types are 'XLIFF', 'SQLite',
+ * 'MySQL', and 'gettext'. The source parameter is dependent on the
+ * source type. For 'gettext' and 'XLIFF', it should point to the directory
+ * where the messages are stored. For database types, e.g. 'SQLite' and
+ * 'MySQL', it should be a PEAR DB style DSN string.
+ *
+ * Custom message source are possible by supplying the a filename parameter
+ * in the factory method.
+ *
+ * @param string the message source type.
+ * @param string the location of the resource.
+ * @param string the filename of the custom message source.
+ * @return MessageSource a new message source of the specified type.
+ * @throw InvalidMessageSourceTypeException
+ */
+ static function &factory($type, $source='.', $filename='')
+ {
+ $types = array('XLIFF', 'SQLite', 'MySQL', 'gettext');
+
+ if(empty($filename) && in_array($type, $types) == false)
+ throw new Exception('Invalid type "'.$type.'", valid types are '.
+ implode(', ', $types));
+
+ $class = 'MessageSource_'.$type;
+
+ if(empty($filename))
+ $filename = dirname(__FILE__).'/'.$class.'.php';
+
+ if(is_file($filename) == false)
+ throw new Exception("File $filename not found");
+
+ include_once $filename;
+
+ $obj = new $class($source);
+
+ return $obj;
+ }
+
+ /**
+ * Load a particular message catalogue. Use read() to
+ * to get the array of messages. The catalogue loading sequence
+ * is as follows
+ *
+ * # [1] call getCatalogeList($catalogue) to get a list of
+ * variants for for the specified $catalogue.
+ * # [2] for each of the variants, call getSource($variant)
+ * to get the resource, could be a file or catalogue ID.
+ * # [3] verify that this resource is valid by calling isValidSource($source)
+ * # [4] try to get the messages from the cache
+ * # [5] if a cache miss, call load($source) to load the message array
+ * # [6] store the messages to cache.
+ * # [7] continue with the foreach loop, e.g. goto [2].
+ *
+ * @param string a catalogue to load
+ * @return boolean true if loaded, false otherwise.
+ * @see read()
+ */
+ function load($catalogue='messages')
+ {
+ $variants = $this->getCatalogueList($catalogue);
+
+ $this->messages = array();
+
+ foreach($variants as $variant)
+ {
+ $source = $this->getSource($variant);
+
+ if($this->isValidSource($source) == false) continue;
+
+ $loadData = true;
+
+ if($this->cache)
+ {
+ $data = $this->cache->get($variant,
+ $this->culture, $this->getLastModified($source));
+
+ if(is_array($data))
+ {
+ $this->messages[$variant] = $data;
+ $loadData = false;
+ }
+ unset($data);
+ }
+ if($loadData)
+ {
+ $data = &$this->loadData($source);
+ if(is_array($data))
+ {
+ $this->messages[$variant] = $data;
+ if($this->cache)
+ $this->cache->save($data, $variant, $this->culture);
+ }
+ unset($data);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Get the array of messages.
+ * @param parameter
+ * @return array translation messages.
+ */
+ public function read()
+ {
+ return $this->messages;
+ }
+
+ /**
+ * Get the cache handler for this source.
+ * @return MessageCache cache handler
+ */
+ public function getCache()
+ {
+ return $this->cache;
+ }
+
+ /**
+ * Set the cache handler for caching the messages.
+ * @param MessageCache the cache handler.
+ */
+ public function setCache(MessageCache $cache)
+ {
+ $this->cache = $cache;
+ }
+
+ /**
+ * Add a untranslated message to the source. Need to call save()
+ * to save the messages to source.
+ * @param string message to add
+ */
+ public function append($message)
+ {
+ if(!in_array($message, $this->untranslated))
+ $this->untranslated[] = $message;
+ }
+
+ /**
+ * Set the culture for this message source.
+ * @param string culture name
+ */
+ public function setCulture($culture)
+ {
+ $this->culture = $culture;
+ }
+
+ /**
+ * Get the culture identifier for the source.
+ * @return string culture identifier.
+ */
+ public function getCulture()
+ {
+ return $this->culture;
+ }
+
+ /**
+ * Get the last modified unix-time for this particular catalogue+variant.
+ * @param string catalogue+variant
+ * @return int last modified in unix-time format.
+ */
+ protected function getLastModified($source)
+ {
+ return 0;
+ }
+
+ /**
+ * Load the message for a particular catalogue+variant.
+ * This methods needs to implemented by subclasses.
+ * @param string catalogue+variant.
+ * @return array of translation messages.
+ */
+ protected function &loadData($variant)
+ {
+ return array();
+ }
+
+ /**
+ * Get the source, this could be a filename or database ID.
+ * @param string catalogue+variant
+ * @return string the resource key
+ */
+ protected function getSource($variant)
+ {
+ return $variant;
+ }
+
+ /**
+ * Determine if the source is valid.
+ * @param string catalogue+variant
+ * @return boolean true if valid, false otherwise.
+ */
+ protected function isValidSource($source)
+ {
+ return false;
+ }
+
+ /**
+ * Get all the variants of a particular catalogue.
+ * This method must be implemented by subclasses.
+ * @param string catalogue name
+ * @return array list of all variants for this catalogue.
+ */
+ protected function getCatalogueList($catalogue)
+ {
+ return array();
+ }
+}
+
+
+/**
+ * TMessageSourceIOException thrown when unable to modify message source
+ * data.
+ *
+ * @author Wei Zhuo
+ * @version $Revision: 1.4 $ $Date: 2005/12/17 06:11:28 ${DATE} ${TIME} $
+ * @package System.I18N.core
+ */
+class TMessageSourceIOException extends TException
+{
+
+}
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/MessageSource_MySQL.php b/framework/I18N/core/MessageSource_MySQL.php
new file mode 100644
index 00000000..dab8de9f
--- /dev/null
+++ b/framework/I18N/core/MessageSource_MySQL.php
@@ -0,0 +1,418 @@
+
+ * @version $Revision: 1.4 $ $Date: 2005/02/25 09:59:40 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the MessageSource class file.
+ */
+require_once(dirname(__FILE__).'/MessageSource.php');
+
+/**
+ * Get the I18N utility file, contains the DSN parser.
+ */
+require_once(dirname(__FILE__).'/util.php');
+
+/**
+ * MessageSource_MySQL class.
+ *
+ * Retrive the message translation from a MySQL database.
+ *
+ * See the MessageSource::factory() method to instantiate this class.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 16:58:58 EST 2004
+ * @package System.I18N.core
+ */
+class MessageSource_MySQL extends MessageSource
+{
+ /**
+ * The datasource string, full DSN to the database.
+ * @var string
+ */
+ protected $source;
+
+ /**
+ * The DSN array property, parsed by PEAR's DB DSN parser.
+ * @var array
+ */
+ protected $dns;
+
+ /**
+ * A resource link to the database
+ * @var db
+ */
+ protected $db;
+ /**
+ * Constructor.
+ * Create a new message source using MySQL.
+ * @param string MySQL datasource, in PEAR's DB DSN format.
+ * @see MessageSource::factory();
+ */
+ function __construct($source)
+ {
+ $this->source = (string)$source;
+ $this->dns = parseDSN($this->source);
+ $this->db = $this->connect();
+ }
+
+ /**
+ * Destructor, close the database connection.
+ */
+ function __destruct()
+ {
+ @mysql_close($this->db);
+ }
+
+ /**
+ * Connect to the MySQL datasource
+ * @return resource MySQL connection.
+ * @throws Exception, connection and database errors.
+ */
+ protected function connect()
+ {
+ /*static $conn;
+
+ if(!is_null($conn))
+ return $conn;
+ */
+ $dsninfo = $this->dns;
+
+ if (isset($dsninfo['protocol']) && $dsninfo['protocol'] == 'unix')
+ $dbhost = ':' . $dsninfo['socket'];
+ else
+ {
+ $dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
+ if (!empty($dsninfo['port']))
+ $dbhost .= ':' . $dsninfo['port'];
+ }
+ $user = $dsninfo['username'];
+ $pw = $dsninfo['password'];
+
+ $connect_function = 'mysql_connect';
+
+ if ($dbhost && $user && $pw)
+ $conn = @$connect_function($dbhost, $user, $pw);
+ elseif ($dbhost && $user)
+ $conn = @$connect_function($dbhost, $user);
+ elseif ($dbhost)
+ $conn = @$connect_function($dbhost);
+ else
+ $conn = false;
+
+ if (empty($conn))
+ {
+ throw new Exception('Error in connecting to '.$dsninfo);
+ }
+
+ if ($dsninfo['database'])
+ {
+ if (!@mysql_select_db($dsninfo['database'], $conn))
+ throw new Exception('Error in connecting database, dns:'.
+ $dsninfo);
+ }
+ else
+ throw new Exception('Please provide a database for message'.
+ ' translation.');
+ return $conn;
+ }
+
+ /**
+ * Get the database connection.
+ * @return db database connection.
+ */
+ public function connection()
+ {
+ return $this->db;
+ }
+
+ /**
+ * Get an array of messages for a particular catalogue and cultural
+ * variant.
+ * @param string the catalogue name + variant
+ * @return array translation messages.
+ */
+ protected function &loadData($variant)
+ {
+ $variant = mysql_escape_string($variant);
+
+ $statement =
+ "SELECT t.id, t.source, t.target, t.comments
+ FROM trans_unit t, catalogue c
+ WHERE c.cat_id = t.cat_id
+ AND c.name = '{$variant}'
+ ORDER BY id ASC";
+
+ $rs = mysql_query($statement,$this->db);
+
+ $result = array();
+
+ while($row = mysql_fetch_array($rs,MYSQL_NUM))
+ {
+ $source = $row[1];
+ $result[$source][] = $row[2]; //target
+ $result[$source][] = $row[0]; //id
+ $result[$source][] = $row[3]; //comments
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get the last modified unix-time for this particular catalogue+variant.
+ * We need to query the database to get the date_modified.
+ * @param string catalogue+variant
+ * @return int last modified in unix-time format.
+ */
+ protected function getLastModified($source)
+ {
+ $source = mysql_escape_string($source);
+
+ $rs = mysql_query(
+ "SELECT date_modified FROM catalogue WHERE name = '{$source}'",
+ $this->db);
+
+ $result = $rs ? intval(mysql_result($rs,0)) : 0;
+
+ return $result;
+ }
+
+ /**
+ * Check if a particular catalogue+variant exists in the database.
+ * @param string catalogue+variant
+ * @return boolean true if the catalogue+variant is in the database,
+ * false otherwise.
+ */
+ protected function isValidSource($variant)
+ {
+ $variant = mysql_escape_string ($variant);
+
+ $rs = mysql_query(
+ "SELECT COUNT(*) FROM catalogue WHERE name = '{$variant}'",
+ $this->db);
+
+ $row = mysql_fetch_array($rs,MYSQL_NUM);
+
+ $result = $row && $row[0] == '1';
+
+ return $result;
+ }
+
+ /**
+ * Get all the variants of a particular catalogue.
+ * @param string catalogue name
+ * @return array list of all variants for this catalogue.
+ */
+ protected function getCatalogueList($catalogue)
+ {
+ $variants = explode('_',$this->culture);
+
+ $catalogues = array($catalogue);
+
+ $variant = null;
+
+ for($i = 0; $i < count($variants); $i++)
+ {
+ if(strlen($variants[$i])>0)
+ {
+ $variant .= ($variant)?'_'.$variants[$i]:$variants[$i];
+ $catalogues[] = $catalogue.'.'.$variant;
+ }
+ }
+ return array_reverse($catalogues);
+ }
+
+ /**
+ * Retrive catalogue details, array($cat_id, $variant, $count).
+ * @param string catalogue
+ * @return array catalogue details, array($cat_id, $variant, $count).
+ */
+ private function getCatalogueDetails($catalogue='messages')
+ {
+ if(empty($catalogue))
+ $catalogue = 'messages';
+
+ $variant = $catalogue.'.'.$this->culture;
+
+ $name = mysql_escape_string($this->getSource($variant));
+
+ $rs = mysql_query("SELECT cat_id
+ FROM catalogue WHERE name = '{$name}'", $this->db);
+
+ if(mysql_num_rows($rs) != 1)
+ return false;
+
+ $cat_id = intval(mysql_result($rs,0));
+
+ //first get the catalogue ID
+ $rs = mysql_query(
+ "SELECT count(msg_id)
+ FROM trans_unit
+ WHERE cat_id = {$cat_id}", $this->db);
+
+ $count = intval(mysql_result($rs,0));
+
+ return array($cat_id, $variant, $count);
+ }
+
+ /**
+ * Update the catalogue last modified time.
+ * @return boolean true if updated, false otherwise.
+ */
+ private function updateCatalogueTime($cat_id, $variant)
+ {
+ $time = time();
+
+ $result = mysql_query("UPDATE catalogue
+ SET date_modified = {$time}
+ WHERE cat_id = {$cat_id}", $this->db);
+
+ if(!empty($this->cache))
+ $this->cache->clean($variant, $this->culture);
+
+ return $result;
+ }
+
+ /**
+ * Save the list of untranslated blocks to the translation source.
+ * If the translation was not found, you should add those
+ * strings to the translation source via the append() method.
+ * @param string the catalogue to add to
+ * @return boolean true if saved successfuly, false otherwise.
+ */
+ function save($catalogue='messages')
+ {
+ $messages = $this->untranslated;
+
+ if(count($messages) <= 0) return false;
+
+ $details = $this->getCatalogueDetails($catalogue);
+
+ if($details)
+ list($cat_id, $variant, $count) = $details;
+ else
+ return false;
+
+ if($cat_id <= 0) return false;
+ $inserted = 0;
+
+ $time = time();
+
+ foreach($messages as $message)
+ {
+ $count++; $inserted++;
+ $message = mysql_escape_string($message);
+ $statement = "INSERT INTO trans_unit
+ (cat_id,id,source,date_added) VALUES
+ ({$cat_id}, {$count},'{$message}',$time)";
+ mysql_query($statement, $this->db);
+ }
+ if($inserted > 0)
+ $this->updateCatalogueTime($cat_id, $variant);
+
+ return $inserted > 0;
+ }
+
+ /**
+ * Delete a particular message from the specified catalogue.
+ * @param string the source message to delete.
+ * @param string the catalogue to delete from.
+ * @return boolean true if deleted, false otherwise.
+ */
+ function delete($message, $catalogue='messages')
+ {
+ $details = $this->getCatalogueDetails($catalogue);
+ if($details)
+ list($cat_id, $variant, $count) = $details;
+ else
+ return false;
+
+ $text = mysql_escape_string($message);
+
+ $statement = "DELETE FROM trans_unit WHERE
+ cat_id = {$cat_id} AND source = '{$message}'";
+ $deleted = false;
+
+ mysql_query($statement, $this->db);
+
+ if(mysql_affected_rows($this->db) == 1)
+ $deleted = $this->updateCatalogueTime($cat_id, $variant);
+
+ return $deleted;
+
+ }
+
+ /**
+ * Update the translation.
+ * @param string the source string.
+ * @param string the new translation string.
+ * @param string comments
+ * @param string the catalogue of the translation.
+ * @return boolean true if translation was updated, false otherwise.
+ */
+ function update($text, $target, $comments, $catalogue='messages')
+ {
+ $details = $this->getCatalogueDetails($catalogue);
+ if($details)
+ list($cat_id, $variant, $count) = $details;
+ else
+ return false;
+
+ $comments = mysql_escape_string($comments);
+ $target = mysql_escape_string($target);
+ $text = mysql_escape_string($text);
+
+ $time = time();
+
+ $statement = "UPDATE trans_unit SET
+ target = '{$target}',
+ comments = '{$comments}',
+ date_modified = '{$time}'
+ WHERE cat_id = {$cat_id}
+ AND source = '{$text}'";
+
+ $updated = false;
+
+ mysql_query($statement, $this->db);
+ if(mysql_affected_rows($this->db) == 1)
+ $updated = $this->updateCatalogueTime($cat_id, $variant);
+
+ return $updated;
+ }
+
+ /**
+ * Returns a list of catalogue as key and all it variants as value.
+ * @return array list of catalogues
+ */
+ function catalogues()
+ {
+ $statement = 'SELECT name FROM catalogue ORDER BY name';
+ $rs = mysql_query($statement, $this->db);
+ $result = array();
+ while($row = mysql_fetch_array($rs,MYSQL_NUM))
+ {
+ $details = explode('.',$row[0]);
+ if(!isset($details[1])) $details[1] = null;
+
+ $result[] = $details;
+ }
+ return $result;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/MessageSource_SQLite.php b/framework/I18N/core/MessageSource_SQLite.php
new file mode 100644
index 00000000..68aceaaf
--- /dev/null
+++ b/framework/I18N/core/MessageSource_SQLite.php
@@ -0,0 +1,354 @@
+
+ * @version $Revision: 1.4 $ $Date: 2005/02/25 09:59:40 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the MessageSource class file.
+ */
+require_once(dirname(__FILE__).'/MessageSource.php');
+
+/**
+ * Get the I18N utility file, contains the DSN parser.
+ */
+require_once(dirname(__FILE__).'/util.php');
+
+/**
+ * MessageSource_SQLite class.
+ *
+ * Retrive the message translation from a SQLite database.
+ *
+ * See the MessageSource::factory() method to instantiate this class.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 16:58:58 EST 2004
+ * @package System.I18N.core
+ */
+class MessageSource_SQLite extends MessageSource
+{
+ /**
+ * The SQLite datasource, the filename of the database.
+ * @var string
+ */
+ protected $source;
+
+ /**
+ * Constructor.
+ * Create a new message source using SQLite.
+ * @see MessageSource::factory();
+ * @param string SQLite datasource, in PEAR's DB DSN format.
+ */
+ function __construct($source)
+ {
+ $dsn = parseDSN((string)$source);
+ $this->source = $dsn['database'];
+ }
+
+ /**
+ * Get an array of messages for a particular catalogue and cultural
+ * variant.
+ * @param string the catalogue name + variant
+ * @return array translation messages.
+ */
+ protected function &loadData($variant)
+ {
+ $variant = sqlite_escape_string($variant);
+
+ $statement =
+ "SELECT t.id, t.source, t.target, t.comments
+ FROM trans_unit t, catalogue c
+ WHERE c.cat_id = t.cat_id
+ AND c.name = '{$variant}'
+ ORDER BY id ASC";
+
+ $db = sqlite_open($this->source);
+ $rs = sqlite_query($statement, $db);
+
+ $result = array();
+
+ while($row = sqlite_fetch_array($rs,SQLITE_NUM))
+ {
+ $source = $row[1];
+ $result[$source][] = $row[2]; //target
+ $result[$source][] = $row[0]; //id
+ $result[$source][] = $row[3]; //comments
+ }
+
+ sqlite_close($db);
+
+ return $result;
+ }
+
+ /**
+ * Get the last modified unix-time for this particular catalogue+variant.
+ * We need to query the database to get the date_modified.
+ * @param string catalogue+variant
+ * @return int last modified in unix-time format.
+ */
+ protected function getLastModified($source)
+ {
+ $source = sqlite_escape_string($source);
+
+ $db = sqlite_open($this->source);
+
+ $rs = sqlite_query(
+ "SELECT date_modified FROM catalogue WHERE name = '{$source}'",
+ $db);
+
+ $result = $rs ? intval(sqlite_fetch_single($rs)) : 0;
+
+ sqlite_close($db);
+
+ return $result;
+ }
+
+ /**
+ * Check if a particular catalogue+variant exists in the database.
+ * @param string catalogue+variant
+ * @return boolean true if the catalogue+variant is in the database,
+ * false otherwise.
+ */
+ protected function isValidSource($variant)
+ {
+ $variant = sqlite_escape_string($variant);
+ $db = sqlite_open($this->source);
+ $rs = sqlite_query(
+ "SELECT COUNT(*) FROM catalogue WHERE name = '{$variant}'",
+ $db);
+ $result = $rs && intval(sqlite_fetch_single($rs));
+ sqlite_close($db);
+
+ return $result;
+ }
+
+ /**
+ * Get all the variants of a particular catalogue.
+ * @param string catalogue name
+ * @return array list of all variants for this catalogue.
+ */
+ protected function getCatalogueList($catalogue)
+ {
+ $variants = explode('_',$this->culture);
+
+ $catalogues = array($catalogue);
+
+ $variant = null;
+
+ for($i = 0; $i < count($variants); $i++)
+ {
+ if(strlen($variants[$i])>0)
+ {
+ $variant .= ($variant)?'_'.$variants[$i]:$variants[$i];
+ $catalogues[] = $catalogue.'.'.$variant;
+ }
+ }
+ return array_reverse($catalogues);
+ }
+
+ /**
+ * Retrive catalogue details, array($cat_id, $variant, $count).
+ * @param string catalogue
+ * @return array catalogue details, array($cat_id, $variant, $count).
+ */
+ private function getCatalogueDetails($catalogue='messages')
+ {
+ if(empty($catalogue))
+ $catalogue = 'messages';
+
+ $variant = $catalogue.'.'.$this->culture;
+
+ $name = sqlite_escape_string($this->getSource($variant));
+
+ $db = sqlite_open($this->source);
+
+ $rs = sqlite_query("SELECT cat_id
+ FROM catalogue WHERE name = '{$name}'", $db);
+
+ if(sqlite_num_rows($rs) != 1)
+ return false;
+
+ $cat_id = intval(sqlite_fetch_single($rs));
+
+ //first get the catalogue ID
+ $rs = sqlite_query(
+ "SELECT count(msg_id)
+ FROM trans_unit
+ WHERE cat_id = {$cat_id}", $db);
+
+ $count = intval(sqlite_fetch_single($rs));
+
+ sqlite_close($db);
+
+ return array($cat_id, $variant, $count);
+ }
+
+ /**
+ * Update the catalogue last modified time.
+ * @return boolean true if updated, false otherwise.
+ */
+ private function updateCatalogueTime($cat_id, $variant, $db)
+ {
+ $time = time();
+
+ $result = sqlite_query("UPDATE catalogue
+ SET date_modified = {$time}
+ WHERE cat_id = {$cat_id}", $db);
+
+ if(!empty($this->cache))
+ $this->cache->clean($variant, $this->culture);
+
+ return $result;
+ }
+
+ /**
+ * Save the list of untranslated blocks to the translation source.
+ * If the translation was not found, you should add those
+ * strings to the translation source via the append() method.
+ * @param string the catalogue to add to
+ * @return boolean true if saved successfuly, false otherwise.
+ */
+ function save($catalogue='messages')
+ {
+ $messages = $this->untranslated;
+
+ if(count($messages) <= 0) return false;
+
+ $details = $this->getCatalogueDetails($catalogue);
+
+ if($details)
+ list($cat_id, $variant, $count) = $details;
+ else
+ return false;
+
+ if($cat_id <= 0) return false;
+ $inserted = 0;
+
+ $db = sqlite_open($this->source);
+ $time = time();
+
+ foreach($messages as $message)
+ {
+ $message = sqlite_escape_string($message);
+ $statement = "INSERT INTO trans_unit
+ (cat_id,id,source,date_added) VALUES
+ ({$cat_id}, {$count},'{$message}',$time)";
+ if(sqlite_query($statement, $db))
+ {
+ $count++; $inserted++;
+ }
+ }
+ if($inserted > 0)
+ $this->updateCatalogueTime($cat_id, $variant, $db);
+
+ sqlite_close($db);
+
+ return $inserted > 0;
+ }
+
+ /**
+ * Update the translation.
+ * @param string the source string.
+ * @param string the new translation string.
+ * @param string comments
+ * @param string the catalogue of the translation.
+ * @return boolean true if translation was updated, false otherwise.
+ */
+ function update($text, $target, $comments, $catalogue='messages')
+ {
+ $details = $this->getCatalogueDetails($catalogue);
+ if($details)
+ list($cat_id, $variant, $count) = $details;
+ else
+ return false;
+
+ $comments = sqlite_escape_string($comments);
+ $target = sqlite_escape_string($target);
+ $text = sqlite_escape_string($text);
+
+ $time = time();
+
+ $db = sqlite_open($this->source);
+
+ $statement = "UPDATE trans_unit SET
+ target = '{$target}',
+ comments = '{$comments}',
+ date_modified = '{$time}'
+ WHERE cat_id = {$cat_id}
+ AND source = '{$text}'";
+
+ $updated = false;
+
+ if(sqlite_query($statement, $db))
+ $updated = $this->updateCatalogueTime($cat_id, $variant, $db);
+
+ sqlite_close($db);
+
+ return $updated;
+ }
+
+ /**
+ * Delete a particular message from the specified catalogue.
+ * @param string the source message to delete.
+ * @param string the catalogue to delete from.
+ * @return boolean true if deleted, false otherwise.
+ */
+ function delete($message, $catalogue='messages')
+ {
+ $details = $this->getCatalogueDetails($catalogue);
+ if($details)
+ list($cat_id, $variant, $count) = $details;
+ else
+ return false;
+
+ $db = sqlite_open($this->source);
+ $text = sqlite_escape_string($message);
+
+ $statement = "DELETE FROM trans_unit WHERE
+ cat_id = {$cat_id} AND source = '{$message}'";
+ $deleted = false;
+
+ if(sqlite_query($statement, $db))
+ $deleted = $this->updateCatalogueTime($cat_id, $variant, $db);
+
+ sqlite_close($db);
+
+ return $deleted;
+ }
+
+ /**
+ * Returns a list of catalogue as key and all it variants as value.
+ * @return array list of catalogues
+ */
+ function catalogues()
+ {
+ $db = sqlite_open($this->source);
+ $statement = 'SELECT name FROM catalogue ORDER BY name';
+ $rs = sqlite_query($statement, $db);
+ $result = array();
+ while($row = sqlite_fetch_array($rs,SQLITE_NUM))
+ {
+ $details = explode('.',$row[0]);
+ if(!isset($details[1])) $details[1] = null;
+
+ $result[] = $details;
+ }
+ sqlite_close($db);
+ return $result;
+ }
+}
+
+?>
diff --git a/framework/I18N/core/MessageSource_XLIFF.php b/framework/I18N/core/MessageSource_XLIFF.php
new file mode 100644
index 00000000..a2b36611
--- /dev/null
+++ b/framework/I18N/core/MessageSource_XLIFF.php
@@ -0,0 +1,505 @@
+
+ * @version $Revision: 1.8 $ $Date: 2005/12/17 06:11:28 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the MessageSource class file.
+ */
+require_once(dirname(__FILE__).'/MessageSource.php');
+
+/**
+ * MessageSource_XLIFF class.
+ *
+ * Using XML XLIFF format as the message source for translation.
+ * Details and example of XLIFF can be found in the following URLs.
+ *
+ * # http://www.opentag.com/xliff.htm
+ * # http://www-106.ibm.com/developerworks/xml/library/x-localis2/
+ *
+ * See the MessageSource::factory() method to instantiate this class.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 16:18:44 EST 2004
+ * @package System.I18N.core
+ */
+class MessageSource_XLIFF extends MessageSource
+{
+ /**
+ * Message data filename extension.
+ * @var string
+ */
+ protected $dataExt = '.xml';
+
+ /**
+ * Separator between culture name and source.
+ * @var string
+ */
+ protected $dataSeparator = '.';
+
+ /**
+ * Constructor.
+ * @param string the directory where the messages are stored.
+ * @see MessageSource::factory();
+ */
+ function __construct($source)
+ {
+ $this->source = (string)$source;
+ }
+
+ /**
+ * Load the messages from a XLIFF file.
+ * @param string XLIFF file.
+ * @return array of messages.
+ */
+ protected function &loadData($filename)
+ {
+ //load it.
+
+ $XML = simplexml_load_file($filename);
+
+ if(!$XML) return false;
+
+ $translationUnit = $XML->xpath('//trans-unit');
+
+ $translations = array();
+
+ foreach($translationUnit as $unit)
+ {
+ $source = (string)$unit->source;
+ $translations[$source][] = (string)$unit->target;
+ $translations[$source][]= (string)$unit['id'];
+ $translations[$source][]= (string)$unit->note;
+ }
+
+ return $translations;
+ }
+
+ /**
+ * Get the last modified unix-time for this particular catalogue+variant.
+ * Just use the file modified time.
+ * @param string catalogue+variant
+ * @return int last modified in unix-time format.
+ */
+ protected function getLastModified($source)
+ {
+ if(is_file($source))
+ return filemtime($source);
+ else
+ return 0;
+ }
+
+ /**
+ * Get the XLIFF file for a specific message catalogue and cultural
+ * vairant.
+ * @param string message catalogue
+ * @return string full path to the XLIFF file.
+ */
+ protected function getSource($variant)
+ {
+ return $this->source.'/'.$variant;
+ }
+
+ /**
+ * Determin if the XLIFF file source is valid.
+ * @param string XLIFF file
+ * @return boolean true if valid, false otherwise.
+ */
+ protected function isValidSource($source)
+ {
+ return is_file($source);
+ }
+
+ /**
+ * Get all the variants of a particular catalogue.
+ * @param string catalogue name
+ * @return array list of all variants for this catalogue.
+ */
+ protected function getCatalogueList($catalogue)
+ {
+ $variants = explode('_',$this->culture);
+ $source = $catalogue.$this->dataExt;
+
+ $catalogues = array($source);
+
+ $variant = null;
+
+ for($i = 0; $i < count($variants); $i++)
+ {
+ if(strlen($variants[$i])>0)
+ {
+ $variant .= ($variant)?'_'.$variants[$i]:$variants[$i];
+ $catalogues[] = $catalogue.$this->dataSeparator.
+ $variant.$this->dataExt;
+ }
+ }
+
+ $byDir = $this->getCatalogueByDir($catalogue);
+ $catalogues = array_merge($byDir,array_reverse($catalogues));
+ return $catalogues;
+ }
+
+ /**
+ * Traverse through the directory structure to find the catalogues.
+ * This should only be called by getCatalogueList()
+ * @param string a particular catalogue.
+ * @return array a list of catalogues.
+ * @see getCatalogueList()
+ */
+ private function getCatalogueByDir($catalogue)
+ {
+ $variants = explode('_',$this->culture);
+ $catalogues = array();
+
+ $variant = null;
+
+ for($i = 0; $i < count($variants); $i++)
+ {
+ if(strlen($variants[$i])>0)
+ {
+ $variant .= ($variant)?'_'.$variants[$i]:$variants[$i];
+ $catalogues[] = $variant.'/'.$catalogue.$this->dataExt;
+ }
+ }
+ return array_reverse($catalogues);
+ }
+
+ /**
+ * Returns a list of catalogue and its culture ID.
+ * E.g. array('messages','en_AU')
+ * @return array list of catalogues
+ * @see getCatalogues()
+ */
+ public function catalogues()
+ {
+ return $this->getCatalogues();
+ }
+
+ /**
+ * Returns a list of catalogue and its culture ID. This takes care
+ * of directory structures.
+ * E.g. array('messages','en_AU')
+ * @return array list of catalogues
+ */
+ protected function getCatalogues($dir=null,$variant=null)
+ {
+ $dir = $dir?$dir:$this->source;
+ $files = scandir($dir);
+
+ $catalogue = array();
+
+ foreach($files as $file)
+ {
+ if(is_dir($dir.'/'.$file)
+ && preg_match('/^[a-z]{2}(_[A-Z]{2,3})?$/',$file))
+ {
+ $catalogue = array_merge($catalogue,
+ $this->getCatalogues($dir.'/'.$file, $file));
+ }
+
+ $pos = strpos($file,$this->dataExt);
+ if($pos >0
+ && substr($file,-1*strlen($this->dataExt)) == $this->dataExt)
+ {
+ $name = substr($file,0,$pos);
+ $dot = strrpos($name,$this->dataSeparator);
+ $culture = $variant;
+ $cat = $name;
+ if(is_int($dot))
+ {
+ $culture = substr($name, $dot+1,strlen($name));
+ $cat = substr($name,0,$dot);
+ }
+ $details[0] = $cat;
+ $details[1] = $culture;
+
+
+ $catalogue[] = $details;
+ }
+ }
+ sort($catalogue);
+ return $catalogue;
+ }
+
+ /**
+ * Get the variant for a catalogue depending on the current culture.
+ * @param string catalogue
+ * @return string the variant.
+ * @see save()
+ * @see update()
+ * @see delete()
+ */
+ private function getVariants($catalogue='messages')
+ {
+ if(is_null($catalogue))
+ $catalogue = 'messages';
+
+ foreach($this->getCatalogueList($catalogue) as $variant)
+ {
+ $file = $this->getSource($variant);
+ if(is_file($file))
+ return array($variant, $file);
+ }
+ return false;
+ }
+
+ /**
+ * Save the list of untranslated blocks to the translation source.
+ * If the translation was not found, you should add those
+ * strings to the translation source via the append() method.
+ * @param string the catalogue to add to
+ * @return boolean true if saved successfuly, false otherwise.
+ */
+ public function save($catalogue='messages')
+ {
+ $messages = $this->untranslated;
+ if(count($messages) <= 0) return false;
+
+ $variants = $this->getVariants($catalogue);
+
+ if($variants)
+ list($variant, $filename) = $variants;
+ else
+ list($variant, $filename) = $this->createMessageTemplate($catalogue);
+
+ if(is_writable($filename) == false)
+ throw new TMessageSourceIOException("Unable to save to file {$filename}, file must be writable.");
+
+ //create a new dom, import the existing xml
+ $dom = DOMDocument::load($filename);
+
+ //find the body element
+ $xpath = new DomXPath($dom);
+ $body = $xpath->query('//body')->item(0);
+
+ $count = $xpath->query('//trans-unit')->length;
+
+ //for each message add it to the XML file using DOM
+ foreach($messages as $message)
+ {
+ $unit = $dom->createElement('trans-unit');
+ $unit->setAttribute('id',++$count);
+
+ $source = $dom->createElement('source', $message);
+ $target = $dom->createElement('target','');
+
+ $unit->appendChild($dom->createTextNode("\n"));
+ $unit->appendChild($source);
+ $unit->appendChild($dom->createTextNode("\n"));
+ $unit->appendChild($target);
+ $unit->appendChild($dom->createTextNode("\n"));
+
+ $body->appendChild($dom->createTextNode("\n"));
+ $body->appendChild($unit);
+ $body->appendChild($dom->createTextNode("\n"));
+ }
+
+
+ $fileNode = $xpath->query('//file')->item(0);
+ $fileNode->setAttribute('date', @date('Y-m-d\TH:i:s\Z'));
+
+ //save it and clear the cache for this variant
+ $dom->save($filename);
+ if(!empty($this->cache))
+ $this->cache->clean($variant, $this->culture);
+
+ return true;
+ }
+
+ /**
+ * Update the translation.
+ * @param string the source string.
+ * @param string the new translation string.
+ * @param string comments
+ * @param string the catalogue to save to.
+ * @return boolean true if translation was updated, false otherwise.
+ */
+ public function update($text, $target, $comments, $catalogue='messages')
+ {
+ $variants = $this->getVariants($catalogue);
+ if($variants)
+ list($variant, $filename) = $variants;
+ else
+ return false;
+
+ if(is_writable($filename) == false)
+ throw new TMessageSourceIOException("Unable to update file {$filename}, file must be writable.");
+
+ //create a new dom, import the existing xml
+ $dom = DOMDocument::load($filename);
+
+ //find the body element
+ $xpath = new DomXPath($dom);
+ $units = $xpath->query('//trans-unit');
+
+ //for each of the existin units
+ foreach($units as $unit)
+ {
+ $found = false;
+ $targetted = false;
+ $commented = false;
+
+ //in each unit, need to find the source, target and comment nodes
+ //it will assume that the source is before the target.
+ foreach($unit->childNodes as $node)
+ {
+ //source node
+ if($node->nodeName == 'source'
+ && $node->firstChild->wholeText == $text)
+ {
+ $found = true;
+ }
+
+ //found source, get the target and notes
+ if($found)
+ {
+ //set the new translated string
+ if($node->nodeName == 'target')
+ {
+ $node->nodeValue = $target;
+ $targetted = true;
+ }
+ //set the notes
+ if(!empty($comments) && $node->nodeName == 'note')
+ {
+ $node->nodeValue = $comments;
+ $commented = true;
+ }
+ }
+ }
+
+ //append a target
+ if($found && !$targetted)
+ $unit->appendChild($dom->createElement('target',$target));
+
+ //append a note
+ if($found && !$commented && !empty($comments))
+ $unit->appendChild($dom->createElement('note',$comments));
+
+ //finished searching
+ if($found) break;
+ }
+
+ $fileNode = $xpath->query('//file')->item(0);
+ $fileNode->setAttribute('date', @date('Y-m-d\TH:i:s\Z'));
+
+ if($dom->save($filename) >0)
+ {
+ if(!empty($this->cache))
+ $this->cache->clean($variant, $this->culture);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Delete a particular message from the specified catalogue.
+ * @param string the source message to delete.
+ * @param string the catalogue to delete from.
+ * @return boolean true if deleted, false otherwise.
+ */
+ public function delete($message, $catalogue='messages')
+ {
+ $variants = $this->getVariants($catalogue);
+ if($variants)
+ list($variant, $filename) = $variants;
+ else
+ return false;
+
+ if(is_writable($filename) == false)
+ throw new TMessageSourceIOException("Unable to modify file {$filename}, file must be writable.");
+
+ //create a new dom, import the existing xml
+ $dom = DOMDocument::load($filename);
+
+ //find the body element
+ $xpath = new DomXPath($dom);
+ $units = $xpath->query('//trans-unit');
+
+ //for each of the existin units
+ foreach($units as $unit)
+ {
+ //in each unit, need to find the source, target and comment nodes
+ //it will assume that the source is before the target.
+ foreach($unit->childNodes as $node)
+ {
+ //source node
+ if($node->nodeName == 'source'
+ && $node->firstChild->wholeText == $message)
+ {
+
+ //we found it, remove and save the xml file.
+ $unit->parentNode->removeChild($unit);
+
+ $fileNode = $xpath->query('//file')->item(0);
+ $fileNode->setAttribute('date', @date('Y-m-d\TH:i:s\Z'));
+
+ if($dom->save($filename) >0)
+ {
+ if(!empty($this->cache))
+ $this->cache->clean($variant, $this->culture);
+ return true;
+ }
+ else return false;
+
+ }
+ }
+
+ }
+
+ return false;
+ }
+
+ protected function createMessageTemplate($catalogue)
+ {
+ if(is_null($catalogue))
+ $catalogue = 'messages';
+ $variants = $this->getCatalogueList($catalogue);
+ $variant = array_shift($variants);
+ $file = $this->getSource($variant);
+ $dir = dirname($file);
+ if(!is_dir($dir)) @mkdir($dir);
+ if(!is_dir($dir))
+ throw new TException("Unable to create directory $dir");
+ file_put_contents($file, $this->getTemplate($catalogue));
+ return array($variant, $file);
+ }
+
+ protected function getTemplate($catalogue)
+ {
+ $date = @date('c');
+$xml = <<
+
+
+
+
+
+
+EOD;
+ return $xml;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/MessageSource_gettext.php b/framework/I18N/core/MessageSource_gettext.php
new file mode 100644
index 00000000..5c6d05af
--- /dev/null
+++ b/framework/I18N/core/MessageSource_gettext.php
@@ -0,0 +1,451 @@
+
+ * @version $Revision: 1.7 $ $Date: 2005/12/17 06:11:28 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the MessageSource class file.
+ */
+require_once(dirname(__FILE__).'/MessageSource.php');
+
+/**
+ * Get the Gettext class.
+ */
+require_once(dirname(__FILE__).'/Gettext/TGettext.php');
+
+/**
+ * MessageSource_gettext class.
+ *
+ * Using Gettext MO format as the message source for translation.
+ * The gettext classes are based on PEAR's gettext MO and PO classes.
+ *
+ * See the MessageSource::factory() method to instantiate this class.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 24 16:18:44 EST 2004
+ * @package System.I18N.core
+ */
+class MessageSource_gettext extends MessageSource
+{
+ /**
+ * Message data filename extension.
+ * @var string
+ */
+ protected $dataExt = '.mo';
+
+ /**
+ * PO data filename extension
+ * @var string
+ */
+ protected $poExt = '.po';
+
+ /**
+ * Separator between culture name and source.
+ * @var string
+ */
+ protected $dataSeparator = '.';
+
+ function __construct($source)
+ {
+ $this->source = (string)$source;
+ }
+
+
+ /**
+ * Load the messages from a MO file.
+ * @param string MO file.
+ * @return array of messages.
+ */
+ protected function &loadData($filename)
+ {
+ $mo = TGettext::factory('MO',$filename);
+ $mo->load();
+ $result = $mo->toArray();
+
+ $results = array();
+ $count=0;
+ foreach($result['strings'] as $source => $target)
+ {
+ $results[$source][] = $target; //target
+ $results[$source][] = $count++; //id
+ $results[$source][] = ''; //comments
+ }
+ return $results;
+ }
+
+ /**
+ * Determin if the MO file source is valid.
+ * @param string MO file
+ * @return boolean true if valid, false otherwise.
+ */
+ protected function isValidSource($filename)
+ {
+ return is_file($filename);
+ }
+
+ /**
+ * Get the MO file for a specific message catalogue and cultural
+ * vairant.
+ * @param string message catalogue
+ * @return string full path to the MO file.
+ */
+ protected function getSource($variant)
+ {
+ return $this->source.'/'.$variant;
+ }
+
+ /**
+ * Get the last modified unix-time for this particular catalogue+variant.
+ * Just use the file modified time.
+ * @param string catalogue+variant
+ * @return int last modified in unix-time format.
+ */
+ protected function getLastModified($source)
+ {
+ if(is_file($source))
+ return filemtime($source);
+ else
+ return 0;
+ }
+
+ /**
+ * Get all the variants of a particular catalogue.
+ * @param string catalogue name
+ * @return array list of all variants for this catalogue.
+ */
+ protected function getCatalogueList($catalogue)
+ {
+ $variants = explode('_',$this->culture);
+ $source = $catalogue.$this->dataExt;
+
+ $catalogues = array($source);
+
+ $variant = null;
+
+ for($i = 0; $i < count($variants); $i++)
+ {
+ if(strlen($variants[$i])>0)
+ {
+ $variant .= ($variant)?'_'.$variants[$i]:$variants[$i];
+ $catalogues[] = $catalogue.$this->dataSeparator.
+ $variant.$this->dataExt;
+ }
+ }
+ $byDir = $this->getCatalogueByDir($catalogue);
+ $catalogues = array_merge($byDir,array_reverse($catalogues));
+ return $catalogues;
+ }
+
+
+ /**
+ * Traverse through the directory structure to find the catalogues.
+ * This should only be called by getCatalogueList()
+ * @param string a particular catalogue.
+ * @return array a list of catalogues.
+ * @see getCatalogueList()
+ */
+ private function getCatalogueByDir($catalogue)
+ {
+ $variants = explode('_',$this->culture);
+ $catalogues = array();
+
+ $variant = null;
+
+ for($i = 0; $i < count($variants); $i++)
+ {
+ if(strlen($variants[$i])>0)
+ {
+ $variant .= ($variant)?'_'.$variants[$i]:$variants[$i];
+ $catalogues[] = $variant.'/'.$catalogue.$this->dataExt;
+ }
+ }
+ return array_reverse($catalogues);
+ }
+
+ /**
+ * Get the variant for a catalogue depending on the current culture.
+ * @param string catalogue
+ * @return string the variant.
+ * @see save()
+ * @see update()
+ * @see delete()
+ */
+ private function getVariants($catalogue='messages')
+ {
+ if(is_null($catalogue))
+ $catalogue = 'messages';
+
+ foreach($this->getCatalogueList($catalogue) as $variant)
+ {
+ $file = $this->getSource($variant);
+ $po = $this->getPOFile($file);
+ if(is_file($file) || is_file($po))
+ return array($variant, $file, $po);
+ }
+ return false;
+ }
+
+ private function getPOFile($MOFile)
+ {
+ $filebase = substr($MOFile, 0, strlen($MOFile)-strlen($this->dataExt));
+ return $filebase.$this->poExt;
+ }
+
+ /**
+ * Save the list of untranslated blocks to the translation source.
+ * If the translation was not found, you should add those
+ * strings to the translation source via the append() method.
+ * @param string the catalogue to add to
+ * @return boolean true if saved successfuly, false otherwise.
+ */
+ function save($catalogue='messages')
+ {
+ $messages = $this->untranslated;
+
+ if(count($messages) <= 0) return false;
+
+ $variants = $this->getVariants($catalogue);
+
+ if($variants)
+ list($variant, $MOFile, $POFile) = $variants;
+ else
+ list($variant, $MOFile, $POFile) = $this->createMessageTemplate($catalogue);
+
+ if(is_writable($MOFile) == false)
+ throw new TMessageSourceIOException("Unable to save to file {$MOFile}, file must be writable.");
+ if(is_writable($POFile) == false)
+ throw new TMessageSourceIOException("Unable to save to file {$POFile}, file must be writable.");
+
+ //set the strings as untranslated.
+ $strings = array();
+ foreach($messages as $message)
+ $strings[$message] = '';
+
+ //load the PO
+ $po = TGettext::factory('PO',$POFile);
+ $po->load();
+ $result = $po->toArray();
+
+ $existing = count($result['strings']);
+
+ //add to strings to the existing message list
+ $result['strings'] = array_merge($result['strings'],$strings);
+
+ $new = count($result['strings']);
+
+ if($new > $existing)
+ {
+ //change the date 2004-12-25 12:26
+ $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s');
+
+ $po->fromArray($result);
+ $mo = $po->toMO();
+ if($po->save() && $mo->save($MOFile))
+ {
+ if(!empty($this->cache))
+ $this->cache->clean($variant, $this->culture);
+ return true;
+ }
+ else
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Delete a particular message from the specified catalogue.
+ * @param string the source message to delete.
+ * @param string the catalogue to delete from.
+ * @return boolean true if deleted, false otherwise.
+ */
+ function delete($message, $catalogue='messages')
+ {
+ $variants = $this->getVariants($catalogue);
+ if($variants)
+ list($variant, $MOFile, $POFile) = $variants;
+ else
+ return false;
+
+ if(is_writable($MOFile) == false)
+ throw new TMessageSourceIOException("Unable to modify file {$MOFile}, file must be writable.");
+ if(is_writable($POFile) == false)
+ throw new TMessageSourceIOException("Unable to modify file {$POFile}, file must be writable.");
+
+ $po = TGettext::factory('PO',$POFile);
+ $po->load();
+ $result = $po->toArray();
+
+ foreach($result['strings'] as $string => $value)
+ {
+ if($string == $message)
+ {
+ $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s');
+ unset($result['strings'][$string]);
+
+ $po->fromArray($result);
+ $mo = $po->toMO();
+ if($po->save() && $mo->save($MOFile))
+ {
+ if(!empty($this->cache))
+ $this->cache->clean($variant, $this->culture);
+ return true;
+ }
+ else
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Update the translation.
+ * @param string the source string.
+ * @param string the new translation string.
+ * @param string comments
+ * @param string the catalogue of the translation.
+ * @return boolean true if translation was updated, false otherwise.
+ */
+ function update($text, $target, $comments, $catalogue='messages')
+ {
+ $variants = $this->getVariants($catalogue);
+ if($variants)
+ list($variant, $MOFile, $POFile) = $variants;
+ else
+ return false;
+
+ if(is_writable($MOFile) == false)
+ throw new TMessageSourceIOException("Unable to update file {$MOFile}, file must be writable.");
+ if(is_writable($POFile) == false)
+ throw new TMessageSourceIOException("Unable to update file {$POFile}, file must be writable.");
+
+
+ $po = TGettext::factory('PO',$POFile);
+ $po->load();
+ $result = $po->toArray();
+
+ foreach($result['strings'] as $string => $value)
+ {
+ if($string == $text)
+ {
+ $result['strings'][$string] = $target;
+ $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s');
+
+ $po->fromArray($result);
+ $mo = $po->toMO();
+
+ if($po->save() && $mo->save($MOFile))
+ {
+ if(!empty($this->cache))
+ $this->cache->clean($variant, $this->culture);
+ return true;
+ }
+ else
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Returns a list of catalogue as key and all it variants as value.
+ * @return array list of catalogues
+ */
+ function catalogues()
+ {
+ return $this->getCatalogues();
+ }
+
+ /**
+ * Returns a list of catalogue and its culture ID. This takes care
+ * of directory structures.
+ * E.g. array('messages','en_AU')
+ * @return array list of catalogues
+ */
+ protected function getCatalogues($dir=null,$variant=null)
+ {
+ $dir = $dir?$dir:$this->source;
+ $files = scandir($dir);
+
+ $catalogue = array();
+
+ foreach($files as $file)
+ {
+ if(is_dir($dir.'/'.$file)
+ && preg_match('/^[a-z]{2}(_[A-Z]{2,3})?$/',$file))
+ {
+
+ $catalogue = array_merge($catalogue,
+ $this->getCatalogues($dir.'/'.$file, $file));
+ }
+
+ $pos = strpos($file,$this->dataExt);
+
+ if($pos >0
+ && substr($file,-1*strlen($this->dataExt)) == $this->dataExt)
+ {
+ $name = substr($file,0,$pos);
+ $dot = strrpos($name,$this->dataSeparator);
+ $culture = $variant;
+ $cat = $name;
+ if(is_int($dot))
+ {
+ $culture = substr($name, $dot+1,strlen($name));
+ $cat = substr($name,0,$dot);
+ }
+ $details[0] = $cat;
+ $details[1] = $culture;
+
+
+ $catalogue[] = $details;
+ }
+ }
+ sort($catalogue);
+
+ return $catalogue;
+ }
+
+ protected function createMessageTemplate($catalogue)
+ {
+ if(is_null($catalogue))
+ $catalogue = 'messages';
+ $variants = $this->getCatalogueList($catalogue);
+ $variant = array_shift($variants);
+ $mo_file = $this->getSource($variant);
+ $po_file = $this->getPOFile($mo_file);
+
+ $dir = dirname($mo_file);
+ if(!is_dir($dir)) @mkdir($dir);
+ if(!is_dir($dir))
+ throw new TException("Unable to create directory $dir");
+
+ $po = TGettext::factory('PO',$po_file);
+ $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s');
+ $result['strings'] = array();
+
+ $po->fromArray($result);
+ $mo = $po->toMO();
+ if($po->save() && $mo->save($mo_file))
+ return array($variant, $mo_file, $po_file);
+ else
+ throw TException("Unable to create file $po_file and $mo_file");
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/NumberFormat.php b/framework/I18N/core/NumberFormat.php
new file mode 100644
index 00000000..bde87e65
--- /dev/null
+++ b/framework/I18N/core/NumberFormat.php
@@ -0,0 +1,297 @@
+
+ * @version $Revision: 1.6 $ $Date: 2005/12/20 09:32:42 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the NumberFormatInfo class file.
+ */
+require_once(dirname(__FILE__).'/NumberFormatInfo.php');
+
+
+/**
+ * Get the encoding utilities
+ */
+require_once(dirname(__FILE__).'/util.php');
+
+
+/**
+ * NumberFormat class.
+ *
+ * NumberFormat formats decimal numbers in any locale. The decimal
+ * number is formatted according to a particular pattern. These
+ * patterns can arise from the NumberFormatInfo object which is
+ * culturally sensitive. The NumberFormat class can be instantiated in
+ * many ways. E.g.
+ *
+ *
+ * //create a invariant number formatter.
+ * $formatter = new NumberFormat();
+ *
+ * //create a number format for the french language locale.
+ * $fr = new NumberFormat('fr');
+ *
+ * //create a number format base on a NumberFormatInfo instance $numberInfo.
+ * $format = new NumberFormat($numberInfo);
+ *
+ *
+ * A normal decimal number can also be displayed as a currency
+ * or as a percentage. For example
+ *
+ * $format->format(1234.5); //Decimal number "1234.5"
+ * $format->format(1234.5,'c'); //Default currency "$1234.50"
+ * $format->format(0.25, 'p') //Percent "25%"
+ *
+ *
+ * Currency is formated using the localized currency pattern. For example
+ * to format the number as Japanese Yen:
+ *
+ * $ja = new NumberFormat('ja_JP');
+ *
+ * //Japanese currency pattern, and using Japanese Yen symbol
+ * $ja->format(123.14,'c','JPY'); //ï¿?123 (Yen 123)
+ *
+ * For each culture, the symbol for each currency may be different.
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Fri Dec 10 18:10:20 EST 2004
+ * @package System.I18N.core
+ */
+class NumberFormat
+{
+
+ /**
+ * The DateTimeFormatInfo, containing culture specific patterns and names.
+ * @var DateTimeFormatInfo
+ */
+ protected $formatInfo;
+
+ /**
+ * Create a new number format instance. The constructor can be instantiated
+ * with a string that represent a culture/locale. Similarly, passing
+ * a CultureInfo or NumberFormatInfo instance will instantiated a instance
+ * for that particular culture.
+ * @param mixed either null, a CultureInfo, a NumberFormatInfo, or string
+ * @return NumberFormat
+ */
+ function __construct($formatInfo=null)
+ {
+ if(is_null($formatInfo))
+ $this->formatInfo = NumberFormatInfo::getInvariantInfo();
+ else if($formatInfo instanceof CultureInfo)
+ $this->formatInfo = $formatInfo->NumberFormat;
+ else if($formatInfo instanceof NumberFormatInfo)
+ $this->formatInfo = $formatInfo;
+ else
+ $this->formatInfo =
+ NumberFormatInfo::getInstance($formatInfo);
+ }
+
+ /**
+ * For the number for a certain pattern. The valid patterns are
+ * 'c', 'd', 'e', 'p' or a custom pattern, such as "#.000" for
+ * 3 decimal places.
+ * @param mixed the number to format.
+ * @param string the format pattern, either, 'c', 'd', 'e', 'p'
+ * or a custom pattern. E.g. "#.000" will format the number to
+ * 3 decimal places.
+ * @param string 3-letter ISO 4217 code. For example, the code
+ * "USD" represents the US Dollar and "EUR" represents the Euro currency.
+ * @return string formatted number string
+ */
+ function format($number, $pattern='d', $currency='USD', $charset='UTF-8')
+ {
+ $this->setPattern($pattern);
+
+ if(strtolower($pattern) == 'p')
+ $number = $number * 100;
+
+ $string = (string)$number;
+
+
+ $decimal = $this->formatDecimal($string);
+ $integer = $this->formatInteger(abs($number));
+
+ if(strlen($decimal)>0)
+ $result = $integer.$decimal;
+ else
+ $result = $integer;
+
+ //get the suffix
+ if($number > 0)
+ $suffix = $this->formatInfo->PositivePattern;
+ else if($number < 0)
+ $suffix = $this->formatInfo->NegativePattern;
+ else
+ $suffix = array("","");
+
+ //append and prepend suffix
+ $result = $suffix[0].$result.$suffix[1];
+
+ //replace currency sign
+ $symbol = @$this->formatInfo->getCurrencySymbol($currency);
+ if(is_null($symbol))
+ $symbol = $currency;
+
+ $result = str_replace('¤',$symbol, $result);
+
+ return I18N_toEncoding($result, $charset);
+ }
+
+ /**
+ * For the integer, perform groupings and string padding.
+ * @param string the decimal number in string form.
+ * @return string formatted integer string with grouping
+ */
+ protected function formatInteger($string)
+ {
+ $string = (string)$string;
+ $dp = strpos($string, '.');
+
+ if(is_int($dp))
+ $string = substr($string, 0, $dp);
+
+ $integer = '';
+
+ $len = strlen($string);
+
+ $groupSeparator = $this->formatInfo->GroupSeparator;
+ $groupSize = $this->formatInfo->GroupSizes;
+
+ $firstGroup = true;
+ $multiGroup = is_int($groupSize[1]);
+ $count = 0;
+
+ if(is_int($groupSize[0]))
+ {
+ //now for the integer groupings
+ for($i=0; $i<$len; $i++)
+ {
+ $char = $string{$len-$i-1};
+
+ if($multiGroup && $count == 0)
+ {
+ if($i != 0 && $i%$groupSize[0] == 0)
+ {
+ $integer = $groupSeparator . $integer;
+ $count++;
+ }
+ }
+ else if($multiGroup && $count >= 1)
+ {
+ if($i != 0 && ($i-$groupSize[0])%$groupSize[1] == 0)
+ {
+ $integer = $groupSeparator . $integer;
+ $count++;
+ }
+ }
+ else
+ {
+ if($i != 0 && $i%$groupSize[0] == 0)
+ {
+ $integer = $groupSeparator . $integer;
+ $count++;
+ }
+ }
+
+ $integer = $char . $integer;
+ }
+ }
+ else
+ $integer = $string;
+
+ return $integer;
+ }
+
+ /**
+ * Format the decimal places.
+ * @param string the decimal number in string form.
+ * @return string formatted decimal places.
+ */
+ protected function formatDecimal($string)
+ {
+ $dp = strpos($string, '.');
+ $decimal = '';
+
+ $decimalDigits = $this->formatInfo->DecimalDigits;
+ $decimalSeparator = $this->formatInfo->DecimalSeparator;
+
+ if(is_int($dp))
+ {
+ if($decimalDigits == -1)
+ {
+ $decimal = substr($string, $dp+1);
+ }
+ else if(is_int($decimalDigits))
+ {
+ $float = round((float)$string, $decimalDigits);
+ if(strpos((string)$float, '.') === false)
+ {
+ $decimal = str_pad($decimal,$decimalDigits,'0');
+ }
+ else
+ {
+ $decimal = substr($float, strpos($float,'.')+1);
+ if(strlen($decimal)<$decimalDigits)
+ $decimal = str_pad($decimal,$decimalDigits,'0');
+ }
+ }
+ else
+ return $decimal;
+
+ return $decimalSeparator.$decimal;
+ }
+ else if ($decimalDigits > 0)
+ return $decimalSeparator.str_pad($decimal,$decimalDigits,'0');
+
+ return $decimal;
+ }
+
+ /**
+ * Set the pattern to format against. The default patterns
+ * are retrieved from the NumberFormatInfo instance.
+ * @param string the requested patterns.
+ * @return string a number format pattern.
+ */
+ protected function setPattern($pattern)
+ {
+ switch($pattern)
+ {
+ case 'c':
+ case 'C':
+ $this->formatInfo->setPattern(NumberFormatInfo::CURRENCY);
+ break;
+ case 'd':
+ case 'D':
+ $this->formatInfo->setPattern(NumberFormatInfo::DECIMAL);
+ break;
+ case 'e':
+ case 'E':
+ $this->formatInfo->setPattern(NumberFormatInfo::SCIENTIFIC);
+ break;
+ case 'p':
+ case 'P':
+ $this->formatInfo->setPattern(NumberFormatInfo::PERCENTAGE);
+ break;
+ default:
+ $this->formatInfo->setPattern($pattern);
+ break;
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/NumberFormatInfo.php b/framework/I18N/core/NumberFormatInfo.php
new file mode 100644
index 00000000..15b9ee5d
--- /dev/null
+++ b/framework/I18N/core/NumberFormatInfo.php
@@ -0,0 +1,633 @@
+
+ * @version $Revision: 1.3 $ $Date: 2005/08/04 05:27:19 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the CultureInfo class file.
+ */
+require_once(dirname(__FILE__).'/CultureInfo.php');
+
+/**
+ * NumberFormatInfo class
+ *
+ * Defines how numeric values are formatted and displayed,
+ * depending on the culture. Numeric values are formatted using
+ * standard or custom patterns stored in the properties of a
+ * NumberFormatInfo.
+ *
+ * This class contains information, such as currency, decimal
+ * separators, and other numeric symbols.
+ *
+ * To create a NumberFormatInfo for a specific culture,
+ * create a CultureInfo for that culture and retrieve the
+ * CultureInfo->NumberFormat property. Or use
+ * NumberFormatInfo::getInstance($culture).
+ * To create a NumberFormatInfo for the invariant culture, use the
+ * InvariantInfo::getInvariantInfo().
+ *
+ *
+ * @author Xiang Wei Zhuo
+ * @version v1.0, last update on Sun Dec 05 14:48:26 EST 2004
+ * @package System.I18N.core
+ */
+class NumberFormatInfo
+{
+
+ /**
+ * ICU number formatting data.
+ * @var array
+ */
+ private $data = array();
+
+ /**
+ * A list of properties that are accessable/writable.
+ * @var array
+ */
+ protected $properties = array();
+
+ /**
+ * The number pattern.
+ * @var array
+ */
+ protected $pattern = array();
+
+ const DECIMAL = 0;
+ const CURRENCY = 1;
+ const PERCENTAGE = 2;
+ const SCIENTIFIC = 3;
+
+ /**
+ * Allow functions that begins with 'set' to be called directly
+ * as an attribute/property to retrieve the value.
+ * @return mixed
+ */
+ function __get($name)
+ {
+ $getProperty = 'get'.$name;
+ if(in_array($getProperty, $this->properties))
+ return $this->$getProperty();
+ else
+ throw new Exception('Property '.$name.' does not exists.');
+ }
+
+ /**
+ * Allow functions that begins with 'set' to be called directly
+ * as an attribute/property to set the value.
+ */
+ function __set($name, $value)
+ {
+ $setProperty = 'set'.$name;
+ if(in_array($setProperty, $this->properties))
+ $this->$setProperty($value);
+ else
+ throw new Exception('Property '.$name.' can not be set.');
+ }
+
+ /**
+ * Initializes a new writable instance of the NumberFormatInfo class
+ * that is dependent on the ICU data for number, decimal, and currency
+ * formatting information. N.B.You should not initialize this
+ * class directly unless you know what you are doing. Please use use
+ * NumberFormatInfo::getInstance() to create an instance.
+ * @param array ICU data for date time formatting.
+ * @see getInstance()
+ */
+ function __construct($data=array(), $type=NumberFormatInfo::DECIMAL)
+ {
+ $this->properties = get_class_methods($this);
+
+ if(empty($data))
+ throw new Exception('Please provide the ICU data to initialize.');
+
+ $this->data = $data;
+
+ $this->setPattern($type);
+ }
+
+ /**
+ * Set the pattern for a specific number pattern. The validate patterns
+ * NumberFormatInfo::DECIMAL, NumberFormatInfo::CURRENCY,
+ * NumberFormatInfo::PERCENTAGE, or NumberFormatInfo::SCIENTIFIC
+ * @param int pattern type.
+ */
+ function setPattern($type=NumberFormatInfo::DECIMAL)
+ {
+ if(is_int($type))
+ $this->pattern =
+ $this->parsePattern($this->data['NumberPatterns'][$type]);
+ else
+ $this->pattern = $this->parsePattern($type);
+
+ $this->pattern['negInfty'] =
+ $this->data['NumberElements'][6].
+ $this->data['NumberElements'][9];
+
+ $this->pattern['posInfty'] =
+ $this->data['NumberElements'][11].
+ $this->data['NumberElements'][9];
+ }
+
+ function getPattern()
+ {
+ return $this->pattern;
+ }
+
+ /**
+ * Gets the default NumberFormatInfo that is culture-independent
+ * (invariant).
+ * @return NumberFormatInfo default NumberFormatInfo.
+ */
+ public function getInvariantInfo($type=NumberFormatInfo::DECIMAL)
+ {
+ static $invariant;
+ if(is_null($invariant))
+ {
+ $culture = CultureInfo::getInvariantCulture();
+ $invariant = $culture->NumberFormat;
+ $invariant->setPattern($type);
+ }
+ return $invariant;
+ }
+
+ /**
+ * Returns the NumberFormatInfo associated with the specified culture.
+ * @param CultureInfo the culture that gets the NumberFormat property.
+ * @param int the number formatting type, it should be
+ * NumberFormatInfo::DECIMAL, NumberFormatInfo::CURRENCY,
+ * NumberFormatInfo::PERCENTAGE, or NumberFormatInfo::SCIENTIFIC
+ * @return NumberFormatInfo NumberFormatInfo for the specified
+ * culture.
+ * @see getCurrencyInstance();
+ * @see getPercentageInstance();
+ * @see getScientificInstance();
+ */
+ public static function getInstance($culture=null,
+ $type=NumberFormatInfo::DECIMAL)
+ {
+ if ($culture instanceof CultureInfo)
+ {
+ $formatInfo = $culture->NumberFormat;
+ $formatInfo->setPattern($type);
+ return $formatInfo;
+ }
+ else if(is_string($culture))
+ {
+ $cultureInfo = new CultureInfo($culture);
+ $formatInfo = $cultureInfo->NumberFormat;
+ $formatInfo->setPattern($type);
+ return $formatInfo;
+ }
+ else
+ {
+ $cultureInfo = new CultureInfo();
+ $formatInfo = $cultureInfo->NumberFormat;
+ $formatInfo->setPattern($type);
+ return $formatInfo;
+ }
+ }
+
+ /**
+ * Returns the currency format info associated with the specified culture.
+ * @param CultureInfo the culture that gets the NumberFormat property.
+ * @return NumberFormatInfo NumberFormatInfo for the specified
+ * culture.
+ */
+ public static function getCurrencyInstance($culture=null)
+ {
+ return self::getInstance($culture, self::CURRENCY);
+ }
+
+ /**
+ * Returns the percentage format info associated with the specified culture.
+ * @param CultureInfo the culture that gets the NumberFormat property.
+ * @return NumberFormatInfo NumberFormatInfo for the specified
+ * culture.
+ */
+ public static function getPercentageInstance($culture=null)
+ {
+ return self::getInstance($culture, self::PERCENTAGE);
+ }
+
+ /**
+ * Returns the scientific format info associated with the specified culture.
+ * @param CultureInfo the culture that gets the NumberFormat property.
+ * @return NumberFormatInfo NumberFormatInfo for the specified
+ * culture.
+ */
+ public static function getScientificInstance($culture=null)
+ {
+ return self::getInstance($culture, self::SCIENTIFIC);
+ }
+
+ /**
+ * Parse the given pattern and return a list of known properties.
+ * @param string a number pattern.
+ * @return array list of pattern properties.
+ */
+ protected function parsePattern($pattern)
+ {
+ $pattern = explode(';',$pattern);
+
+ $negative = null;
+ if(count($pattern) > 1)
+ $negative = $pattern[1];
+ $pattern = $pattern[0];
+
+ $comma = ',';
+ $dot = '.';
+ $digit = '0';
+ $hash = '#';
+
+ //find the first group point, and decimal point
+ $groupPos1 = strrpos($pattern,$comma);
+ $decimalPos = strrpos($pattern,$dot);
+
+ $groupPos2 = false;
+ $groupSize1 = false;
+ $groupSize2 = false;
+ $decimalPoints = is_int($decimalPos)?-1:false;
+
+ $info['negPref'] = $this->data['NumberElements'][6];
+ $info['negPost'] = '';
+
+ $info['negative'] = $negative;
+ $info['positive'] = $pattern;
+
+ //find the negative prefix and postfix
+ if($negative)
+ {
+ $prefixPostfix = $this->getPrePostfix($negative);
+ $info['negPref'] = $prefixPostfix[0];
+ $info['negPost'] = $prefixPostfix[1];
+ }
+
+ $posfix = $this->getPrePostfix($pattern);
+ $info['posPref'] = $posfix[0];
+ $info['posPost'] = $posfix[1];
+
+ //var_dump($pattern);
+ //var_dump($decimalPos);
+ if(is_int($groupPos1))
+ {
+ //get the second group
+ $groupPos2 = strrpos(substr($pattern,0,$groupPos1),$comma);
+
+ //get the number of decimal digits
+ if(is_int($decimalPos))
+ {
+ $groupSize1 = $decimalPos - $groupPos1-1;
+
+ }
+ else
+ {
+ //no decimal point, so traverse from the back
+ //to find the groupsize 1.
+ for($i=strlen($pattern)-1; $i>=0; $i--)
+ {
+ if($pattern{$i} == $digit || $pattern{$i}==$hash)
+ {
+ $groupSize1 = $i - $groupPos1;
+ break;
+ }
+ }
+ }
+
+ //get the second group size
+ if(is_int($groupPos2))
+ $groupSize2 = $groupPos1 - $groupPos2-1;
+ }
+
+ if(is_int($decimalPos))
+ {
+ for($i=strlen($pattern)-1; $i>=0; $i--)
+ {
+ if($pattern{$i} == $dot) break;
+ if($pattern{$i} == $digit)
+ {
+ $decimalPoints = $i - $decimalPos;
+ break;
+ }
+ }
+ }
+
+ $info['groupPos1'] = $groupPos1;
+ $info['groupSize1'] = $groupSize1;
+ $info['groupPos2'] = $groupPos2;
+ $info['groupSize2'] = $groupSize2;
+ $info['decimalPos'] = $decimalPos;
+ $info['decimalPoints'] = $decimalPoints;
+ return $info;
+ }
+
+ /**
+ * Get the prefix and postfix of a pattern.
+ * @param string pattern
+ * @return array of prefix and postfix, array(prefix,postfix).
+ */
+ protected function getPrePostfix($pattern)
+ {
+ $regexp = '/[#,\.0]+/';
+ $result = preg_split($regexp, $pattern);
+ return array($result[0],$result[1]);
+ }
+
+
+ /**
+ * Indicates the number of decimal places.
+ * @return int number of decimal places.
+ */
+ function getDecimalDigits()
+ {
+ return $this->pattern['decimalPoints'];
+ }
+
+ /**
+ * Set the number of decimal places.
+ * @param int number of decimal places.
+ */
+ function setDecimalDigits($value)
+ {
+ return $this->pattern['decimalPoints'] = $value;
+ }
+
+ /**
+ * Gets the string to use as the decimal separator.
+ * @return string decimal separator.
+ */
+ function getDecimalSeparator()
+ {
+ return $this->data['NumberElements'][0];
+ }
+
+ /**
+ * Set the string to use as the decimal separator.
+ * @param string the decimal point
+ */
+ function setDecimalSeparator($value)
+ {
+ return $this->data['NumberElements'][0] = $value;
+ }
+
+ /**
+ * Gets the string that separates groups of digits to the left
+ * of the decimal in currency values.
+ * @param parameter
+ * @return string currency group separator.
+ */
+ function getGroupSeparator()
+ {
+ return $this->data['NumberElements'][1];
+ }
+
+ /**
+ * Set the string to use as the group separator.
+ * @param string the group separator.
+ */
+ function setGroupSeparator($value)
+ {
+ return $this->data['NumberElements'][1] = $value;
+ }
+
+ /**
+ * Gets the number of digits in each group to the left of the decimal
+ * There can be two grouping sizes, this fucntion
+ * returns array(group1, group2), if there is only 1 grouping size,
+ * group2 will be false.
+ * @return array grouping size(s).
+ */
+ function getGroupSizes()
+ {
+ $group1 = $this->pattern['groupSize1'];
+ $group2 = $this->pattern['groupSize2'];
+
+ return array($group1, $group2);
+ }
+
+ /**
+ * Set the number of digits in each group to the left of the decimal.
+ * There can be two grouping sizes, the value should
+ * be an array(group1, group2), if there is only 1 grouping size,
+ * group2 should be false.
+ * @param array grouping size(s).
+ */
+ function setGroupSizes($groupSize)
+ {
+ $this->pattern['groupSize1'] = $groupSize[0];
+ $this->pattern['groupSize2'] = $groupSize[1];
+ }
+
+ /**
+ * Gets the format pattern for negative values.
+ * The negative pattern is composed of a prefix, and postfix.
+ * This function returns array(prefix, postfix).
+ * @return arary negative pattern.
+ */
+ function getNegativePattern()
+ {
+ $prefix = $this->pattern['negPref'];
+ $postfix = $this->pattern['negPost'];
+ return array($prefix, $postfix);
+ }
+
+ /**
+ * Set the format pattern for negative values.
+ * The negative pattern is composed of a prefix, and postfix in the form
+ * array(prefix, postfix).
+ * @param arary negative pattern.
+ */
+ function setNegativePattern($pattern)
+ {
+ $this->pattern['negPref'] = $pattern[0];
+ $this->pattern['negPost'] = $pattern[1];
+ }
+
+ /**
+ * Gets the format pattern for positive values.
+ * The positive pattern is composed of a prefix, and postfix.
+ * This function returns array(prefix, postfix).
+ * @return arary positive pattern.
+ */
+ function getPositivePattern()
+ {
+ $prefix = $this->pattern['posPref'];
+ $postfix = $this->pattern['posPost'];
+ return array($prefix, $postfix);
+ }
+
+ /**
+ * Set the format pattern for positive values.
+ * The positive pattern is composed of a prefix, and postfix in the form
+ * array(prefix, postfix).
+ * @param arary positive pattern.
+ */
+ function setPositivePattern($pattern)
+ {
+ $this->pattern['posPref'] = $pattern[0];
+ $this->pattern['posPost'] = $pattern[1];
+ }
+
+ /**
+ * Gets the string to use as the currency symbol.
+ * @return string currency symbol.
+ */
+ function getCurrencySymbol($currency='USD')
+ {
+ if(isset($this->pattern['symbol']))
+ return $this->pattern['symbol'];
+ else
+ return $this->data['Currencies'][$currency][0];
+ }
+
+
+ /**
+ * Set the string to use as the currency symbol.
+ * @param string currency symbol.
+ */
+ function setCurrencySymbol($symbol)
+ {
+ $this->pattern['symbol'] = $symbol;
+ }
+
+ /**
+ * Gets the string that represents negative infinity.
+ * @return string negative infinity.
+ */
+ function getNegativeInfinitySymbol()
+ {
+ return $this->pattern['negInfty'];
+ }
+
+ /**
+ * Set the string that represents negative infinity.
+ * @param string negative infinity.
+ */
+ function setNegativeInfinitySymbol($value)
+ {
+ $this->pattern['negInfty'] = $value;
+ }
+
+ /**
+ * Gets the string that represents positive infinity.
+ * @return string positive infinity.
+ */
+ function getPositiveInfinitySymbol()
+ {
+ return $this->pattern['posInfty'];
+ }
+
+ /**
+ * Set the string that represents positive infinity.
+ * @param string positive infinity.
+ */
+ function setPositiveInfinitySymbol($value)
+ {
+ $this->pattern['posInfty'] = $value;
+ }
+
+ /**
+ * Gets the string that denotes that the associated number is negative.
+ * @return string negative sign.
+ */
+ function getNegativeSign()
+ {
+ return $this->data['NumberElements'][6];
+ }
+
+ /**
+ * Set the string that denotes that the associated number is negative.
+ * @param string negative sign.
+ */
+ function setNegativeSign($value)
+ {
+ $this->data['NumberElements'][6] = $value;
+ }
+
+ /**
+ * Gets the string that denotes that the associated number is positive.
+ * @return string positive sign.
+ */
+ function getPositiveSign()
+ {
+ return $this->data['NumberElements'][11];
+ }
+
+ /**
+ * Set the string that denotes that the associated number is positive.
+ * @param string positive sign.
+ */
+ function setPositiveSign($value)
+ {
+ $this->data['NumberElements'][11] = $value;
+ }
+
+ /**
+ * Gets the string that represents the IEEE NaN (not a number) value.
+ * @return string NaN symbol.
+ */
+ function getNaNSymbol()
+ {
+ return $this->data['NumberElements'][10];
+ }
+
+ /**
+ * Set the string that represents the IEEE NaN (not a number) value.
+ * @param string NaN symbol.
+ */
+ function setNaNSymbol($value)
+ {
+ $this->data['NumberElements'][10] = $value;
+ }
+
+ /**
+ * Gets the string to use as the percent symbol.
+ * @return string percent symbol.
+ */
+ function getPercentSymbol()
+ {
+ return $this->data['NumberElements'][3];
+ }
+
+ /**
+ * Set the string to use as the percent symbol.
+ * @param string percent symbol.
+ */
+ function setPercentSymbol($value)
+ {
+ $this->data['NumberElements'][3] = $value;
+ }
+
+ /**
+ * Gets the string to use as the per mille symbol.
+ * @return string percent symbol.
+ */
+ function getPerMilleSymbol()
+ {
+ return $this->data['NumberElements'][8];
+ }
+
+ /**
+ * Set the string to use as the per mille symbol.
+ * @param string percent symbol.
+ */
+ function setPerMilleSymbol($value)
+ {
+ $this->data['NumberElements'][8] = $value;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/core/TCache_Lite.php b/framework/I18N/core/TCache_Lite.php
new file mode 100644
index 00000000..45f1dc95
--- /dev/null
+++ b/framework/I18N/core/TCache_Lite.php
@@ -0,0 +1,622 @@
+
+ * @version $Revision: 1.3 $ $Date: 2005/10/09 10:24:12 $
+ * @package System.I18N.core
+ */
+
+/**
+* Fast, light and safe Cache Class
+*
+* TCache_Lite is a fast, light and safe cache system. It's optimized
+* for file containers. It is fast and safe (because it uses file
+* locking and/or anti-corruption tests).
+*
+* There are some examples in the 'docs/examples' file
+* Technical choices are described in the 'docs/technical' file
+*
+* A tutorial is available in english at this url :
+* http://www.pearfr.org/index.php/en/article/cache_lite
+* (big thanks to Pierre-Alain Joye for the translation)
+*
+* The same tutorial is also available in french at this url :
+* http://www.pearfr.org/index.php/fr/article/cache_lite
+*
+* Memory Caching is from an original idea of
+* Mike BENOIT
+*
+* @package System.I18N.core
+* @version $Id: TCache_Lite.php,v 1.3 2005/10/09 10:24:12 weizhuo Exp $
+* @author Fabien MARTY
+*/
+class TCache_Lite
+{
+
+ // --- Private properties ---
+
+ /**
+ * Directory where to put the cache files
+ * (make sure to add a trailing slash)
+ *
+ * @var string $_cacheDir
+ */
+ protected $_cacheDir = '/tmp/';
+
+ /**
+ * Enable / disable caching
+ *
+ * (can be very usefull for the debug of cached scripts)
+ *
+ * @var boolean $_caching
+ */
+ protected $_caching = true;
+
+ /**
+ * Cache lifetime (in seconds)
+ *
+ * @var int $_lifeTime
+ */
+ protected $_lifeTime = 3600;
+
+ /**
+ * Enable / disable fileLocking
+ *
+ * (can avoid cache corruption under bad circumstances)
+ *
+ * @var boolean $_fileLocking
+ */
+ protected $_fileLocking = true;
+
+ /**
+ * Timestamp of the last valid cache
+ *
+ * @var int $_refreshTime
+ */
+ protected $_refreshTime;
+
+ /**
+ * File name (with path)
+ *
+ * @var string $_file
+ */
+ protected $_file;
+
+ /**
+ * Enable / disable write control (the cache is read just after writing
+ * to detect corrupt entries)
+ *
+ * Enable write control will lightly slow the cache writing but not the
+ * cache reading. Write control can detect some corrupt cache files but
+ * maybe it's not a perfect control
+ *
+ * @var boolean $_writeControl
+ */
+ protected $_writeControl = true;
+
+ /**
+ * Enable / disable read control
+ *
+ * If enabled, a control key is embeded in cache file and this key is
+ * compared with the one calculated after the reading.
+ *
+ * @var boolean $_writeControl
+ */
+ protected $_readControl = true;
+
+ /**
+ * Type of read control (only if read control is enabled)
+ *
+ * Available values are :
+ * 'md5' for a md5 hash control (best but slowest)
+ * 'crc32' for a crc32 hash control (lightly less safe but faster,
+ * better choice)
+ * 'strlen' for a length only test (fastest)
+ *
+ * @var boolean $_readControlType
+ */
+ protected $_readControlType = 'crc32';
+
+ /**
+ * Current cache id
+ *
+ * @var string $_id
+ */
+ protected $_id;
+
+ /**
+ * Current cache group
+ *
+ * @var string $_group
+ */
+ protected $_group;
+
+ /**
+ * Enable / Disable "Memory Caching"
+ *
+ * NB : There is no lifetime for memory caching !
+ *
+ * @var boolean $_memoryCaching
+ */
+ protected $_memoryCaching = false;
+
+ /**
+ * Enable / Disable "Only Memory Caching"
+ * (be carefull, memory caching is "beta quality")
+ *
+ * @var boolean $_onlyMemoryCaching
+ */
+ protected $_onlyMemoryCaching = false;
+
+ /**
+ * Memory caching array
+ *
+ * @var array $_memoryCachingArray
+ */
+ protected $_memoryCachingArray = array();
+
+ /**
+ * Memory caching counter
+ *
+ * @var int $memoryCachingCounter
+ */
+ protected $_memoryCachingCounter = 0;
+
+ /**
+ * Memory caching limit
+ *
+ * @var int $memoryCachingLimit
+ */
+ protected $_memoryCachingLimit = 1000;
+
+ /**
+ * File Name protection
+ *
+ * if set to true, you can use any cache id or group name
+ * if set to false, it can be faster but cache ids and group names
+ * will be used directly in cache file names so be carefull with
+ * special characters...
+ *
+ * @var boolean $fileNameProtection
+ */
+ protected $_fileNameProtection = true;
+
+ /**
+ * Enable / disable automatic serialization
+ *
+ * it can be used to save directly datas which aren't strings
+ * (but it's slower)
+ *
+ * @var boolean $_serialize
+ */
+ protected $_automaticSerialization = false;
+
+ // --- Public methods ---
+
+ /**
+ * Constructor
+ *
+ * $options is an assoc. Available options are :
+ * $options = array(
+ * 'cacheDir' => directory where to put the cache files (string),
+ * 'caching' => enable / disable caching (boolean),
+ * 'lifeTime' => cache lifetime in seconds (int),
+ * 'fileLocking' => enable / disable fileLocking (boolean),
+ * 'writeControl' => enable / disable write control (boolean),
+ * 'readControl' => enable / disable read control (boolean),
+ * 'readControlType' => type of read control 'crc32', 'md5', 'strlen',
+ * 'memoryCaching' => enable / disable memory caching (boolean),
+ * 'onlyMemoryCaching' => enable / disable only memory caching (boolean),
+ * 'memoryCachingLimit' => max nbr of records in memory caching (int),
+ * 'fileNameProtection' => enable / disable file name protection (boolean),
+ * 'automaticSerialization' => enable / disable serialization (boolean)
+ * );
+ *
+ * @param array $options options
+ * @access public
+ */
+ function TCache_Lite($options = array(NULL))
+ {
+ $availableOptions = array( 'automaticSerialization',
+ 'fileNameProtection',
+ 'memoryCaching',
+ 'onlyMemoryCaching',
+ 'memoryCachingLimit',
+ 'cacheDir',
+ 'caching',
+ 'lifeTime',
+ 'fileLocking',
+ 'writeControl',
+ 'readControl',
+ 'readControlType');
+ foreach($options as $key => $value) {
+ if(in_array($key, $availableOptions)) {
+ $property = '_'.$key;
+ $this->$property = $value;
+ }
+ }
+ $this->_refreshTime = time() - $this->_lifeTime;
+ }
+
+ /**
+ * Test if a cache is available and (if yes) return it
+ *
+ * @param string $id cache id
+ * @param string $group name of the cache group
+ * @param boolean $doNotTestCacheValidity if set to true, the cache
+ * validity won't be tested
+ * @return string data of the cache (or false if no cache available)
+ * @access public
+ */
+ function get($id, $group = 'default', $doNotTestCacheValidity = false)
+ {
+ $this->_id = $id;
+ $this->_group = $group;
+ $data = false;
+ if ($this->_caching) {
+ $this->_setFileName($id, $group);
+ if ($this->_memoryCaching) {
+ if (isset($this->_memoryCachingArray[$this->_file])) {
+ if ($this->_automaticSerialization) {
+ return unserialize(
+ $this->_memoryCachingArray[$this->_file]);
+ } else {
+ return $this->_memoryCachingArray[$this->_file];
+ }
+ } else {
+ if ($this->_onlyMemoryCaching) {
+ return false;
+ }
+ }
+ }
+ if ($doNotTestCacheValidity) {
+ if (file_exists($this->_file)) {
+ $data = $this->_read();
+ }
+ } else {
+ if (@filemtime($this->_file) > $this->_refreshTime) {
+ $data = $this->_read();
+ }
+ }
+ if (($data) and ($this->_memoryCaching)) {
+ $this->_memoryCacheAdd($this->_file, $data);
+ }
+ if ($this->_automaticSerialization && is_string($data)) {
+ $data = unserialize($data);
+ }
+ return $data;
+ }
+ return false;
+ }
+
+ /**
+ * Save some data in a cache file
+ *
+ * @param string $data data to put in cache (can be another type than strings
+ * if automaticSerialization is on)
+ * @param string $id cache id
+ * @param string $group name of the cache group
+ * @return boolean true if no problem
+ * @access public
+ */
+ function save($data, $id = NULL, $group = 'default')
+ {
+ if ($this->_caching) {
+ if ($this->_automaticSerialization) {
+ $data = serialize($data);
+ }
+ if (isset($id)) {
+ $this->_setFileName($id, $group);
+ }
+ if ($this->_memoryCaching) {
+ $this->_memoryCacheAdd($this->_file, $data);
+ if ($this->_onlyMemoryCaching) {
+ return true;
+ }
+ }
+ if ($this->_writeControl) {
+ if (!$this->_writeAndControl($data)) {
+ @touch($this->_file, time() - 2*abs($this->_lifeTime));
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return $this->_write($data);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove a cache file
+ *
+ * @param string $id cache id
+ * @param string $group name of the cache group
+ * @return boolean true if no problem
+ * @access public
+ */
+ function remove($id, $group = 'default')
+ {
+ $this->_setFileName($id, $group);
+ if (!@unlink($this->_file)) {
+ $this->raiseError('TCache_Lite : Unable to remove cache !', -3);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Clean the cache
+ *
+ * if no group is specified all cache files will be destroyed
+ * else only cache files of the specified group will be destroyed
+ *
+ * @param string $group name of the cache group
+ * @return boolean true if no problem
+ * @access public
+ */
+ function clean($group = false)
+ {
+ if ($this->_fileNameProtection) {
+ $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_';
+ } else {
+ $motif = ($group) ? 'cache_'.$group.'_' : 'cache_';
+ }
+ if ($this->_memoryCaching) {
+ while (list($key, $value) = each($this->_memoryCaching)) {
+ if (strpos($key, $motif, 0)) {
+ unset($this->_memoryCaching[$key]);
+ $this->_memoryCachingCounter =
+ $this->_memoryCachingCounter - 1;
+ }
+ }
+ if ($this->_onlyMemoryCaching) {
+ return true;
+ }
+ }
+ if (!($dh = opendir($this->_cacheDir))) {
+ $this->raiseError('TCache_Lite : Unable to open cache directory !');
+ return false;
+ }
+ while ($file = readdir($dh)) {
+ if (($file != '.') && ($file != '..')) {
+ $file = $this->_cacheDir . $file;
+ if (is_file($file)) {
+ if (strpos($file, $motif, 0)) {
+ if (!@unlink($file)) {
+ $this->raiseError('Cache_Lite : Unable to remove cache !', -3);
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Set a new life time
+ *
+ * @param int $newLifeTime new life time (in seconds)
+ * @access public
+ */
+ function setLifeTime($newLifeTime)
+ {
+ $this->_lifeTime = $newLifeTime;
+ $this->_refreshTime = time() - $newLifeTime;
+ }
+
+ /**
+ *
+ * @access public
+ */
+ function saveMemoryCachingState($id, $group = 'default')
+ {
+ if ($this->_caching) {
+ $array = array(
+ 'counter' => $this->_memoryCachingCounter,
+ 'array' => $this->_memoryCachingState
+ );
+ $data = serialize($array);
+ $this->save($data, $id, $group);
+ }
+ }
+
+ /**
+ *
+ * @access public
+ */
+ function getMemoryCachingState($id, $group = 'default',
+ $doNotTestCacheValidity = false)
+ {
+ if ($this->_caching) {
+ if ($data = $this->get($id, $group, $doNotTestCacheValidity))
+ {
+ $array = unserialize($data);
+ $this->_memoryCachingCounter = $array['counter'];
+ $this->_memoryCachingArray = $array['array'];
+ }
+ }
+ }
+
+ /**
+ * Return the cache last modification time
+ *
+ * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY !
+ *
+ * @return int last modification time
+ */
+ function lastModified() {
+ return filemtime($this->cache->_file);
+ }
+
+ /**
+ * Trigger a PEAR error
+ *
+ * To improve performances, the PEAR.php file is included dynamically.
+ * The file is so included only when an error is triggered. So, in most
+ * cases, the file isn't included and perfs are much better.
+ *
+ * @param string $msg error message
+ * @param int $code error code
+ * @access public
+ */
+ function raiseError($msg, $code)
+ {
+ throw new Exception($msg);
+ }
+
+ // --- Private methods ---
+
+ /**
+ *
+ * @access private
+ */
+ function _memoryCacheAdd($id, $data)
+ {
+ $this->_memoryCachingArray[$this->_file] = $data;
+ if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) {
+ list($key, $value) = each($this->_memoryCachingArray);
+ unset($this->_memoryCachingArray[$key]);
+ } else {
+ $this->_memoryCachingCounter = $this->_memoryCachingCounter + 1;
+ }
+ }
+
+ /**
+ * Make a file name (with path)
+ *
+ * @param string $id cache id
+ * @param string $group name of the group
+ * @access private
+ */
+ function _setFileName($id, $group)
+ {
+ if ($this->_fileNameProtection) {
+ $this->_file = ($this->_cacheDir.'cache_'.md5($group).'_'
+ .md5($id));
+ } else {
+ $this->_file = $this->_cacheDir.'cache_'.$group.'_'.$id;
+ }
+ }
+
+ function getCacheFile()
+ {
+ return $this->_file;
+ }
+
+ /**
+ * Read the cache file and return the content
+ *
+ * @return string content of the cache file
+ * @access private
+ */
+ function _read()
+ {
+ $fp = @fopen($this->_file, "rb");
+ if ($this->_fileLocking) @flock($fp, LOCK_SH);
+ if ($fp) {
+ // because the filesize can be cached by PHP itself...
+ clearstatcache();
+ $length = @filesize($this->_file);
+ $mqr = get_magic_quotes_runtime();
+ set_magic_quotes_runtime(0);
+ if ($this->_readControl) {
+ $hashControl = @fread($fp, 32);
+ $length = $length - 32;
+ }
+ $data = @fread($fp, $length);
+ set_magic_quotes_runtime($mqr);
+ if ($this->_fileLocking) @flock($fp, LOCK_UN);
+ @fclose($fp);
+ if ($this->_readControl) {
+ $hashData = $this->_hash($data, $this->_readControlType);
+ if ($hashData != $hashControl) {
+ @touch($this->_file, time() - 2*abs($this->_lifeTime));
+ return false;
+ }
+ }
+ return $data;
+ }
+ $this->raiseError('Cache_Lite : Unable to read cache !', -2);
+ return false;
+ }
+
+ /**
+ * Write the given data in the cache file
+ *
+ * @param string $data data to put in cache
+ * @return boolean true if ok
+ * @access private
+ */
+ function _write($data)
+ {
+ $fp = @fopen($this->_file, "wb");
+ if ($fp) {
+ if ($this->_fileLocking) @flock($fp, LOCK_EX);
+ if ($this->_readControl) {
+ @fwrite($fp, $this->_hash($data, $this->_readControlType), 32);
+ }
+ $len = strlen($data);
+ @fwrite($fp, $data, $len);
+ if ($this->_fileLocking) @flock($fp, LOCK_UN);
+ @fclose($fp);
+ return true;
+ }
+ $this->raiseError('Cache_Lite : Unable to write cache !', -1);
+ return false;
+ }
+
+ /**
+ * Write the given data in the cache file and control it just after to avoid
+ * corrupted cache entries
+ *
+ * @param string $data data to put in cache
+ * @return boolean true if the test is ok
+ * @access private
+ */
+ function _writeAndControl($data)
+ {
+ $this->_write($data);
+ $dataRead = $this->_read($data);
+ return ($dataRead==$data);
+ }
+
+ /**
+ * Make a control key with the string containing datas
+ *
+ * @param string $data data
+ * @param string $controlType type of control 'md5', 'crc32' or 'strlen'
+ * @return string control key
+ * @access private
+ */
+ function _hash($data, $controlType)
+ {
+ switch ($controlType) {
+ case 'md5':
+ return md5($data);
+ case 'crc32':
+ return sprintf('% 32d', crc32($data));
+ case 'strlen':
+ return sprintf('% 32d', strlen($data));
+ default:
+ $this->raiseError('Unknown controlType ! '.
+ '(available values are only \'md5\', \'crc32\', \'strlen\')', -5);
+ }
+ }
+
+}
+
+?>
diff --git a/framework/I18N/core/data/af.dat b/framework/I18N/core/data/af.dat
new file mode 100644
index 00000000..bad75bef
--- /dev/null
+++ b/framework/I18N/core/data/af.dat
@@ -0,0 +1 @@
+a:7:{s:9:"Countries";a:130:{s:2:"AE";a:1:{i:0;s:26:"Verenigde Arabiese Emirate";}s:2:"AF";a:1:{i:0;s:10:"Afganistan";}s:2:"AG";a:1:{i:0;s:18:"Antigua en Barbuda";}s:2:"AL";a:1:{i:0;s:8:"Albanië";}s:2:"AM";a:1:{i:0;s:8:"Armenië";}s:2:"AR";a:1:{i:0;s:11:"Argentinië";}s:2:"AT";a:1:{i:0;s:9:"Oostenryk";}s:2:"AU";a:1:{i:0;s:10:"Australië";}s:2:"AZ";a:1:{i:0;s:11:"Aserbeidjan";}s:2:"BA";a:1:{i:0;s:22:"Bosnië en Herzegowina";}s:2:"BD";a:1:{i:0;s:10:"Bangladesj";}s:2:"BE";a:1:{i:0;s:7:"België";}s:2:"BF";a:1:{i:0;s:14:"Boerkina Fasso";}s:2:"BG";a:1:{i:0;s:8:"Bulgarye";}s:2:"BH";a:1:{i:0;s:7:"Bahrein";}s:2:"BN";a:1:{i:0;s:7:"Broenei";}s:2:"BO";a:1:{i:0;s:8:"Bolivië";}s:2:"BR";a:1:{i:0;s:9:"Brasilië";}s:2:"BT";a:1:{i:0;s:7:"Bhoetan";}s:2:"BY";a:1:{i:0;s:11:"Wit-Rusland";}s:2:"CA";a:1:{i:0;s:6:"Kanada";}s:2:"CF";a:1:{i:0;s:29:"Sentraal-Afrikaanse Republiek";}s:2:"CG";a:1:{i:0;s:5:"Kongo";}s:2:"CH";a:1:{i:0;s:11:"Switserland";}s:2:"CI";a:1:{i:0;s:8:"Ivoorkus";}s:2:"CL";a:1:{i:0;s:5:"Chili";}s:2:"CM";a:1:{i:0;s:8:"Kameroen";}s:2:"CN";a:1:{i:0;s:5:"Sjina";}s:2:"CU";a:1:{i:0;s:4:"Kuba";}s:2:"CV";a:1:{i:0;s:10:"Kaap Verde";}s:2:"CY";a:1:{i:0;s:6:"Ciprus";}s:2:"CZ";a:1:{i:0;s:19:"Tjeggiese Republiek";}s:2:"DE";a:1:{i:0;s:9:"Duitsland";}s:2:"DJ";a:1:{i:0;s:8:"Djiboeti";}s:2:"DK";a:1:{i:0;s:9:"Denemarke";}s:2:"DO";a:1:{i:0;s:22:"Dominikaanse Republiek";}s:2:"DZ";a:1:{i:0;s:8:"Algerië";}s:2:"EE";a:1:{i:0;s:7:"Estland";}s:2:"EG";a:1:{i:0;s:6:"Egipte";}s:2:"EH";a:1:{i:0;s:10:"Wes-Sahara";}s:2:"ES";a:1:{i:0;s:6:"Spanje";}s:2:"ET";a:1:{i:0;s:9:"Ethiopië";}s:2:"FJ";a:1:{i:0;s:5:"Fidji";}s:2:"FM";a:1:{i:0;s:11:"Mikronesië";}s:2:"FR";a:1:{i:0;s:8:"Frankryk";}s:2:"GA";a:1:{i:0;s:6:"Gaboen";}s:2:"GB";a:1:{i:0;s:15:"Groot-Brittanje";}s:2:"GE";a:1:{i:0;s:8:"Georgië";}s:2:"GM";a:1:{i:0;s:7:"Gambië";}s:2:"GN";a:1:{i:0;s:6:"Guinee";}s:2:"GQ";a:1:{i:0;s:18:"Ekwatoriaal-Guinee";}s:2:"GR";a:1:{i:0;s:10:"Griekeland";}s:2:"GW";a:1:{i:0;s:13:"Guinee-Bissau";}s:2:"HR";a:1:{i:0;s:8:"Kroasië";}s:2:"HT";a:1:{i:0;s:6:"Haïti";}s:2:"HU";a:1:{i:0;s:8:"Hongarye";}s:2:"ID";a:1:{i:0;s:10:"Indonesië";}s:2:"IE";a:1:{i:0;s:7:"Ierland";}s:2:"IN";a:1:{i:0;s:6:"Indië";}s:2:"IQ";a:1:{i:0;s:4:"Irak";}s:2:"IS";a:1:{i:0;s:6:"Ysland";}s:2:"IT";a:1:{i:0;s:7:"Italië";}s:2:"JM";a:1:{i:0;s:7:"Jamaika";}s:2:"JO";a:1:{i:0;s:9:"Jordanië";}s:2:"KE";a:1:{i:0;s:5:"Kenia";}s:2:"KG";a:1:{i:0;s:9:"Kirgisië";}s:2:"KH";a:1:{i:0;s:8:"Kambodja";}s:2:"KM";a:1:{i:0;s:6:"Comore";}s:2:"KN";a:1:{i:0;s:20:"Saint Kitts en Nevis";}s:2:"KP";a:1:{i:0;s:11:"Noord-Korea";}s:2:"KR";a:1:{i:0;s:10:"Suid-Korea";}s:2:"KW";a:1:{i:0;s:7:"Koeweit";}s:2:"KZ";a:1:{i:0;s:9:"Kasakstan";}s:2:"LB";a:1:{i:0;s:7:"Libanon";}s:2:"LR";a:1:{i:0;s:8:"Liberië";}s:2:"LT";a:1:{i:0;s:6:"Litaue";}s:2:"LU";a:1:{i:0;s:9:"Luxemburg";}s:2:"LV";a:1:{i:0;s:7:"Letland";}s:2:"LY";a:1:{i:0;s:6:"Libië";}s:2:"MA";a:1:{i:0;s:7:"Marokko";}s:2:"MG";a:1:{i:0;s:10:"Madagaskar";}s:2:"MH";a:1:{i:0;s:16:"Marshall-eilande";}s:2:"MK";a:1:{i:0;s:10:"Macedonië";}s:2:"MN";a:1:{i:0;s:9:"Mongolië";}s:2:"MR";a:1:{i:0;s:11:"Mouritanië";}s:2:"MV";a:1:{i:0;s:7:"Maldive";}s:2:"MX";a:1:{i:0;s:7:"Meksiko";}s:2:"MY";a:1:{i:0;s:9:"Maleisië";}s:2:"MZ";a:1:{i:0;s:9:"Mosambiek";}s:2:"NA";a:1:{i:0;s:8:"Namibië";}s:2:"NE";a:1:{i:0;s:8:"Nigerië";}s:2:"NL";a:1:{i:0;s:9:"Nederland";}s:2:"NO";a:1:{i:0;s:8:"Noorweë";}s:2:"NR";a:1:{i:0;s:7:"Naoeroe";}s:2:"NZ";a:1:{i:0;s:12:"Nieu-Seeland";}s:2:"PG";a:1:{i:0;s:18:"Papoea Nieu-Guinee";}s:2:"PH";a:1:{i:0;s:9:"Filippyne";}s:2:"PL";a:1:{i:0;s:4:"Pole";}s:2:"QA";a:1:{i:0;s:5:"Katar";}s:2:"RO";a:1:{i:0;s:9:"Roemenië";}s:2:"RU";a:1:{i:0;s:7:"Rusland";}s:2:"SA";a:1:{i:0;s:14:"Saoedi-Arabië";}s:2:"SB";a:1:{i:0;s:15:"Solomon Eilande";}s:2:"SC";a:1:{i:0;s:9:"Seychelle";}s:2:"SD";a:1:{i:0;s:6:"Soedan";}s:2:"SE";a:1:{i:0;s:5:"Swede";}s:2:"SG";a:1:{i:0;s:9:"Singapoer";}s:2:"SI";a:1:{i:0;s:9:"Slowenië";}s:2:"SK";a:1:{i:0;s:8:"Slowakye";}s:2:"SO";a:1:{i:0;s:8:"Somalië";}s:2:"SP";a:1:{i:0;s:7:"Serwië";}s:2:"ST";a:1:{i:0;s:20:"Sao Tome en Principe";}s:2:"SV";a:1:{i:0;s:8:"Salvador";}s:2:"SY";a:1:{i:0;s:6:"Sirië";}s:2:"TD";a:1:{i:0;s:6:"Tsjaad";}s:2:"TJ";a:1:{i:0;s:11:"Tadjikistan";}s:2:"TM";a:1:{i:0;s:10:"Turkmenië";}s:2:"TN";a:1:{i:0;s:8:"Tunisië";}s:2:"TR";a:1:{i:0;s:6:"Turkye";}s:2:"TT";a:1:{i:0;s:18:"Trinidad en Tobago";}s:2:"TZ";a:1:{i:0;s:9:"Tanzanië";}s:2:"UA";a:1:{i:0;s:8:"Oekraine";}s:2:"US";a:1:{i:0;s:27:"Verenigde State van Amerika";}s:2:"UZ";a:1:{i:0;s:11:"Oesbekistan";}s:2:"VA";a:1:{i:0;s:8:"Vatikaan";}s:2:"VC";a:1:{i:0;s:30:"Saint Vincent en die Grenadine";}s:2:"VN";a:1:{i:0;s:8:"Viëtnam";}s:2:"YE";a:1:{i:0;s:5:"Jemen";}s:2:"ZA";a:1:{i:0;s:11:"Suid-Afrika";}s:2:"ZM";a:1:{i:0;s:7:"Zambië";}}s:10:"Currencies";a:1:{s:3:"ZAR";a:2:{i:0;s:1:"R";i:1;s:4:"Rand";}}s:9:"Languages";a:1:{s:2:"af";a:1:{i:0;s:9:"Afrikaans";}}s:12:"LocaleScript";a:1:{i:0;s:4:"Latn";}s:14:"NumberElements";a:12:{i:0;s:1:",";i:1;s:2:" ";i:2;s:1:";";i:3;s:1:"%";i:4;s:1:"0";i:5;s:1:"#";i:6;s:1:"-";i:7;s:1:"E";i:8;s:3:"‰";i:9;s:3:"∞";i:10;s:3:"�";i:11;s:1:"+";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:4:{s:11:"AmPmMarkers";a:2:{i:0;s:3:"vm.";i:1;s:3:"nm.";}s:8:"dayNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:7:{i:0;s:2:"So";i:1;s:2:"Ma";i:2;s:2:"Di";i:3;s:2:"Wo";i:4;s:2:"Do";i:5;s:2:"Vr";i:6;s:2:"Sa";}s:4:"wide";a:7:{i:0;s:6:"Sondag";i:1;s:7:"Maandag";i:2;s:7:"Dinsdag";i:3;s:8:"Woensdag";i:4;s:9:"Donderdag";i:5;s:6:"Vrydag";i:6;s:8:"Saterdag";}}}s:4:"eras";a:1:{s:11:"abbreviated";a:2:{i:0;s:4:"v.C.";i:1;s:4:"n.C.";}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:12:{i:0;s:3:"Jan";i:1;s:3:"Feb";i:2;s:3:"Mar";i:3;s:3:"Apr";i:4;s:3:"Mei";i:5;s:3:"Jun";i:6;s:3:"Jul";i:7;s:3:"Aug";i:8;s:3:"Sep";i:9;s:3:"Okt";i:10;s:3:"Nov";i:11;s:3:"Des";}s:4:"wide";a:12:{i:0;s:8:"Januarie";i:1;s:9:"Februarie";i:2;s:5:"Maart";i:3;s:5:"April";i:4;s:3:"Mei";i:5;s:5:"Junie";i:6;s:5:"Julie";i:7;s:8:"Augustus";i:8;s:9:"September";i:9;s:7:"Oktober";i:10;s:8:"November";i:11;s:8:"Desember";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/af_ZA.dat b/framework/I18N/core/data/af_ZA.dat
new file mode 100644
index 00000000..fd63a836
--- /dev/null
+++ b/framework/I18N/core/data/af_ZA.dat
@@ -0,0 +1 @@
+a:3:{s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;-#,##0.###";i:1;s:22:"¤#,##0.00;-¤#,##0.00";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:1:{s:16:"DateTimePatterns";a:9:{i:0;s:9:"h:mm:ss a";i:1;s:9:"h:mm:ss a";i:2;s:9:"h:mm:ss a";i:3;s:6:"h:mm a";i:4;s:17:"EEEE dd MMMM yyyy";i:5;s:12:"dd MMMM yyyy";i:6;s:11:"dd MMM yyyy";i:7;s:10:"yyyy/MM/dd";i:8;s:7:"{1} {0}";}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/am.dat b/framework/I18N/core/data/am.dat
new file mode 100644
index 00000000..914ea029
--- /dev/null
+++ b/framework/I18N/core/data/am.dat
@@ -0,0 +1 @@
+a:5:{s:9:"Countries";a:128:{s:2:"AD";a:1:{i:0;s:12:"አንዶራ";}s:2:"AE";a:1:{i:0;s:44:"የተባበሩት አረብ ኤáˆáˆ¬á‰µáˆµ";}s:2:"AL";a:1:{i:0;s:15:"አáˆá‰£áŠ’á‹«";}s:2:"AM";a:1:{i:0;s:15:"አáˆáˆœáŠ’á‹«";}s:2:"AN";a:1:{i:0;s:37:"ኔዘáˆáˆ‹áŠ•á‹µáˆµ አንቲáˆáˆµ";}s:2:"AR";a:1:{i:0;s:18:"አáˆáŒ€áŠ•á‰²áŠ“";}s:2:"AT";a:1:{i:0;s:15:"ኦስትሪያ";}s:2:"AU";a:1:{i:0;s:21:"አá‹áˆµá‰µáˆ¬áˆŠá‹«";}s:2:"AZ";a:1:{i:0;s:18:"አዘáˆá‰£áŒƒáŠ•";}s:2:"BA";a:1:{i:0;s:41:"ቦስኒያ እና ሄáˆá‹žáŒŽá‰ªáŠ’á‹«";}s:2:"BB";a:1:{i:0;s:15:"ባáˆá‰¤á‹¶áˆµ";}s:2:"BE";a:1:{i:0;s:12:"ቤáˆáŒ„áˆ";}s:2:"BG";a:1:{i:0;s:15:"ቡáˆáŒŒáˆªá‹«";}s:2:"BH";a:1:{i:0;s:12:"ባህሬን";}s:2:"BM";a:1:{i:0;s:12:"ቤáˆáˆ™á‹³";}s:2:"BO";a:1:{i:0;s:12:"ቦሊቪያ";}s:2:"BR";a:1:{i:0;s:12:"ብራዚáˆ";}s:2:"BT";a:1:{i:0;s:12:"ቡህታን";}s:2:"BY";a:1:{i:0;s:12:"ቤላሩስ";}s:2:"BZ";a:1:{i:0;s:9:"ቤሊዘ";}s:2:"CD";a:1:{i:0;s:9:"ኮንጎ";}s:2:"CF";a:1:{i:0;s:50:"የመካከለኛዠአáሪካ ሪáብሊáŠ";}s:2:"CH";a:1:{i:0;s:21:"ስዊዘáˆáˆ‹áŠ•á‹µ";}s:2:"CL";a:1:{i:0;s:6:"ቺሊ";}s:2:"CM";a:1:{i:0;s:12:"ካሜሩን";}s:2:"CN";a:1:{i:0;s:9:"ቻá‹áŠ“";}s:2:"CO";a:1:{i:0;s:15:"ኮሎáˆá‰¢á‹«";}s:2:"CV";a:1:{i:0;s:16:"ኬᕠቬáˆá‹´";}s:2:"CY";a:1:{i:0;s:15:"ሳá‹á•áˆ¨áˆµ";}s:2:"CZ";a:1:{i:0;s:22:"ቼአሪá‘ብሊáŠ";}s:2:"DE";a:1:{i:0;s:12:"ጀáˆáˆ˜áŠ•";}s:2:"DK";a:1:{i:0;s:15:"ዴንማáˆáŠ";}s:2:"DM";a:1:{i:0;s:12:"ዶሚኒካ";}s:2:"DO";a:1:{i:0;s:28:"ዶሚኒአሪá‘ብሊáŠ";}s:2:"DZ";a:1:{i:0;s:15:"አáˆáŒ„ሪያ";}s:2:"EC";a:1:{i:0;s:12:"ኢኳዶáˆ";}s:2:"EE";a:1:{i:0;s:15:"ኤስቶኒያ";}s:2:"EG";a:1:{i:0;s:9:"áŒá‰¥áŒ½";}s:2:"EH";a:1:{i:0;s:25:"áˆá‹•áˆ«á‰£á‹Š ሳህራ";}s:2:"ER";a:1:{i:0;s:12:"ኤáˆá‰µáˆ«";}s:2:"ES";a:1:{i:0;s:9:"ስá”ን";}s:2:"ET";a:1:{i:0;s:15:"ኢትዮጵያ";}s:2:"FI";a:1:{i:0;s:15:"áŠáŠ•áˆ‹áŠ•á‹µ";}s:2:"FJ";a:1:{i:0;s:6:"áŠáŒ‚";}s:2:"FM";a:1:{i:0;s:18:"ሚáŠáˆ®áŠ”ዢያ";}s:2:"GB";a:1:{i:0;s:15:"እንáŒáˆŠá‹";}s:2:"GE";a:1:{i:0;s:12:"ጆáˆáŒ‚á‹«";}s:2:"GF";a:1:{i:0;s:31:"የáˆáˆ¨áŠ•áˆ³á‹ ጉዊአና";}s:2:"GM";a:1:{i:0;s:12:"ጋáˆá‰¢á‹«";}s:2:"GN";a:1:{i:0;s:6:"ጊኒ";}s:2:"GQ";a:1:{i:0;s:25:"ኢኳቶሪያሠጊኒ";}s:2:"GR";a:1:{i:0;s:9:"áŒáˆªáŠ";}s:2:"GW";a:1:{i:0;s:9:"ቢሳዎ";}s:2:"GY";a:1:{i:0;s:9:"ጉያና";}s:2:"HR";a:1:{i:0;s:15:"áŠáˆ®áŠ¤áˆ½á‹«";}s:2:"HT";a:1:{i:0;s:9:"ሀá‹á‰²";}s:2:"HU";a:1:{i:0;s:12:"ሀንጋሪ";}s:2:"ID";a:1:{i:0;s:18:"ኢንዶኔዢያ";}s:2:"IE";a:1:{i:0;s:18:"አየáˆáˆ‹áŠ•á‹µ";}s:2:"IL";a:1:{i:0;s:15:"እስራኤáˆ";}s:2:"IN";a:1:{i:0;s:9:"ህንድ";}s:2:"IQ";a:1:{i:0;s:9:"ኢራቅ";}s:2:"IS";a:1:{i:0;s:18:"አá‹áˆµáˆ‹áŠ•á‹µ";}s:2:"IT";a:1:{i:0;s:12:"ጣሊያን";}s:2:"JM";a:1:{i:0;s:12:"ጃማá‹áŠ«";}s:2:"JO";a:1:{i:0;s:12:"ጆáˆá‹³áŠ•";}s:2:"JP";a:1:{i:0;s:9:"ጃá“ን";}s:2:"KH";a:1:{i:0;s:15:"ካáˆá‰¦á‹²á‹«";}s:2:"KM";a:1:{i:0;s:12:"ኮሞሮስ";}s:2:"KP";a:1:{i:0;s:19:"ደቡብ ኮሪያ";}s:2:"KR";a:1:{i:0;s:19:"ሰሜን ኮሪያ";}s:2:"KW";a:1:{i:0;s:9:"áŠá‹Œá‰µ";}s:2:"LB";a:1:{i:0;s:12:"ሊባኖስ";}s:2:"LT";a:1:{i:0;s:15:"ሊቱዌኒያ";}s:2:"LV";a:1:{i:0;s:12:"ላትቪያ";}s:2:"LY";a:1:{i:0;s:9:"ሊቢያ";}s:2:"MA";a:1:{i:0;s:9:"ሞሮኮ";}s:2:"MD";a:1:{i:0;s:12:"ሞáˆá‹¶á‰«";}s:2:"MK";a:1:{i:0;s:15:"ማከዶኒያ";}s:2:"MN";a:1:{i:0;s:15:"ሞንጎሊያ";}s:2:"MR";a:1:{i:0;s:15:"ሞሪቴኒያ";}s:2:"MT";a:1:{i:0;s:9:"ማáˆá‰³";}s:2:"MU";a:1:{i:0;s:12:"ማሩሸስ";}s:2:"MX";a:1:{i:0;s:12:"ሜáŠáˆ²áŠ®";}s:2:"MY";a:1:{i:0;s:12:"ማሌዢያ";}s:2:"NA";a:1:{i:0;s:12:"ናሚቢያ";}s:2:"NC";a:1:{i:0;s:22:"ኒዠካሌዶኒያ";}s:2:"NG";a:1:{i:0;s:15:"ናá‹áŒ„ሪያ";}s:2:"NL";a:1:{i:0;s:18:"ኔዘáˆáˆ‹áŠ•á‹µ";}s:2:"NO";a:1:{i:0;s:9:"ኖáˆá‹Œ";}s:2:"NP";a:1:{i:0;s:9:"ኔá“áˆ";}s:2:"NZ";a:1:{i:0;s:19:"ኒዠዚላንድ";}s:2:"PE";a:1:{i:0;s:6:"á”ሩ";}s:2:"PF";a:1:{i:0;s:34:"የáˆáˆ¨áŠ•áˆ³á‹ á–ሊኔዢያ";}s:2:"PG";a:1:{i:0;s:23:"á“á‘á‹‹ ኒዠጊኒ";}s:2:"PL";a:1:{i:0;s:12:"á–ላንድ";}s:2:"PR";a:1:{i:0;s:16:"á–áˆá‰³ ሪኮ";}s:2:"RO";a:1:{i:0;s:12:"ሮሜኒያ";}s:2:"RU";a:1:{i:0;s:9:"ራሺያ";}s:2:"SA";a:1:{i:0;s:21:"ሳá‹á‹µáŠ ረቢያ";}s:2:"SD";a:1:{i:0;s:9:"ሱዳን";}s:2:"SE";a:1:{i:0;s:12:"ስዊድን";}s:2:"SG";a:1:{i:0;s:15:"ሲንጋá–áˆ";}s:2:"SI";a:1:{i:0;s:15:"ስሎቬኒያ";}s:2:"SK";a:1:{i:0;s:15:"ስሎቫኪያ";}s:2:"SN";a:1:{i:0;s:12:"ሴኔጋáˆ";}s:2:"SO";a:1:{i:0;s:9:"ሱማሌ";}s:2:"SP";a:1:{i:0;s:12:"ሰáˆá‰¢á‹«";}s:2:"SY";a:1:{i:0;s:9:"ሲሪያ";}s:2:"TD";a:1:{i:0;s:6:"ቻድ";}s:2:"TF";a:1:{i:0;s:44:"የáˆáˆ¨áŠ•áˆ³á‹ ደቡባዊ áŒá‹›á‰¶á‰½";}s:2:"TH";a:1:{i:0;s:15:"ታá‹áˆ‹áŠ•á‹µ";}s:2:"TJ";a:1:{i:0;s:18:"ታጃኪስታን";}s:2:"TL";a:1:{i:0;s:22:"áˆáˆµáˆ«á‰… ቲሞáˆ";}s:2:"TN";a:1:{i:0;s:12:"ቱኒዚያ";}s:2:"TR";a:1:{i:0;s:9:"ቱáˆáŠ";}s:2:"TT";a:1:{i:0;s:32:"ትሪኒዳድ እና ቶባጎ";}s:2:"TZ";a:1:{i:0;s:15:"ታንዛኒያ";}s:2:"UG";a:1:{i:0;s:12:"ዩጋንዳ";}s:2:"US";a:1:{i:0;s:12:"አሜሪካ";}s:2:"UZ";a:1:{i:0;s:21:"á‹©á‹á‰ ኪስታን";}s:2:"VE";a:1:{i:0;s:15:"ቬንዙዌላ";}s:2:"VG";a:1:{i:0;s:44:"የእንáŒáˆŠá‹ ድንáŒáˆ ደሴቶች";}s:2:"VI";a:1:{i:0;s:41:"የአሜሪካ ቨáˆáŒ‚ን ደሴቶች";}s:2:"YE";a:1:{i:0;s:9:"የመን";}s:2:"YU";a:1:{i:0;s:18:"ዩጎá‹áˆ‹á‰ªá‹«";}s:2:"ZA";a:1:{i:0;s:22:"ደቡብ አáሪካ";}s:2:"ZM";a:1:{i:0;s:12:"á‹›áˆá‰¢á‹«";}}s:9:"Languages";a:142:{s:2:"aa";a:1:{i:0;s:12:"አá‹áˆáŠ›";}s:2:"ab";a:1:{i:0;s:15:"አብáˆá‹šáŠ›";}s:2:"af";a:1:{i:0;s:21:"አáሪቃንስኛ";}s:2:"am";a:1:{i:0;s:12:"አማáˆáŠ›";}s:2:"ar";a:1:{i:0;s:12:"á‹áˆá‰¢áŠ›";}s:2:"as";a:1:{i:0;s:15:"አሳሜዛዊ";}s:2:"ay";a:1:{i:0;s:15:"አያማáˆáŠ›";}s:2:"az";a:1:{i:0;s:24:"አዜáˆá‰£á‹áŒƒáŠ•áŠ›";}s:2:"ba";a:1:{i:0;s:15:"ባስኪáˆáŠ›";}s:2:"be";a:1:{i:0;s:15:"ቤላራሻኛ";}s:2:"bg";a:1:{i:0;s:15:"ቡáˆáŒ‹áˆªáŠ›";}s:2:"bh";a:1:{i:0;s:9:"ቢሃሪ";}s:2:"bi";a:1:{i:0;s:15:"ቢስላáˆáŠ›";}s:2:"bn";a:1:{i:0;s:15:"በንጋሊኛ";}s:2:"bo";a:1:{i:0;s:15:"ትበትንኛ";}s:2:"br";a:1:{i:0;s:15:"ብሬቶንኛ";}s:3:"byn";a:1:{i:0;s:9:"ብሊን";}s:2:"ca";a:1:{i:0;s:15:"ካታላንኛ";}s:2:"co";a:1:{i:0;s:15:"ኮáˆáˆ²áŠ«áŠ›";}s:2:"cs";a:1:{i:0;s:9:"ቼáŠáŠ›";}s:2:"cy";a:1:{i:0;s:9:"ወáˆáˆ½";}s:2:"da";a:1:{i:0;s:9:"ዴኒሽ";}s:2:"de";a:1:{i:0;s:12:"ጀáˆáˆ˜áŠ•";}s:2:"dz";a:1:{i:0;s:18:"ድዞንáŒáŠ»áŠ›";}s:2:"el";a:1:{i:0;s:12:"áŒáˆªáŠáŠ›";}s:2:"en";a:1:{i:0;s:18:"እንáŒáˆŠá‹áŠ›";}s:2:"eo";a:1:{i:0;s:18:"ኤስáራንቶ";}s:2:"es";a:1:{i:0;s:12:"ስá“ኒሽ";}s:2:"et";a:1:{i:0;s:18:"ኤስቶኒአን";}s:2:"eu";a:1:{i:0;s:12:"ባስáŠáŠ›";}s:2:"fa";a:1:{i:0;s:15:"ááˆáˆ²á‹«áŠ›";}s:2:"fi";a:1:{i:0;s:9:"áŠáŠ’ሽ";}s:2:"fj";a:1:{i:0;s:9:"áŠáŒ‚ኛ";}s:2:"fo";a:1:{i:0;s:9:"á‹áˆ®áŠ›";}s:2:"fr";a:1:{i:0;s:18:"áˆáˆ¨áŠ•áˆ³á‹áŠ›";}s:2:"fy";a:1:{i:0;s:12:"áሪስኛ";}s:2:"ga";a:1:{i:0;s:12:"አá‹áˆªáˆ½";}s:2:"gd";a:1:{i:0;s:28:"እስኮትስ ጌáˆáŠáŠ›";}s:3:"gez";a:1:{i:0;s:12:"áŒá‹•á‹áŠ›";}s:2:"gl";a:1:{i:0;s:12:"ጋለጋኛ";}s:2:"gn";a:1:{i:0;s:12:"ጓራኒኛ";}s:2:"gu";a:1:{i:0;s:15:"ጉጃáˆá‰²áŠ›";}s:2:"ha";a:1:{i:0;s:12:"ሃá‹áˆ³áŠ›";}s:2:"he";a:1:{i:0;s:15:"ዕብራስጥ";}s:2:"hi";a:1:{i:0;s:12:"áˆáŠ•á‹µáŠ›";}s:2:"hr";a:1:{i:0;s:18:"áŠáˆ®áˆ½á‹«áŠ•áŠ›";}s:2:"hu";a:1:{i:0;s:15:"ሀንጋሪኛ";}s:2:"hy";a:1:{i:0;s:15:"አáˆáˆ˜áŠ“á‹Š";}s:2:"ia";a:1:{i:0;s:21:"ኢንቴáˆáˆŠáŠ•áŒ“";}s:2:"id";a:1:{i:0;s:18:"እንዶኒሲኛ";}s:2:"ie";a:1:{i:0;s:24:"እንተáˆáˆŠáŠ•áŒá‹ˆ";}s:2:"ik";a:1:{i:0;s:18:"እኑá’ያቅኛ";}s:2:"is";a:1:{i:0;s:21:"አá‹áˆµáˆ‹áŠ•á‹µáŠ›";}s:2:"it";a:1:{i:0;s:15:"ጣሊያንኛ";}s:2:"iu";a:1:{i:0;s:21:"እኑáŠá‰²á‰±á‰µáŠ›";}s:2:"ja";a:1:{i:0;s:12:"ጃá“ንኛ";}s:2:"jv";a:1:{i:0;s:12:"ጃቫንኛ";}s:2:"ka";a:1:{i:0;s:18:"ጊዮáˆáŒŠá‹«áŠ•";}s:2:"kk";a:1:{i:0;s:12:"ካዛáŠáŠ›";}s:2:"kl";a:1:{i:0;s:18:"ካላሊሱትኛ";}s:2:"km";a:1:{i:0;s:12:"áŠáˆ˜áˆáŠ›";}s:2:"kn";a:1:{i:0;s:12:"ካናዳኛ";}s:2:"ko";a:1:{i:0;s:12:"ኮሪያኛ";}s:2:"ks";a:1:{i:0;s:15:"ካሽሚáˆáŠ›";}s:2:"ku";a:1:{i:0;s:15:"ኩáˆá‹µáˆ½áŠ›";}s:2:"ky";a:1:{i:0;s:15:"ኪáˆáŒŠá‹áŠ›";}s:2:"la";a:1:{i:0;s:12:"ላቲንኛ";}s:2:"ln";a:1:{i:0;s:15:"ሊንጋላኛ";}s:2:"lo";a:1:{i:0;s:12:"ላá‹áˆµáŠ›";}s:2:"lt";a:1:{i:0;s:18:"ሊቱአኒያን";}s:2:"lv";a:1:{i:0;s:15:"ላትቪያን";}s:2:"mg";a:1:{i:0;s:15:"ማላጋስኛ";}s:2:"mi";a:1:{i:0;s:12:"ማዮሪኛ";}s:2:"mk";a:1:{i:0;s:15:"ማከዶኒኛ";}s:2:"ml";a:1:{i:0;s:18:"ማላያላáˆáŠ›";}s:2:"mn";a:1:{i:0;s:18:"ሞንጎላዊኛ";}s:2:"mo";a:1:{i:0;s:18:"ሞáˆá‹³á‰«á‹ŠáŠ“";}s:2:"mr";a:1:{i:0;s:12:"ማራዚኛ";}s:2:"ms";a:1:{i:0;s:12:"ማላá‹áŠ›";}s:2:"mt";a:1:{i:0;s:15:"ማáˆá‰²áˆµáŠ›";}s:2:"my";a:1:{i:0;s:12:"ቡáˆáˆ›áŠ›";}s:2:"na";a:1:{i:0;s:9:"ናኡሩ";}s:2:"ne";a:1:{i:0;s:12:"ኔá“ሊኛ";}s:2:"nl";a:1:{i:0;s:6:"ደች";}s:2:"no";a:1:{i:0;s:18:"ኖáˆá‹ŒáŒ‚ያን";}s:2:"oc";a:1:{i:0;s:15:"ኦኪታንኛ";}s:2:"om";a:1:{i:0;s:12:"ኦሮáˆáŠ›";}s:2:"or";a:1:{i:0;s:12:"ኦሪያኛ";}s:2:"pa";a:1:{i:0;s:15:"á“ንጃቢኛ";}s:2:"pl";a:1:{i:0;s:9:"á–ሊሽ";}s:2:"ps";a:1:{i:0;s:12:"á‘ሽቶኛ";}s:2:"pt";a:1:{i:0;s:18:"á–áˆá‰±áŒ‹áˆŠáŠ›";}s:2:"qu";a:1:{i:0;s:9:"ኵቿኛ";}s:2:"rm";a:1:{i:0;s:12:"ሮማንስ";}s:2:"rn";a:1:{i:0;s:12:"ሩንዲኛ";}s:2:"ro";a:1:{i:0;s:15:"ሮማኒያን";}s:2:"ru";a:1:{i:0;s:9:"ራሽኛ";}s:2:"rw";a:1:{i:0;s:24:"ኪንያáˆá‹‹áŠ•á‹µáŠ›";}s:2:"sa";a:1:{i:0;s:21:"ሳንስáŠáˆªá‰µáŠ›";}s:2:"sd";a:1:{i:0;s:15:"ሲንድሂኛ";}s:2:"sg";a:1:{i:0;s:12:"ሳንጎኛ";}s:2:"si";a:1:{i:0;s:15:"ስንሃáˆáŠ›";}s:3:"sid";a:1:{i:0;s:12:"ሲዳáˆáŠ›";}s:2:"sk";a:1:{i:0;s:15:"ስሎቫáŠáŠ›";}s:2:"sl";a:1:{i:0;s:12:"ስሎቪኛ";}s:2:"sm";a:1:{i:0;s:12:"ሳሞአኛ";}s:2:"sn";a:1:{i:0;s:9:"ሾናኛ";}s:2:"so";a:1:{i:0;s:12:"ሱማáˆáŠ›";}s:2:"sq";a:1:{i:0;s:12:"áˆá‰¤áŠ’ኛ";}s:2:"sr";a:1:{i:0;s:12:"ሰáˆá‰¢áŠ›";}s:2:"ss";a:1:{i:0;s:12:"ስዋቲኛ";}s:2:"st";a:1:{i:0;s:9:"ሶዞኛ";}s:2:"su";a:1:{i:0;s:12:"ሱዳንኛ";}s:2:"sv";a:1:{i:0;s:15:"ስዊድንኛ";}s:2:"sw";a:1:{i:0;s:15:"ስዋሂሊኛ";}s:2:"ta";a:1:{i:0;s:12:"ታሚáˆáŠ›";}s:2:"te";a:1:{i:0;s:12:"ተሉጉኛ";}s:2:"tg";a:1:{i:0;s:12:"ታጂኪኛ";}s:2:"th";a:1:{i:0;s:9:"ታá‹áŠ›";}s:2:"ti";a:1:{i:0;s:12:"ትáŒáˆáŠ›";}s:3:"tig";a:1:{i:0;s:9:"ትáŒáˆ¨";}s:2:"tk";a:1:{i:0;s:18:"ቱáˆáŠáˆ˜áŠ•áŠ›";}s:2:"tl";a:1:{i:0;s:15:"ታጋሎገኛ";}s:2:"tn";a:1:{i:0;s:15:"ጽዋናዊኛ";}s:2:"to";a:1:{i:0;s:9:"ቶንጋ";}s:2:"tr";a:1:{i:0;s:12:"ቱáˆáŠáŠ›";}s:2:"ts";a:1:{i:0;s:12:"ጾንጋኛ";}s:2:"tt";a:1:{i:0;s:12:"ታታáˆáŠ›";}s:2:"tw";a:1:{i:0;s:9:"ትዊኛ";}s:2:"ug";a:1:{i:0;s:18:"ኡዊáŒáˆáˆáŠ›";}s:2:"uk";a:1:{i:0;s:15:"á‹©áŠáˆ¨áŠ’ኛ";}s:2:"ur";a:1:{i:0;s:12:"ኡáˆá‹±áŠ›";}s:2:"uz";a:1:{i:0;s:15:"ኡá‹á‰ áŠáŠ›";}s:2:"vi";a:1:{i:0;s:15:"ቪትናáˆáŠ›";}s:2:"vo";a:1:{i:0;s:15:"ቮላá‘áŠáŠ›";}s:2:"wo";a:1:{i:0;s:12:"ዎሎáኛ";}s:2:"xh";a:1:{i:0;s:9:"ዞሳኛ";}s:2:"yi";a:1:{i:0;s:15:"á‹á‹²áˆ»á‹ŠáŠ›";}s:2:"yo";a:1:{i:0;s:15:"ዮሩባዊኛ";}s:2:"za";a:1:{i:0;s:15:"ዡዋንáŒáŠ›";}s:2:"zh";a:1:{i:0;s:12:"ቻá‹áŠ•áŠ›";}s:2:"zu";a:1:{i:0;s:9:"ዙሉኛ";}}s:12:"LocaleScript";a:1:{i:0;s:4:"Ethi";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:4:{s:26:"DateTimeElements:intvector";a:2:{i:0;i:7;i:1;i:1;}s:8:"dayNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:7:{i:0;s:9:"እሑድ";i:1;s:6:"ሰኞ";i:2;s:9:"ማáŠáˆ°";i:3;s:9:"ረቡዕ";i:4;s:9:"áˆáˆ™áˆµ";i:5;s:9:"á‹“áˆá‰¥";i:6;s:9:"ቅዳሜ";}s:4:"wide";a:7:{i:0;s:9:"እሑድ";i:1;s:6:"ሰኞ";i:2;s:12:"ማáŠáˆ°áŠž";i:3;s:9:"ረቡዕ";i:4;s:9:"áˆáˆ™áˆµ";i:5;s:9:"á‹“áˆá‰¥";i:6;s:9:"ቅዳሜ";}}}s:4:"eras";a:1:{s:11:"abbreviated";a:2:{i:0;s:7:"á‹“/á‹“";i:1;s:7:"á‹“/áˆ";}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:12:{i:0;s:9:"ጃንዩ";i:1;s:9:"áŒá‰¥áˆ©";i:2;s:9:"ማáˆá‰½";i:3;s:9:"ኤá•áˆ¨";i:4;s:6:"ሜá‹";i:5;s:6:"áŒáŠ•";i:6;s:9:"áŒáˆ‹á‹";i:7;s:9:"ኦገስ";i:8;s:9:"ሴá•á‰´";i:9;s:9:"ኦáŠá‰°";i:10;s:9:"ኖቬáˆ";i:11;s:9:"ዲሴáˆ";}s:4:"wide";a:12:{i:0;s:15:"ጃንዩወሪ";i:1;s:15:"áŒá‰¥áˆ©á‹ˆáˆª";i:2;s:9:"ማáˆá‰½";i:3;s:12:"ኤá•áˆ¨áˆ";i:4;s:6:"ሜá‹";i:5;s:6:"áŒáŠ•";i:6;s:9:"áŒáˆ‹á‹";i:7;s:12:"ኦገስት";i:8;s:18:"ሴá•á‰´áˆá‰ áˆ";i:9;s:18:"ኦáŠá‰°á‹á‰ áˆ";i:10;s:15:"ኖቬáˆá‰ áˆ";i:11;s:15:"ዲሴáˆá‰ áˆ";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/am_ET.dat b/framework/I18N/core/data/am_ET.dat
new file mode 100644
index 00000000..673caa42
--- /dev/null
+++ b/framework/I18N/core/data/am_ET.dat
@@ -0,0 +1 @@
+a:4:{s:10:"Currencies";a:2:{s:3:"ETB";a:2:{i:0;s:1:"$";i:1;s:3:"ETB";}s:3:"USD";a:2:{i:0;s:3:"US$";i:1;s:3:"USD";}}s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;-#,##0.###";i:1;s:22:"¤#,##0.00;-¤#,##0.00";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:2:{s:11:"AmPmMarkers";a:2:{i:0;s:9:"ጡዋት";i:1;s:12:"ከሳዓት";}s:16:"DateTimePatterns";a:9:{i:0;s:10:"hh:mm:ss a";i:1;s:10:"hh:mm:ss a";i:2;s:9:"h:mm:ss a";i:3;s:6:"h:mm a";i:4;s:29:"EEEEᣠdd MMMM ቀን yyyy G";i:5;s:12:"dd MMMM yyyy";i:6;s:9:"dd-MMM-yy";i:7;s:8:"dd/MM/yy";i:8;s:7:"{1} {0}";}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar.dat b/framework/I18N/core/data/ar.dat
new file mode 100644
index 00000000..aa8d5538
--- /dev/null
+++ b/framework/I18N/core/data/ar.dat
@@ -0,0 +1 @@
+a:12:{s:9:"Countries";a:190:{s:2:"AD";a:1:{i:0;s:12:"اندورا";}s:2:"AE";a:1:{i:0;s:46:"الامارات العربية المتØدة";}s:2:"AF";a:1:{i:0;s:18:"اÙغانستان";}s:2:"AG";a:1:{i:0;s:29:"انتيغوا وبربودا";}s:2:"AI";a:1:{i:0;s:14:"البانيا";}s:2:"AM";a:1:{i:0;s:14:"ارمينيا";}s:2:"AO";a:1:{i:0;s:12:"انغولا";}s:2:"AR";a:1:{i:0;s:18:"الارجنتين";}s:2:"AT";a:1:{i:0;s:12:"النمسا";}s:2:"AU";a:1:{i:0;s:16:"استراليا";}s:2:"AZ";a:1:{i:0;s:16:"آذربيجان";}s:2:"BA";a:1:{i:0;s:29:"البوسنة والهرسك";}s:2:"BB";a:1:{i:0;s:14:"بربادوس";}s:2:"BD";a:1:{i:0;s:16:"بنغلاديش";}s:2:"BE";a:1:{i:0;s:12:"بلجيكا";}s:2:"BF";a:1:{i:0;s:23:"بوركينا Ùاسو";}s:2:"BG";a:1:{i:0;s:14:"بلغاريا";}s:2:"BH";a:1:{i:0;s:14:"البØرين";}s:2:"BI";a:1:{i:0;s:14:"بوروندي";}s:2:"BJ";a:1:{i:0;s:8:"بنين";}s:2:"BN";a:1:{i:0;s:12:"بروناي";}s:2:"BO";a:1:{i:0;s:14:"بوليÙيا";}s:2:"BR";a:1:{i:0;s:16:"البرازيل";}s:2:"BS";a:1:{i:0;s:14:"البهاما";}s:2:"BT";a:1:{i:0;s:10:"بوتان";}s:2:"BW";a:1:{i:0;s:16:"بوتسوانا";}s:2:"BY";a:1:{i:0;s:25:"روسيا البيضاء";}s:2:"BZ";a:1:{i:0;s:8:"بليز";}s:2:"CA";a:1:{i:0;s:8:"كندا";}s:2:"CF";a:1:{i:0;s:42:"جمهورية اÙريقيا الوسطى";}s:2:"CG";a:1:{i:0;s:14:"الكونغو";}s:2:"CH";a:1:{i:0;s:12:"سويسرا";}s:2:"CL";a:1:{i:0;s:10:"تشيلي";}s:2:"CM";a:1:{i:0;s:18:"الكاميرون";}s:2:"CN";a:1:{i:0;s:10:"الصين";}s:2:"CO";a:1:{i:0;s:16:"كولومبيا";}s:2:"CR";a:1:{i:0;s:18:"كوستاريكا";}s:2:"CU";a:1:{i:0;s:8:"كوبا";}s:2:"CV";a:1:{i:0;s:23:"الرأس الاخضر";}s:2:"CY";a:1:{i:0;s:8:"قبرص";}s:2:"CZ";a:1:{i:0;s:27:"جمهورية التشيك";}s:2:"DE";a:1:{i:0;s:14:"المانيا";}s:2:"DJ";a:1:{i:0;s:12:"جيبوتي";}s:2:"DK";a:1:{i:0;s:16:"الدانمرك";}s:2:"DM";a:1:{i:0;s:16:"دومينيكا";}s:2:"DO";a:1:{i:0;s:41:"الجمهورية الدومينيكية";}s:2:"DZ";a:1:{i:0;s:14:"الجزائر";}s:2:"EC";a:1:{i:0;s:14:"اكوادور";}s:2:"EE";a:1:{i:0;s:14:"استونيا";}s:2:"EG";a:1:{i:0;s:6:"مصر";}s:2:"EH";a:1:{i:0;s:29:"الصØراء الغربية";}s:2:"ER";a:1:{i:0;s:14:"ارتيريا";}s:2:"ES";a:1:{i:0;s:14:"اسبانيا";}s:2:"ET";a:1:{i:0;s:14:"اثيوبيا";}s:2:"FI";a:1:{i:0;s:12:"Ùنلندا";}s:2:"FJ";a:1:{i:0;s:8:"Ùيجي";}s:2:"FM";a:1:{i:0;s:20:"ميكرونيزيا";}s:2:"FR";a:1:{i:0;s:10:"Ùرنسا";}s:2:"GA";a:1:{i:0;s:10:"غابون";}s:2:"GB";a:1:{i:0;s:29:"المملكة المتØدة";}s:2:"GD";a:1:{i:0;s:14:"غرينادا";}s:2:"GE";a:1:{i:0;s:12:"جورجيا";}s:2:"GH";a:1:{i:0;s:8:"غانا";}s:2:"GM";a:1:{i:0;s:12:"غامبيا";}s:2:"GN";a:1:{i:0;s:10:"غينيا";}s:2:"GQ";a:1:{i:0;s:31:"غينيا الاستوائية";}s:2:"GR";a:1:{i:0;s:14:"اليونان";}s:2:"GT";a:1:{i:0;s:18:"غواتيمالا";}s:2:"GW";a:1:{i:0;s:21:"غينيا بيساو";}s:2:"GY";a:1:{i:0;s:14:"غوايانا";}s:2:"HN";a:1:{i:0;s:14:"هندوراس";}s:2:"HR";a:1:{i:0;s:14:"كرواتيا";}s:2:"HT";a:1:{i:0;s:10:"هايتي";}s:2:"HU";a:1:{i:0;s:14:"هنغاريا";}s:2:"ID";a:1:{i:0;s:18:"اندونيسيا";}s:2:"IE";a:1:{i:0;s:14:"ايرلندا";}s:2:"IL";a:1:{i:0;s:14:"اسرائيل";}s:2:"IN";a:1:{i:0;s:10:"الهند";}s:2:"IQ";a:1:{i:0;s:12:"العراق";}s:2:"IR";a:1:{i:0;s:10:"ايران";}s:2:"IS";a:1:{i:0;s:14:"ايسلندا";}s:2:"IT";a:1:{i:0;s:14:"ايطاليا";}s:2:"JM";a:1:{i:0;s:14:"جامايكا";}s:2:"JO";a:1:{i:0;s:12:"الاردن";}s:2:"JP";a:1:{i:0;s:14:"اليابان";}s:2:"KE";a:1:{i:0;s:10:"كينيا";}s:2:"KG";a:1:{i:0;s:20:"قيرغيزستان";}s:2:"KH";a:1:{i:0;s:14:"كمبوديا";}s:2:"KI";a:1:{i:0;s:16:"كيريباتي";}s:2:"KM";a:1:{i:0;s:17:"جزر القمر";}s:2:"KN";a:1:{i:0;s:30:"سانت كيتس ونيÙيس";}s:2:"KP";a:1:{i:0;s:27:"كوريا الشمالية";}s:2:"KR";a:1:{i:0;s:27:"كوريا الجنوبية";}s:2:"KW";a:1:{i:0;s:12:"الكويت";}s:2:"KZ";a:1:{i:0;s:18:"كازاخستان";}s:2:"LA";a:1:{i:0;s:8:"لاوس";}s:2:"LB";a:1:{i:0;s:10:"لبنان";}s:2:"LC";a:1:{i:0;s:19:"سانت لوسيا";}s:2:"LI";a:1:{i:0;s:20:"ليختنشتاين";}s:2:"LK";a:1:{i:0;s:17:"سري لانكا";}s:2:"LR";a:1:{i:0;s:14:"ليبيريا";}s:2:"LS";a:1:{i:0;s:12:"ليسوتو";}s:2:"LT";a:1:{i:0;s:16:"ليتوانيا";}s:2:"LU";a:1:{i:0;s:18:"لوكسومبرغ";}s:2:"LV";a:1:{i:0;s:12:"لاتÙيا";}s:2:"LY";a:1:{i:0;s:10:"ليبيا";}s:2:"MA";a:1:{i:0;s:12:"المغرب";}s:2:"MC";a:1:{i:0;s:12:"موناكو";}s:2:"MD";a:1:{i:0;s:14:"مولدوÙا";}s:2:"MG";a:1:{i:0;s:12:"مدغشقر";}s:2:"MH";a:1:{i:0;s:23:"جزر المارشال";}s:2:"MK";a:1:{i:0;s:14:"مقدونيا";}s:2:"ML";a:1:{i:0;s:8:"مالي";}s:2:"MM";a:1:{i:0;s:14:"ميانمار";}s:2:"MN";a:1:{i:0;s:14:"منغوليا";}s:2:"MR";a:1:{i:0;s:18:"موريتانيا";}s:2:"MT";a:1:{i:0;s:10:"مالطة";}s:2:"MU";a:1:{i:0;s:14:"موريشوس";}s:2:"MV";a:1:{i:0;s:12:"مالديÙ";}s:2:"MW";a:1:{i:0;s:10:"ملاوي";}s:2:"MX";a:1:{i:0;s:14:"المكسيك";}s:2:"MY";a:1:{i:0;s:14:"ماليزيا";}s:2:"MZ";a:1:{i:0;s:14:"موزمبيق";}s:2:"NA";a:1:{i:0;s:14:"ناميبيا";}s:2:"NE";a:1:{i:0;s:12:"النيجر";}s:2:"NG";a:1:{i:0;s:14:"نيجيريا";}s:2:"NI";a:1:{i:0;s:18:"نيكاراغوا";}s:2:"NL";a:1:{i:0;s:12:"هولندا";}s:2:"NO";a:1:{i:0;s:14:"النرويج";}s:2:"NP";a:1:{i:0;s:14:"النيبال";}s:2:"NR";a:1:{i:0;s:10:"ناورو";}s:2:"NZ";a:1:{i:0;s:27:"زيلندا الجديدة";}s:2:"OM";a:1:{i:0;s:8:"عمان";}s:2:"PA";a:1:{i:0;s:8:"بنما";}s:2:"PE";a:1:{i:0;s:8:"بيرو";}s:2:"PG";a:1:{i:0;s:36:"بابوا غينيا الجديدة";}s:2:"PH";a:1:{i:0;s:16:"الÙيلبين";}s:2:"PK";a:1:{i:0;s:18:"الباكستان";}s:2:"PL";a:1:{i:0;s:12:"بولندا";}s:2:"PT";a:1:{i:0;s:16:"البرتغال";}s:2:"PW";a:1:{i:0;s:10:"بالاو";}s:2:"PY";a:1:{i:0;s:16:"باراغواي";}s:2:"QA";a:1:{i:0;s:6:"قطر";}s:2:"RO";a:1:{i:0;s:14:"رومانيا";}s:2:"RU";a:1:{i:0;s:10:"روسيا";}s:2:"RW";a:1:{i:0;s:12:"رواندا";}s:2:"SA";a:1:{i:0;s:31:"العربية السعودية";}s:2:"SB";a:1:{i:0;s:19:"جزر سليمان";}s:2:"SC";a:1:{i:0;s:8:"سيشل";}s:2:"SD";a:1:{i:0;s:14:"السودان";}s:2:"SE";a:1:{i:0;s:12:"السويد";}s:2:"SG";a:1:{i:0;s:16:"سنغاÙورة";}s:2:"SI";a:1:{i:0;s:16:"سلوÙينيا";}s:2:"SK";a:1:{i:0;s:16:"سلوÙاكيا";}s:2:"SL";a:1:{i:0;s:16:"سيراليون";}s:2:"SM";a:1:{i:0;s:19:"سان مارينو";}s:2:"SN";a:1:{i:0;s:14:"السنغال";}s:2:"SO";a:1:{i:0;s:14:"الصومال";}s:2:"SR";a:1:{i:0;s:14:"سورينام";}s:2:"ST";a:1:{i:0;s:34:"سان تومي وبرينسيبي";}s:2:"SV";a:1:{i:0;s:18:"السلÙادور";}s:2:"SY";a:1:{i:0;s:10:"سورية";}s:2:"SZ";a:1:{i:0;s:18:"سوازيلاند";}s:2:"TD";a:1:{i:0;s:8:"تشاد";}s:2:"TG";a:1:{i:0;s:8:"توغو";}s:2:"TH";a:1:{i:0;s:12:"تايلند";}s:2:"TJ";a:1:{i:0;s:18:"تاجيكستان";}s:2:"TM";a:1:{i:0;s:20:"تركمانستان";}s:2:"TN";a:1:{i:0;s:8:"تونس";}s:2:"TO";a:1:{i:0;s:10:"تونغا";}s:2:"TR";a:1:{i:0;s:10:"تركيا";}s:2:"TT";a:1:{i:0;s:31:"ترينيداد وتوباغو";}s:2:"TV";a:1:{i:0;s:12:"توÙالو";}s:2:"TW";a:1:{i:0;s:12:"تايوان";}s:2:"TZ";a:1:{i:0;s:16:"تانزانيا";}s:2:"UA";a:1:{i:0;s:16:"اوكرانيا";}s:2:"UG";a:1:{i:0;s:12:"اوغندا";}s:2:"US";a:1:{i:0;s:52:"الاولايات المتØدة الامريكية";}s:2:"UY";a:1:{i:0;s:14:"اروغواي";}s:2:"UZ";a:1:{i:0;s:16:"ازبكستان";}s:2:"VA";a:1:{i:0;s:18:"الÙاتيكان";}s:2:"VC";a:1:{i:0;s:45:"سانت Ùنسنت وجزر غرينادين";}s:2:"VE";a:1:{i:0;s:14:"Ùنزويلا";}s:2:"VN";a:1:{i:0;s:12:"Ùيتنام";}s:2:"VU";a:1:{i:0;s:14:"Ùانوآتو";}s:2:"WS";a:1:{i:0;s:10:"ساموا";}s:2:"YE";a:1:{i:0;s:10:"اليمن";}s:2:"ZA";a:1:{i:0;s:23:"جنوب اÙريقيا";}s:2:"ZM";a:1:{i:0;s:12:"زامبيا";}s:2:"ZW";a:1:{i:0;s:16:"زيمبابوي";}}s:10:"Currencies";a:17:{s:3:"AED";a:2:{i:0;s:9:"د.Ø¥.â€";i:1;s:3:"AED";}s:3:"BHD";a:2:{i:0;s:9:"د.ب.â€";i:1;s:3:"BHD";}s:3:"DZD";a:2:{i:0;s:9:"د.ج.â€";i:1;s:3:"DZD";}s:3:"EGP";a:2:{i:0;s:9:"ج.Ù….â€";i:1;s:3:"EGP";}s:3:"IQD";a:2:{i:0;s:9:"د.ع.â€";i:1;s:3:"IQD";}s:3:"JOD";a:2:{i:0;s:9:"د.Ø£.â€";i:1;s:3:"JOD";}s:3:"KWD";a:2:{i:0;s:9:"د.Ùƒ.â€";i:1;s:3:"KWD";}s:3:"LBP";a:2:{i:0;s:9:"Ù„.Ù„.â€";i:1;s:3:"LBP";}s:3:"LYD";a:2:{i:0;s:9:"د.Ù„.â€";i:1;s:3:"LYD";}s:3:"MAD";a:2:{i:0;s:9:"د.Ù….â€";i:1;s:3:"MAD";}s:3:"OMR";a:2:{i:0;s:9:"ر.ع.â€";i:1;s:3:"OMR";}s:3:"QAR";a:2:{i:0;s:9:"ر.Ù‚.â€";i:1;s:3:"QAR";}s:3:"SAR";a:2:{i:0;s:9:"ر.س.â€";i:1;s:3:"SAR";}s:3:"SDP";a:2:{i:0;s:9:"ج.س.â€";i:1;s:3:"SDP";}s:3:"SYP";a:2:{i:0;s:9:"Ù„.س.â€";i:1;s:3:"SYP";}s:3:"TND";a:2:{i:0;s:9:"د.ت.â€";i:1;s:3:"TND";}s:3:"YER";a:2:{i:0;s:9:"ر.ÙŠ.â€";i:1;s:3:"YER";}}s:4:"Keys";a:3:{s:8:"calendar";a:1:{i:0;s:10:"تقويم";}s:9:"collation";a:1:{i:0;s:14:"الترتيب";}s:8:"currency";a:1:{i:0;s:14:"العملات";}}s:9:"Languages";a:79:{s:2:"aa";a:1:{i:0;s:16:"الاÙارية";}s:2:"ab";a:1:{i:0;s:18:"الابخازية";}s:2:"af";a:1:{i:0;s:18:"الاÙريقية";}s:3:"afa";a:1:{i:0;s:21:"اÙرو-اسيوية";}s:3:"ang";a:1:{i:0;s:27:"انكليزية، قديم";}s:2:"ar";a:1:{i:0;s:14:"العربية";}s:3:"arc";a:1:{i:0;s:16:"الارامية";}s:2:"az";a:1:{i:0;s:10:"اذرية";}s:3:"bal";a:1:{i:0;s:16:"البلوشية";}s:2:"be";a:1:{i:0;s:22:"البيلوروسية";}s:3:"ber";a:1:{i:0;s:16:"البربرية";}s:2:"bg";a:1:{i:0;s:18:"البلغارية";}s:2:"bn";a:1:{i:0;s:18:"البنغالية";}s:2:"bo";a:1:{i:0;s:14:"التبتية";}s:2:"bs";a:1:{i:0;s:16:"البوسنية";}s:2:"ca";a:1:{i:0;s:24:"الكاتالوينية";}s:2:"ce";a:1:{i:0;s:18:"الشيشانية";}s:3:"cop";a:1:{i:0;s:10:"قبطية";}s:2:"cs";a:1:{i:0;s:16:"التشيكية";}s:2:"cy";a:1:{i:0;s:14:"الولزية";}s:2:"da";a:1:{i:0;s:22:"الدانماركية";}s:2:"de";a:1:{i:0;s:18:"الالمانية";}s:2:"dv";a:1:{i:0;s:20:"المالديÙية";}s:2:"dz";a:1:{i:0;s:18:"الزونخاية";}s:3:"egy";a:1:{i:0;s:23:"مصرية، قديمة";}s:2:"el";a:1:{i:0;s:18:"اليونانية";}s:2:"en";a:1:{i:0;s:20:"الانجليزية";}s:2:"eo";a:1:{i:0;s:16:"اسبرانتو";}s:2:"es";a:1:{i:0;s:18:"الاسبانية";}s:2:"et";a:1:{i:0;s:14:"استونية";}s:2:"fa";a:1:{i:0;s:16:"الÙارسية";}s:2:"fi";a:1:{i:0;s:18:"الÙنلندية";}s:2:"fj";a:1:{i:0;s:14:"الÙيجية";}s:2:"fr";a:1:{i:0;s:16:"الÙرنسية";}s:2:"gu";a:1:{i:0;s:22:"الغوجاراتية";}s:2:"he";a:1:{i:0;s:14:"العبرية";}s:2:"hi";a:1:{i:0;s:14:"الهندية";}s:2:"hr";a:1:{i:0;s:18:"الكرواتية";}s:2:"ht";a:1:{i:0;s:16:"الهايتية";}s:2:"hu";a:1:{i:0;s:18:"الهنغارية";}s:2:"hy";a:1:{i:0;s:16:"الارمنية";}s:2:"id";a:1:{i:0;s:22:"الاندونيسية";}s:3:"ira";a:1:{i:0;s:18:"الايرانية";}s:2:"it";a:1:{i:0;s:18:"الايطالية";}s:2:"ja";a:1:{i:0;s:18:"اليابانية";}s:2:"km";a:1:{i:0;s:16:"الخميرية";}s:2:"ko";a:1:{i:0;s:14:"الكورية";}s:2:"ks";a:1:{i:0;s:20:"الكاشميرية";}s:2:"ku";a:1:{i:0;s:14:"الكردية";}s:2:"la";a:1:{i:0;s:18:"اللاتينية";}s:2:"lt";a:1:{i:0;s:18:"اللتوانية";}s:2:"lv";a:1:{i:0;s:16:"اللاتÙية";}s:2:"mn";a:1:{i:0;s:18:"المنغولية";}s:2:"ms";a:1:{i:0;s:21:"لغة الملايو";}s:2:"mt";a:1:{i:0;s:16:"المالطية";}s:2:"my";a:1:{i:0;s:16:"البورمية";}s:2:"ne";a:1:{i:0;s:18:"النيبالية";}s:2:"nl";a:1:{i:0;s:18:"الهولندية";}s:2:"pa";a:1:{i:0;s:18:"البنجابية";}s:2:"pl";a:1:{i:0;s:18:"البولونية";}s:2:"ps";a:1:{i:0;s:18:"البشتونية";}s:2:"pt";a:1:{i:0;s:20:"البرتغالية";}s:2:"ro";a:1:{i:0;s:18:"الرومانية";}s:2:"ru";a:1:{i:0;s:14:"الروسية";}s:3:"smi";a:1:{i:0;s:27:"اللغات السامية";}s:2:"sq";a:1:{i:0;s:18:"الالبانية";}s:2:"sr";a:1:{i:0;s:14:"الصربية";}s:2:"sv";a:1:{i:0;s:16:"السويدية";}s:2:"sw";a:1:{i:0;s:18:"السواØلية";}s:3:"syr";a:1:{i:0;s:18:"السريانية";}s:2:"th";a:1:{i:0;s:22:"التايلاندية";}s:2:"tl";a:1:{i:0;s:22:"التاغالوغية";}s:2:"tr";a:1:{i:0;s:14:"التركية";}s:2:"tt";a:1:{i:0;s:14:"التترية";}s:2:"ug";a:1:{i:0;s:16:"الاغورية";}s:2:"uk";a:1:{i:0;s:20:"الاوكرانية";}s:2:"ur";a:1:{i:0;s:14:"الاردية";}s:2:"vi";a:1:{i:0;s:20:"الÙيتنامية";}s:2:"zh";a:1:{i:0;s:14:"الصينية";}}s:12:"LocaleScript";a:1:{i:0;s:4:"Arab";}s:14:"NumberElements";a:12:{i:0;s:2:"Ù«";i:1;s:2:"Ù¬";i:2;s:1:";";i:3;s:2:"Ùª";i:4;s:2:"Ù ";i:5;s:1:"#";i:6;s:1:"-";i:7;s:1:"E";i:8;s:3:"‰";i:9;s:3:"∞";i:10;s:3:"�";i:11;s:1:"+";}s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;#,##0.###-";i:1;s:24:"¤ #,##0.00;¤ #,##0.00-";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Scripts";a:19:{s:4:"Arab";a:1:{i:0;s:14:"العربية";}s:4:"Armn";a:1:{i:0;s:16:"الارمنية";}s:4:"Beng";a:1:{i:0;s:18:"البنغالية";}s:4:"Brai";a:1:{i:0;s:10:"برايل";}s:4:"Copt";a:1:{i:0;s:14:"القبطية";}s:4:"Cprt";a:1:{i:0;s:16:"القبرصية";}s:4:"Ethi";a:1:{i:0;s:18:"الاثيوبية";}s:4:"Geor";a:1:{i:0;s:16:"الجورجية";}s:4:"Grek";a:1:{i:0;s:18:"اليونانية";}s:4:"Gujr";a:1:{i:0;s:18:"تاغجراتية";}s:4:"Hebr";a:1:{i:0;s:14:"العبرية";}s:4:"Khmr";a:1:{i:0;s:16:"الخميرية";}s:4:"Latn";a:1:{i:0;s:16:"اللاتنية";}s:4:"Mong";a:1:{i:0;s:16:"المغولية";}s:4:"Syrc";a:1:{i:0;s:18:"السريانية";}s:4:"Taml";a:1:{i:0;s:14:"التاميل";}s:4:"Tglg";a:1:{i:0;s:20:"التغالوغية";}s:4:"Thai";a:1:{i:0;s:20:"التايلندية";}s:4:"Tibt";a:1:{i:0;s:14:"التبتية";}}s:5:"Types";a:2:{s:8:"calendar";a:7:{s:8:"buddhist";a:1:{i:0;s:19:"تقويم بوني";}s:7:"chinese";a:1:{i:0;s:19:"تقويم صيني";}s:9:"gregorian";a:1:{i:0;s:23:"تقويم ميلادي";}s:6:"hebrew";a:1:{i:0;s:19:"تقويم عبري";}s:7:"islamic";a:1:{i:0;s:23:"تقويم اسلامي";}s:13:"islamic-civil";a:1:{i:0;s:32:"تقويم اسلامي مدني";}s:8:"japanese";a:1:{i:0;s:23:"تقويم ياباني";}}s:9:"collation";a:3:{s:6:"direct";a:1:{i:0;s:21:"ترتيب مباشر";}s:9:"phonebook";a:1:{i:0;s:32:"ترتيب دليل الهاتÙ";}s:11:"traditional";a:1:{i:0;s:12:"تقليدي";}}}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:4:{s:8:"buddhist";a:1:{s:4:"eras";a:1:{s:11:"abbreviated";a:1:{i:0;s:27:"التقويم البوذي";}}}s:9:"gregorian";a:7:{s:11:"AmPmMarkers";a:2:{i:0;s:2:"ص";i:1;s:2:"Ù…";}s:26:"DateTimeElements:intvector";a:2:{i:0;i:7;i:1;i:1;}s:16:"DateTimePatterns";a:9:{i:0;s:11:"z h:mm:ss a";i:1;s:9:"h:mm:ss a";i:2;s:9:"h:mm:ss a";i:3;s:6:"h:mm a";i:4;s:18:"EEEE, d MMMM, yyyy";i:5;s:12:"d MMMM, yyyy";i:6;s:10:"dd/MM/yyyy";i:7;s:8:"d/M/yyyy";i:8;s:7:"{1} {0}";}s:8:"dayNames";a:1:{s:6:"format";a:3:{s:11:"abbreviated";a:7:{i:0;s:2:"Ø";i:1;s:2:"Ù†";i:2;s:2:"Ø«";i:3;s:2:"ر";i:4;s:2:"Ø®";i:5;s:2:"ج";i:6;s:2:"س";}s:6:"narrow";a:7:{i:0;s:2:"Ø";i:1;s:2:"Ù†";i:2;s:2:"Ø«";i:3;s:2:"ر";i:4;s:2:"Ø®";i:5;s:2:"ج";i:6;s:2:"س";}s:4:"wide";a:7:{i:0;s:10:"الأØد";i:1;s:14:"الاثنين";i:2;s:16:"الثلاثاء";i:3;s:16:"الأربعاء";i:4;s:12:"الخميس";i:5;s:12:"الجمعة";i:6;s:10:"السبت";}}}s:4:"eras";a:1:{s:11:"abbreviated";a:2:{i:0;s:5:"Ù‚.Ù…";i:1;s:2:"Ù…";}}s:10:"monthNames";a:1:{s:6:"format";a:3:{s:11:"abbreviated";a:12:{i:0;s:10:"يناير";i:1;s:12:"Ùبراير";i:2;s:8:"مارس";i:3;s:10:"أبريل";i:4;s:8:"مايو";i:5;s:10:"يونيو";i:6;s:10:"يوليو";i:7;s:10:"أغسطس";i:8;s:12:"سبتمبر";i:9;s:12:"أكتوبر";i:10;s:12:"نوÙمبر";i:11;s:12:"ديسمبر";}s:6:"narrow";a:12:{i:0;s:2:"ÙŠ";i:1;s:2:"Ù";i:2;s:2:"Ù…";i:3;s:2:"Ø¢";i:4;s:2:"Ùˆ";i:5;s:2:"Ù†";i:6;s:2:"Ù„";i:7;s:2:"غ";i:8;s:2:"س";i:9;s:2:"Ùƒ";i:10;s:2:"ب";i:11;s:2:"د";}s:4:"wide";a:12:{i:0;s:10:"يناير";i:1;s:12:"Ùبراير";i:2;s:8:"مارس";i:3;s:10:"أبريل";i:4;s:8:"مايو";i:5;s:10:"يونيو";i:6;s:10:"يوليو";i:7;s:10:"أغسطس";i:8;s:12:"سبتمبر";i:9;s:12:"أكتوبر";i:10;s:12:"نوÙمبر";i:11;s:12:"ديسمبر";}}}s:17:"weekend:intvector";a:4:{i:0;i:5;i:1;i:0;i:2;i:6;i:3;i:86400000;}}s:7:"islamic";a:2:{s:4:"eras";a:1:{s:11:"abbreviated";a:1:{i:0;s:5:"Ù‡â€";}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:17:"abbreviated:alias";a:1:{i:0;s:42:"ar/calendar/islamic/monthNames/format/wide";}s:4:"wide";a:12:{i:0;s:8:"Ù…Øرم";i:1;s:6:"صÙر";i:2;s:19:"ربيع الأول";i:3;s:19:"ربيع الآخر";i:4;s:23:"جمادى الأولى";i:5;s:23:"جمادى الآخرة";i:6;s:6:"رجب";i:7;s:10:"شعبان";i:8;s:10:"رمضان";i:9;s:8:"شوال";i:10;s:17:"ذو القعدة";i:11;s:15:"ذو الØجة";}}}}s:13:"islamic-civil";a:2:{s:10:"eras:alias";a:1:{i:0;s:24:"ar/calendar/islamic/eras";}s:16:"monthNames:alias";a:1:{i:0;s:30:"ar/calendar/islamic/monthNames";}}}s:17:"localPatternChars";a:1:{i:0;s:24:"GanjkHmsSEDFwWxhKzAeugXZ";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_AE.dat b/framework/I18N/core/data/ar_AE.dat
new file mode 100644
index 00000000..9d38c95d
--- /dev/null
+++ b/framework/I18N/core/data/ar_AE.dat
@@ -0,0 +1 @@
+a:1:{s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_BH.dat b/framework/I18N/core/data/ar_BH.dat
new file mode 100644
index 00000000..9d38c95d
--- /dev/null
+++ b/framework/I18N/core/data/ar_BH.dat
@@ -0,0 +1 @@
+a:1:{s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_DZ.dat b/framework/I18N/core/data/ar_DZ.dat
new file mode 100644
index 00000000..1c3fdb2e
--- /dev/null
+++ b/framework/I18N/core/data/ar_DZ.dat
@@ -0,0 +1 @@
+a:2:{s:14:"NumberElements";a:12:{i:0;s:2:"٫";i:1;s:2:"٬";i:2;s:1:";";i:3;s:2:"٪";i:4;s:1:"0";i:5;s:1:"#";i:6;s:1:"-";i:7;s:1:"E";i:8;s:3:"‰";i:9;s:3:"∞";i:10;s:3:"�";i:11;s:1:"+";}s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_EG.dat b/framework/I18N/core/data/ar_EG.dat
new file mode 100644
index 00000000..ab1883f4
--- /dev/null
+++ b/framework/I18N/core/data/ar_EG.dat
@@ -0,0 +1 @@
+a:2:{s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:1:{s:17:"weekend:intvector";a:4:{i:0;i:6;i:1;i:0;i:2;i:7;i:3;i:86400000;}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_IN.dat b/framework/I18N/core/data/ar_IN.dat
new file mode 100644
index 00000000..e13234cb
--- /dev/null
+++ b/framework/I18N/core/data/ar_IN.dat
@@ -0,0 +1 @@
+a:3:{s:14:"NumberPatterns";a:4:{i:0;s:28:"##,##,##0.###;-##,##,##0.###";i:1;s:32:"¤ ##,##,##0.00;-¤ ##,##,##0.00";i:2;s:10:"##,##,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:3:{s:26:"DateTimeElements:intvector";a:2:{i:0;i:2;i:1;i:1;}s:16:"DateTimePatterns";a:9:{i:0;s:11:"h:mm:ss a z";i:1;s:11:"h:mm:ss a z";i:2;s:9:"h:mm:ss a";i:3;s:6:"h:mm a";i:4;s:16:"EEEE d MMMM yyyy";i:5;s:11:"d MMMM yyyy";i:6;s:10:"dd-MM-yyyy";i:7;s:6:"d-M-yy";i:8;s:7:"{1} {0}";}s:17:"weekend:intvector";a:4:{i:0;i:1;i:1;i:0;i:2;i:1;i:3;i:86400000;}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_IQ.dat b/framework/I18N/core/data/ar_IQ.dat
new file mode 100644
index 00000000..929a0798
--- /dev/null
+++ b/framework/I18N/core/data/ar_IQ.dat
@@ -0,0 +1 @@
+a:2:{s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;#,##0.###-";i:1;s:26:"¤ #,##0.000;¤ #,##0.000-";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_JO.dat b/framework/I18N/core/data/ar_JO.dat
new file mode 100644
index 00000000..78b0d6a1
--- /dev/null
+++ b/framework/I18N/core/data/ar_JO.dat
@@ -0,0 +1 @@
+a:3:{s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;#,##0.###-";i:1;s:26:"¤ #,##0.000;¤ #,##0.000-";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:2:{s:8:"dayNames";a:1:{s:6:"format";a:1:{s:11:"abbreviated";a:7:{i:0;s:10:"الأØد";i:1;s:14:"الاثنين";i:2;s:16:"الثلاثاء";i:3;s:16:"الأربعاء";i:4;s:12:"الخميس";i:5;s:12:"الجمعة";i:6;s:10:"السبت";}}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:12:{i:0;s:23:"كانون الثاني";i:1;s:8:"شباط";i:2;s:8:"آذار";i:3;s:10:"نيسان";i:4;s:8:"أيار";i:5;s:12:"Øزيران";i:6;s:8:"تموز";i:7;s:4:"آب";i:8;s:10:"أيلول";i:9;s:21:"تشرين الأول";i:10;s:23:"تشرين الثاني";i:11;s:21:"كانون الأول";}s:4:"wide";a:12:{i:0;s:23:"كانون الثاني";i:1;s:8:"شباط";i:2;s:8:"آذار";i:3;s:10:"نيسان";i:4;s:8:"أيار";i:5;s:12:"Øزيران";i:6;s:8:"تموز";i:7;s:4:"آب";i:8;s:10:"أيلول";i:9;s:21:"تشرين الأول";i:10;s:23:"تشرين الثاني";i:11;s:21:"كانون الأول";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_KW.dat b/framework/I18N/core/data/ar_KW.dat
new file mode 100644
index 00000000..929a0798
--- /dev/null
+++ b/framework/I18N/core/data/ar_KW.dat
@@ -0,0 +1 @@
+a:2:{s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;#,##0.###-";i:1;s:26:"¤ #,##0.000;¤ #,##0.000-";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_LB.dat b/framework/I18N/core/data/ar_LB.dat
new file mode 100644
index 00000000..92cba531
--- /dev/null
+++ b/framework/I18N/core/data/ar_LB.dat
@@ -0,0 +1 @@
+a:2:{s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:2:{s:8:"dayNames";a:1:{s:6:"format";a:1:{s:11:"abbreviated";a:7:{i:0;s:10:"الأØد";i:1;s:14:"الاثنين";i:2;s:16:"الثلاثاء";i:3;s:16:"الأربعاء";i:4;s:12:"الخميس";i:5;s:12:"الجمعة";i:6;s:10:"السبت";}}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:12:{i:0;s:23:"كانون الثاني";i:1;s:8:"شباط";i:2;s:8:"آذار";i:3;s:10:"نيسان";i:4;s:8:"نوار";i:5;s:12:"Øزيران";i:6;s:8:"تموز";i:7;s:4:"آب";i:8;s:10:"أيلول";i:9;s:21:"تشرين الأول";i:10;s:23:"تشرين الثاني";i:11;s:21:"كانون الأول";}s:4:"wide";a:12:{i:0;s:23:"كانون الثاني";i:1;s:8:"شباط";i:2;s:8:"آذار";i:3;s:10:"نيسان";i:4;s:8:"نوار";i:5;s:12:"Øزيران";i:6;s:8:"تموز";i:7;s:4:"آب";i:8;s:10:"أيلول";i:9;s:21:"تشرين الأول";i:10;s:23:"تشرين الثاني";i:11;s:21:"كانون الأول";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_LY.dat b/framework/I18N/core/data/ar_LY.dat
new file mode 100644
index 00000000..929a0798
--- /dev/null
+++ b/framework/I18N/core/data/ar_LY.dat
@@ -0,0 +1 @@
+a:2:{s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;#,##0.###-";i:1;s:26:"¤ #,##0.000;¤ #,##0.000-";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_MA.dat b/framework/I18N/core/data/ar_MA.dat
new file mode 100644
index 00000000..1c3fdb2e
--- /dev/null
+++ b/framework/I18N/core/data/ar_MA.dat
@@ -0,0 +1 @@
+a:2:{s:14:"NumberElements";a:12:{i:0;s:2:"٫";i:1;s:2:"٬";i:2;s:1:";";i:3;s:2:"٪";i:4;s:1:"0";i:5;s:1:"#";i:6;s:1:"-";i:7;s:1:"E";i:8;s:3:"‰";i:9;s:3:"∞";i:10;s:3:"�";i:11;s:1:"+";}s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_OM.dat b/framework/I18N/core/data/ar_OM.dat
new file mode 100644
index 00000000..9d38c95d
--- /dev/null
+++ b/framework/I18N/core/data/ar_OM.dat
@@ -0,0 +1 @@
+a:1:{s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_QA.dat b/framework/I18N/core/data/ar_QA.dat
new file mode 100644
index 00000000..17db97d7
--- /dev/null
+++ b/framework/I18N/core/data/ar_QA.dat
@@ -0,0 +1 @@
+a:3:{s:14:"NumberPatterns";a:4:{i:0;s:18:"###0.###;###0.###-";i:1;s:20:"¤###0.00;-¤###0.00";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:1:{s:8:"dayNames";a:1:{s:6:"format";a:1:{s:11:"abbreviated";a:7:{i:0;s:10:"الأØد";i:1;s:14:"الاثنين";i:2;s:16:"الثلاثاء";i:3;s:16:"الأربعاء";i:4;s:12:"الخميس";i:5;s:12:"الجمعة";i:6;s:10:"السبت";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_SA.dat b/framework/I18N/core/data/ar_SA.dat
new file mode 100644
index 00000000..17db97d7
--- /dev/null
+++ b/framework/I18N/core/data/ar_SA.dat
@@ -0,0 +1 @@
+a:3:{s:14:"NumberPatterns";a:4:{i:0;s:18:"###0.###;###0.###-";i:1;s:20:"¤###0.00;-¤###0.00";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:1:{s:8:"dayNames";a:1:{s:6:"format";a:1:{s:11:"abbreviated";a:7:{i:0;s:10:"الأØد";i:1;s:14:"الاثنين";i:2;s:16:"الثلاثاء";i:3;s:16:"الأربعاء";i:4;s:12:"الخميس";i:5;s:12:"الجمعة";i:6;s:10:"السبت";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_SD.dat b/framework/I18N/core/data/ar_SD.dat
new file mode 100644
index 00000000..9d38c95d
--- /dev/null
+++ b/framework/I18N/core/data/ar_SD.dat
@@ -0,0 +1 @@
+a:1:{s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_SY.dat b/framework/I18N/core/data/ar_SY.dat
new file mode 100644
index 00000000..7695ad55
--- /dev/null
+++ b/framework/I18N/core/data/ar_SY.dat
@@ -0,0 +1 @@
+a:3:{s:14:"NumberPatterns";a:4:{i:0;s:18:"###0.###;###0.###-";i:1;s:20:"¤###0.00;-¤###0.00";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:4:{s:26:"DateTimeElements:intvector";a:2:{i:0;i:5;i:1;i:1;}s:8:"dayNames";a:1:{s:6:"format";a:1:{s:11:"abbreviated";a:7:{i:0;s:10:"الأØد";i:1;s:14:"الاثنين";i:2;s:16:"الثلاثاء";i:3;s:16:"الأربعاء";i:4;s:12:"الخميس";i:5;s:12:"الجمعة";i:6;s:10:"السبت";}}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:12:{i:0;s:23:"كانون الثاني";i:1;s:8:"شباط";i:2;s:8:"آذار";i:3;s:10:"نيسان";i:4;s:8:"نوار";i:5;s:12:"Øزيران";i:6;s:8:"تموز";i:7;s:4:"آب";i:8;s:10:"أيلول";i:9;s:21:"تشرين الأول";i:10;s:23:"تشرين الثاني";i:11;s:21:"كانون الأول";}s:4:"wide";a:12:{i:0;s:23:"كانون الثاني";i:1;s:8:"شباط";i:2;s:8:"آذار";i:3;s:10:"نيسان";i:4;s:8:"نوار";i:5;s:12:"Øزيران";i:6;s:8:"تموز";i:7;s:4:"آب";i:8;s:10:"أيلول";i:9;s:21:"تشرين الأول";i:10;s:23:"تشرين الثاني";i:11;s:21:"كانون الأول";}}}s:17:"weekend:intvector";a:4:{i:0;i:6;i:1;i:0;i:2;i:7;i:3;i:86400000;}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_TN.dat b/framework/I18N/core/data/ar_TN.dat
new file mode 100644
index 00000000..80c9ef71
--- /dev/null
+++ b/framework/I18N/core/data/ar_TN.dat
@@ -0,0 +1 @@
+a:4:{s:14:"NumberElements";a:12:{i:0;s:2:"Ù«";i:1;s:2:"Ù¬";i:2;s:1:";";i:3;s:2:"Ùª";i:4;s:1:"0";i:5;s:1:"#";i:6;s:1:"-";i:7;s:1:"E";i:8;s:3:"‰";i:9;s:3:"∞";i:10;s:3:"�";i:11;s:1:"+";}s:14:"NumberPatterns";a:4:{i:0;s:18:"###0.###;###0.###-";i:1;s:20:"¤###0.00;-¤###0.00";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:1:{s:8:"dayNames";a:1:{s:6:"format";a:1:{s:11:"abbreviated";a:7:{i:0;s:10:"الأØد";i:1;s:14:"الاثنين";i:2;s:16:"الثلاثاء";i:3;s:16:"الأربعاء";i:4;s:12:"الخميس";i:5;s:12:"الجمعة";i:6;s:10:"السبت";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ar_YE.dat b/framework/I18N/core/data/ar_YE.dat
new file mode 100644
index 00000000..17db97d7
--- /dev/null
+++ b/framework/I18N/core/data/ar_YE.dat
@@ -0,0 +1 @@
+a:3:{s:14:"NumberPatterns";a:4:{i:0;s:18:"###0.###;###0.###-";i:1;s:20:"¤###0.00;-¤###0.00";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:1:{s:8:"dayNames";a:1:{s:6:"format";a:1:{s:11:"abbreviated";a:7:{i:0;s:10:"الأØد";i:1;s:14:"الاثنين";i:2;s:16:"الثلاثاء";i:3;s:16:"الأربعاء";i:4;s:12:"الخميس";i:5;s:12:"الجمعة";i:6;s:10:"السبت";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/be.dat b/framework/I18N/core/data/be.dat
new file mode 100644
index 00000000..5508ad39
--- /dev/null
+++ b/framework/I18N/core/data/be.dat
@@ -0,0 +1 @@
+a:8:{s:9:"Countries";a:1:{s:2:"BY";a:1:{i:0;s:16:"БеларуÑÑŒ";}}s:10:"Currencies";a:1:{s:3:"BYB";a:2:{i:0;s:6:"Руб";i:1;s:3:"BYB";}}s:9:"Languages";a:1:{s:2:"be";a:1:{i:0;s:18:"БеларуÑкі";}}s:12:"LocaleScript";a:1:{i:0;s:4:"Cyrl";}s:14:"NumberElements";a:12:{i:0;s:1:",";i:1;s:2:" ";i:2;s:1:";";i:3;s:1:"%";i:4;s:1:"0";i:5;s:1:"#";i:6;s:1:"-";i:7;s:1:"E";i:8;s:3:"‰";i:9;s:3:"∞";i:10;s:3:"�";i:11;s:1:"+";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:5:{s:26:"DateTimeElements:intvector";a:2:{i:0;i:2;i:1;i:1;}s:16:"DateTimePatterns";a:9:{i:0;s:10:"HH.mm.ss z";i:1;s:10:"HH.mm.ss z";i:2;s:8:"HH.mm.ss";i:3;s:5:"HH.mm";i:4;s:17:"EEEE, d MMMM yyyy";i:5;s:11:"d MMMM yyyy";i:6;s:8:"d.M.yyyy";i:7;s:6:"d.M.yy";i:8;s:7:"{1} {0}";}s:8:"dayNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:7:{i:0;s:4:"нд";i:1;s:4:"пн";i:2;s:4:"аў";i:3;s:4:"ÑÑ€";i:4;s:4:"чц";i:5;s:4:"пт";i:6;s:4:"Ñб";}s:4:"wide";a:7:{i:0;s:14:"нÑдзелÑ";i:1;s:20:"панÑдзелак";i:2;s:14:"аўторак";i:3;s:12:"Ñерада";i:4;s:12:"чацвер";i:5;s:14:"пÑтніца";i:6;s:12:"Ñубота";}}}s:4:"eras";a:1:{s:11:"abbreviated";a:2:{i:0;s:11:"да н.е.";i:1;s:6:"н.е.";}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:12:{i:0;s:6:"Ñту";i:1;s:6:"лют";i:2;s:6:"Ñак";i:3;s:6:"кра";i:4;s:6:"май";i:5;s:6:"чÑÑ€";i:6;s:6:"ліп";i:7;s:6:"жні";i:8;s:6:"вер";i:9;s:6:"каÑ";i:10;s:6:"ліÑ";i:11;s:6:"Ñне";}s:4:"wide";a:12:{i:0;s:16:"Ñтудзень";i:1;s:8:"люты";i:2;s:14:"Ñакавік";i:3;s:16:"краÑавік";i:4;s:6:"май";i:5;s:14:"чÑрвень";i:6;s:12:"ліпень";i:7;s:14:"жнівень";i:8;s:16:"вераÑень";i:9;s:20:"каÑтрычнік";i:10;s:16:"ліÑтапад";i:11;s:14:"Ñнежань";}}}}}s:17:"localPatternChars";a:1:{i:0;s:24:"GanjkHmsSEDFwWxhKzAeugXZ";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/be_BY.dat b/framework/I18N/core/data/be_BY.dat
new file mode 100644
index 00000000..16784a7e
--- /dev/null
+++ b/framework/I18N/core/data/be_BY.dat
@@ -0,0 +1 @@
+a:2:{s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;-#,##0.###";i:1;s:16:"¤#,##0;-¤#,##0";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/bg.dat b/framework/I18N/core/data/bg.dat
new file mode 100644
index 00000000..c2ccd974
--- /dev/null
+++ b/framework/I18N/core/data/bg.dat
@@ -0,0 +1 @@
+a:12:{s:9:"Countries";a:239:{s:2:"AD";a:1:{i:0;s:12:"Ðндора";}s:2:"AE";a:1:{i:0;s:50:"Обединени ÐрабÑки ЕмирÑтва";}s:2:"AF";a:1:{i:0;s:20:"ÐфганиÑтан";}s:2:"AG";a:1:{i:0;s:32:"Ðнтигуа и Барбуда";}s:2:"AI";a:1:{i:0;s:14:"Ðнгуила";}s:2:"AL";a:1:{i:0;s:14:"ÐлбаниÑ";}s:2:"AM";a:1:{i:0;s:14:"ÐрмениÑ";}s:2:"AN";a:1:{i:0;s:31:"ХоландÑки Ðнтили";}s:2:"AO";a:1:{i:0;s:12:"Ðнгола";}s:2:"AQ";a:1:{i:0;s:20:"Ðнтарктика";}s:2:"AR";a:1:{i:0;s:18:"Ðржентина";}s:2:"AS";a:1:{i:0;s:33:"ÐмериканÑко Самоа";}s:2:"AT";a:1:{i:0;s:14:"ÐвÑтриÑ";}s:2:"AU";a:1:{i:0;s:18:"ÐвÑтралиÑ";}s:2:"AW";a:1:{i:0;s:10:"Ðруба";}s:2:"AZ";a:1:{i:0;s:22:"Ðзербайджан";}s:2:"BA";a:1:{i:0;s:36:"БоÑна и Херцеговина";}s:2:"BB";a:1:{i:0;s:16:"БарбадоÑ";}s:2:"BD";a:1:{i:0;s:18:"Бангладеш";}s:2:"BE";a:1:{i:0;s:12:"БелгиÑ";}s:2:"BF";a:1:{i:0;s:23:"Буркина ФаÑо";}s:2:"BG";a:1:{i:0;s:16:"БългариÑ";}s:2:"BH";a:1:{i:0;s:14:"Бахрейн";}s:2:"BI";a:1:{i:0;s:14:"Бурунди";}s:2:"BJ";a:1:{i:0;s:10:"Бенин";}s:2:"BM";a:1:{i:0;s:14:"Бермуда";}s:2:"BN";a:1:{i:0;s:31:"Бруней ДаруÑалам";}s:2:"BO";a:1:{i:0;s:14:"БоливиÑ";}s:2:"BR";a:1:{i:0;s:16:"БразилиÑ";}s:2:"BS";a:1:{i:0;s:12:"Бахами";}s:2:"BT";a:1:{i:0;s:10:"Бутан";}s:2:"BV";a:1:{i:0;s:21:"ОÑтров Буве";}s:2:"BW";a:1:{i:0;s:16:"БотÑуана";}s:2:"BY";a:1:{i:0;s:14:"БеларуÑ";}s:2:"BZ";a:1:{i:0;s:10:"Белиз";}s:2:"CA";a:1:{i:0;s:12:"Канада";}s:2:"CC";a:1:{i:0;s:48:"КокоÑови (Кийлинг) оÑтрови";}s:2:"CD";a:1:{i:0;s:54:"Демократична Република Конго";}s:2:"CF";a:1:{i:0;s:57:"ЦентралноафриканÑка Република";}s:2:"CG";a:1:{i:0;s:10:"Конго";}s:2:"CH";a:1:{i:0;s:18:"ШвейцариÑ";}s:2:"CI";a:1:{i:0;s:22:"Кот д’Ивоар";}s:2:"CK";a:1:{i:0;s:21:"ОÑтрови Кук";}s:2:"CL";a:1:{i:0;s:8:"Чили";}s:2:"CM";a:1:{i:0;s:14:"Камерун";}s:2:"CN";a:1:{i:0;s:10:"Китай";}s:2:"CO";a:1:{i:0;s:16:"КолумбиÑ";}s:2:"CR";a:1:{i:0;s:19:"КоÑта Рика";}s:2:"CU";a:1:{i:0;s:8:"Куба";}s:2:"CV";a:1:{i:0;s:19:"Кабо Верде";}s:2:"CX";a:1:{i:0;s:29:"ОÑтров КриÑтмаÑ";}s:2:"CY";a:1:{i:0;s:10:"Кипър";}s:2:"CZ";a:1:{i:0;s:29:"Чешка Република";}s:2:"DE";a:1:{i:0;s:16:"ГерманиÑ";}s:2:"DJ";a:1:{i:0;s:14:"Джибути";}s:2:"DK";a:1:{i:0;s:10:"ДаниÑ";}s:2:"DM";a:1:{i:0;s:16:"Доминика";}s:2:"DO";a:1:{i:0;s:43:"ДоминиканÑка Република";}s:2:"DZ";a:1:{i:0;s:10:"Ðлжир";}s:2:"EC";a:1:{i:0;s:14:"Еквадор";}s:2:"EE";a:1:{i:0;s:14:"ЕÑтониÑ";}s:2:"EG";a:1:{i:0;s:12:"Египет";}s:2:"EH";a:1:{i:0;s:27:"Западна Сахара";}s:2:"ER";a:1:{i:0;s:14:"ЕритреÑ";}s:2:"ES";a:1:{i:0;s:14:"ИÑпаниÑ";}s:2:"ET";a:1:{i:0;s:14:"ЕтиопиÑ";}s:2:"FI";a:1:{i:0;s:18:"ФинландиÑ";}s:2:"FJ";a:1:{i:0;s:10:"Фиджи";}s:2:"FK";a:1:{i:0;s:37:"ФолклендÑки оÑтрови";}s:2:"FM";a:1:{i:0;s:49:"МикронезиÑ, Обединени Щати";}s:2:"FO";a:1:{i:0;s:33:"ФарьорÑки оÑтрови";}s:2:"FR";a:1:{i:0;s:14:"ФранциÑ";}s:2:"GA";a:1:{i:0;s:10:"Габон";}s:2:"GB";a:1:{i:0;s:35:"Обединено кралÑтво";}s:2:"GD";a:1:{i:0;s:14:"Гренада";}s:2:"GE";a:1:{i:0;s:12:"ГрузиÑ";}s:2:"GF";a:1:{i:0;s:27:"ФренÑка Гвиана";}s:2:"GH";a:1:{i:0;s:8:"Гана";}s:2:"GI";a:1:{i:0;s:18:"Гибралтар";}s:2:"GL";a:1:{i:0;s:20:"ГренландиÑ";}s:2:"GM";a:1:{i:0;s:12:"ГамбиÑ";}s:2:"GN";a:1:{i:0;s:12:"ГвинеÑ";}s:2:"GP";a:1:{i:0;s:18:"Гваделупа";}s:2:"GQ";a:1:{i:0;s:37:"Екваториална ГвинеÑ";}s:2:"GR";a:1:{i:0;s:12:"ГърциÑ";}s:2:"GS";a:1:{i:0;s:73:"Южна Ð”Ð¶Ð¾Ñ€Ð´Ð¶Ð¸Ñ Ð¸ Южни Сандвичеви ОÑтрови";}s:2:"GT";a:1:{i:0;s:18:"Гватемала";}s:2:"GU";a:1:{i:0;s:8:"Гуам";}s:2:"GW";a:1:{i:0;s:23:"ГвинеÑ-БиÑау";}s:2:"GY";a:1:{i:0;s:12:"Гвиана";}s:2:"HK";a:1:{i:0;s:43:"Хонг-Конг О.Ð.Ð . на Китай";}s:2:"HM";a:1:{i:0;s:58:"ОÑтров Хърд и ОÑтрови Макдоналд";}s:2:"HN";a:1:{i:0;s:16:"ХондураÑ";}s:2:"HR";a:1:{i:0;s:18:"ХърватÑка";}s:2:"HT";a:1:{i:0;s:10:"Хаити";}s:2:"HU";a:1:{i:0;s:14:"УнгариÑ";}s:2:"ID";a:1:{i:0;s:18:"ИндонезиÑ";}s:2:"IE";a:1:{i:0;s:16:"ИрландиÑ";}s:2:"IL";a:1:{i:0;s:12:"Израел";}s:2:"IN";a:1:{i:0;s:10:"ИндиÑ";}s:2:"IO";a:1:{i:0;s:70:"БританÑки територии в ИндийÑÐºÐ¸Ñ Ð¾ÐºÐµÐ°Ð½";}s:2:"IQ";a:1:{i:0;s:8:"Ирак";}s:2:"IR";a:1:{i:0;s:45:"Иран, ИÑлÑмÑка република";}s:2:"IS";a:1:{i:0;s:16:"ИÑландиÑ";}s:2:"IT";a:1:{i:0;s:12:"ИталиÑ";}s:2:"JM";a:1:{i:0;s:12:"Ямайка";}s:2:"JO";a:1:{i:0;s:16:"ЙорданиÑ";}s:2:"JP";a:1:{i:0;s:12:"ЯпониÑ";}s:2:"KE";a:1:{i:0;s:10:"КениÑ";}s:2:"KG";a:1:{i:0;s:20:"КиргизÑтан";}s:2:"KH";a:1:{i:0;s:16:"Камбоджа";}s:2:"KI";a:1:{i:0;s:16:"Кирибати";}s:2:"KM";a:1:{i:0;s:12:"Комори";}s:2:"KN";a:1:{i:0;s:33:"Сейнт ÐšÐ¸Ñ‚Ñ Ð¸ ÐевиÑ";}s:2:"KP";a:1:{i:0;s:26:"КореÑ, Северна";}s:2:"KR";a:1:{i:0;s:20:"КореÑ, Южна";}s:2:"KW";a:1:{i:0;s:12:"Кувейт";}s:2:"KY";a:1:{i:0;s:33:"Кайманови оÑтрови";}s:2:"KZ";a:1:{i:0;s:18:"КазахÑтан";}s:2:"LA";a:1:{i:0;s:67:"Ðародна Демократична Република ЛаоÑ";}s:2:"LB";a:1:{i:0;s:10:"Ливан";}s:2:"LC";a:1:{i:0;s:21:"Сейнт ЛуÑиÑ";}s:2:"LI";a:1:{i:0;s:20:"Лихтенщайн";}s:2:"LK";a:1:{i:0;s:17:"Шри Ланка";}s:2:"LR";a:1:{i:0;s:14:"ЛибериÑ";}s:2:"LS";a:1:{i:0;s:12:"ЛеÑото";}s:2:"LT";a:1:{i:0;s:10:"Литва";}s:2:"LU";a:1:{i:0;s:20:"ЛюкÑембург";}s:2:"LV";a:1:{i:0;s:12:"ЛатвиÑ";}s:2:"LY";a:1:{i:0;s:52:"ЛибийÑка ÐрабÑка ДжамахириÑ";}s:2:"MA";a:1:{i:0;s:12:"Мароко";}s:2:"MC";a:1:{i:0;s:12:"Монако";}s:2:"MD";a:1:{i:0;s:34:"Молдова, Република";}s:2:"MG";a:1:{i:0;s:20:"МадагаÑкар";}s:2:"MH";a:1:{i:0;s:33:"Маршалови ОÑтрови";}s:2:"MK";a:1:{i:0;s:38:"МакедониÑ, Република";}s:2:"ML";a:1:{i:0;s:8:"Мали";}s:2:"MM";a:1:{i:0;s:14:"Мианмар";}s:2:"MN";a:1:{i:0;s:16:"МонголиÑ";}s:2:"MO";a:1:{i:0;s:36:"Макао О.Ð.Ð . на Китай";}s:2:"MP";a:1:{i:0;s:48:"Северни МарианÑки ОÑтрови";}s:2:"MQ";a:1:{i:0;s:18:"Мартиника";}s:2:"MR";a:1:{i:0;s:20:"МавританиÑ";}s:2:"MS";a:1:{i:0;s:16:"МонÑерат";}s:2:"MT";a:1:{i:0;s:10:"Малта";}s:2:"MU";a:1:{i:0;s:16:"Мавриций";}s:2:"MV";a:1:{i:0;s:14:"Малдиви";}s:2:"MW";a:1:{i:0;s:12:"Малави";}s:2:"MX";a:1:{i:0;s:14:"МекÑико";}s:2:"MY";a:1:{i:0;s:16:"МалайзиÑ";}s:2:"MZ";a:1:{i:0;s:16:"Мозамбик";}s:2:"NA";a:1:{i:0;s:14:"ÐамибиÑ";}s:2:"NC";a:1:{i:0;s:27:"Ðова КаледониÑ";}s:2:"NE";a:1:{i:0;s:10:"Ðигер";}s:2:"NF";a:1:{i:0;s:27:"ОÑтров Ðорфолк";}s:2:"NG";a:1:{i:0;s:14:"ÐигериÑ";}s:2:"NI";a:1:{i:0;s:18:"Ðикарагуа";}s:2:"NL";a:1:{i:0;s:16:"ХоландиÑ";}s:2:"NO";a:1:{i:0;s:16:"ÐорвегиÑ";}s:2:"NP";a:1:{i:0;s:10:"Ðепал";}s:2:"NR";a:1:{i:0;s:10:"Ðауру";}s:2:"NU";a:1:{i:0;s:8:"Ðиуе";}s:2:"NZ";a:1:{i:0;s:25:"Ðова ЗеландиÑ";}s:2:"OM";a:1:{i:0;s:8:"Оман";}s:2:"PA";a:1:{i:0;s:12:"Панама";}s:2:"PE";a:1:{i:0;s:8:"Перу";}s:2:"PF";a:1:{i:0;s:33:"ФренÑка ПолинезиÑ";}s:2:"PG";a:1:{i:0;s:32:"Папуа Ðова ГвинеÑ";}s:2:"PH";a:1:{i:0;s:16:"Филипини";}s:2:"PK";a:1:{i:0;s:16:"ПакиÑтан";}s:2:"PL";a:1:{i:0;s:10:"Полша";}s:2:"PM";a:1:{i:0;s:33:"Сен Пиер и Мигелон";}s:2:"PN";a:1:{i:0;s:16:"Питкайрн";}s:2:"PR";a:1:{i:0;s:21:"Пуерто Рико";}s:2:"PS";a:1:{i:0;s:41:"ПалеÑтинÑки територии";}s:2:"PT";a:1:{i:0;s:20:"ПортугалиÑ";}s:2:"PW";a:1:{i:0;s:10:"Палау";}s:2:"PY";a:1:{i:0;s:16:"Парагвай";}s:2:"QA";a:1:{i:0;s:10:"Катар";}s:2:"RE";a:1:{i:0;s:14:"Реюниън";}s:2:"RO";a:1:{i:0;s:14:"РумъниÑ";}s:2:"RU";a:1:{i:0;s:29:"РуÑка ФедерациÑ";}s:2:"RW";a:1:{i:0;s:12:"Руанда";}s:2:"SA";a:1:{i:0;s:31:"СаудитÑка ÐрабиÑ";}s:2:"SB";a:1:{i:0;s:35:"Соломонови ОÑтрови";}s:2:"SC";a:1:{i:0;s:14:"Сейшели";}s:2:"SD";a:1:{i:0;s:10:"Судан";}s:2:"SE";a:1:{i:0;s:12:"ШвециÑ";}s:2:"SG";a:1:{i:0;s:16:"Сингапур";}s:2:"SH";a:1:{i:0;s:21:"Света Елена";}s:2:"SI";a:1:{i:0;s:16:"СловениÑ";}s:2:"SJ";a:1:{i:0;s:35:"Свалбард и Ян Майен";}s:2:"SK";a:1:{i:0;s:16:"СловакиÑ";}s:2:"SL";a:1:{i:0;s:21:"Сиера Леоне";}s:2:"SM";a:1:{i:0;s:19:"Сан Марино";}s:2:"SN";a:1:{i:0;s:14:"Сенегал";}s:2:"SO";a:1:{i:0;s:14:"СомалиÑ";}s:2:"SR";a:1:{i:0;s:14:"Суринам";}s:2:"ST";a:1:{i:0;s:35:"Сао Томе и Принципе";}s:2:"SV";a:1:{i:0;s:21:"Ел Салвадор";}s:2:"SY";a:1:{i:0;s:50:"СирийÑка ÐрабÑка Република";}s:2:"SZ";a:1:{i:0;s:18:"Суазиленд";}s:2:"TC";a:1:{i:0;s:41:"ОÑтрови Ð¢ÑƒÑ€ÐºÑ Ð¸ КайкоÑ";}s:2:"TD";a:1:{i:0;s:6:"Чад";}s:2:"TF";a:1:{i:0;s:42:"ФренÑки Южни Територии";}s:2:"TG";a:1:{i:0;s:8:"Того";}s:2:"TH";a:1:{i:0;s:14:"Тайланд";}s:2:"TJ";a:1:{i:0;s:22:"ТаджикиÑтан";}s:2:"TK";a:1:{i:0;s:14:"Токелау";}s:2:"TL";a:1:{i:0;s:25:"Източен Тимор";}s:2:"TM";a:1:{i:0;s:24:"ТуркмениÑтан";}s:2:"TN";a:1:{i:0;s:10:"ТуниÑ";}s:2:"TO";a:1:{i:0;s:10:"Тонга";}s:2:"TR";a:1:{i:0;s:12:"ТурциÑ";}s:2:"TT";a:1:{i:0;s:32:"Тринидад и Тобаго";}s:2:"TV";a:1:{i:0;s:12:"Тувалу";}s:2:"TW";a:1:{i:0;s:12:"Тайван";}s:2:"TZ";a:1:{i:0;s:16:"ТанзаниÑ";}s:2:"UA";a:1:{i:0;s:14:"Украйна";}s:2:"UG";a:1:{i:0;s:12:"Уганда";}s:2:"UM";a:1:{i:0;s:36:"СÐЩ - външни оÑтрови";}s:2:"US";a:1:{i:0;s:6:"СÐЩ";}s:2:"UY";a:1:{i:0;s:14:"Уругвай";}s:2:"UZ";a:1:{i:0;s:20:"УзбекиÑтан";}s:2:"VA";a:1:{i:0;s:61:"Свещено море (ВатиканÑка държава)";}s:2:"VC";a:1:{i:0;s:47:"Сейнт ВинÑънт и Гренадини";}s:2:"VE";a:1:{i:0;s:18:"Венецуела";}s:2:"VG";a:1:{i:0;s:54:"БританÑки ВирджинÑки ОÑтрови";}s:2:"VI";a:1:{i:0;s:43:"СÐЩ, ВирджинÑки ОÑтрови";}s:2:"VN";a:1:{i:0;s:14:"Виетнам";}s:2:"VU";a:1:{i:0;s:14:"Вануату";}s:2:"WF";a:1:{i:0;s:26:"Ð£Ð¾Ð»Ð¸Ñ Ð¸ Футуна";}s:2:"WS";a:1:{i:0;s:10:"Самоа";}s:2:"YE";a:1:{i:0;s:10:"Йемен";}s:2:"YT";a:1:{i:0;s:10:"Мейот";}s:2:"YU";a:1:{i:0;s:18:"ЮгоÑлавиÑ";}s:2:"ZA";a:1:{i:0;s:21:"Южна Ðфрика";}s:2:"ZM";a:1:{i:0;s:12:"ЗамбиÑ";}s:2:"ZW";a:1:{i:0;s:16:"Зимбабве";}}s:10:"Currencies";a:277:{s:3:"ADD";a:2:{i:0;s:3:"ADD";i:1;s:27:"ÐндорÑки динар";}s:3:"ADP";a:2:{i:0;s:3:"ADP";i:1;s:29:"ÐндорÑка пеÑета";}s:3:"AED";a:2:{i:0;s:3:"AED";i:1;s:63:"Обединени арабÑки емирÑтва-дирхам";}s:3:"AFA";a:2:{i:0;s:3:"AFA";i:1;s:49:"ÐфганиÑтанÑки афган (1927-2002)";}s:3:"AFN";a:2:{i:0;s:2:"Af";i:1;s:37:"ÐфганиÑтанÑки афган";}s:3:"ALK";a:2:{i:0;s:3:"ALK";i:1;s:35:"ÐлбанÑки лек (1946-1961)";}s:3:"ALL";a:2:{i:0;s:3:"lek";i:1;s:23:"ÐлбанÑки лек";}s:3:"ALV";a:2:{i:0;s:3:"ALV";i:1;s:38:"ÐлбанÑки валутен лек";}s:3:"ALX";a:2:{i:0;s:3:"ALX";i:1;s:52:"ÐлбанÑки конвертируем долар";}s:3:"AMD";a:2:{i:0;s:4:"dram";i:1;s:25:"ÐрменÑки драм";}s:3:"ANG";a:2:{i:0;s:5:"NA f.";i:1;s:29:"ÐнтилÑки гулден";}s:3:"AOA";a:2:{i:0;s:3:"AOA";i:1;s:29:"ÐнголÑка кванца";}s:3:"AOK";a:2:{i:0;s:3:"AOK";i:1;s:41:"ÐнголÑка кванца (1977-1990)";}s:3:"AON";a:2:{i:0;s:3:"AON";i:1;s:50:"ÐнголÑка нова кванца (1990-2000)";}s:3:"AOR";a:2:{i:0;s:3:"AOR";i:1;s:50:"ÐнголÑка нова кванца (1995-1999)";}s:3:"AOS";a:2:{i:0;s:3:"AOS";i:1;s:29:"ÐнголÑко еÑкудо";}s:3:"ARP";a:2:{i:0;s:3:"ARP";i:1;s:43:"ÐржентинÑко пеÑо (1983-1985)";}s:3:"ARS";a:2:{i:0;s:4:"Arg$";i:1;s:31:"ÐржентинÑко пеÑо";}s:3:"ATS";a:2:{i:0;s:3:"ATS";i:1;s:33:"ÐвÑтрийÑки шилинг";}s:3:"AUD";a:2:{i:0;s:2:"$A";i:1;s:35:"ÐвÑтралийÑки долар";}s:3:"AUP";a:2:{i:0;s:3:"AUP";i:1;s:33:"ÐвÑтралийÑка лира";}s:3:"AWG";a:2:{i:0;s:3:"AWG";i:1;s:44:"ÐрубÑки гилдер - о. Ðруба";}s:3:"AZM";a:2:{i:0;s:3:"AZM";i:1;s:39:"ÐзербайджанÑки манат";}s:3:"BAD";a:2:{i:0;s:3:"BAD";i:1;s:47:"БоÑна и Херцеговина-динар";}s:3:"BAM";a:2:{i:0;s:2:"KM";i:1;s:56:"БоÑненÑка конвертируема марка";}s:3:"BAN";a:2:{i:0;s:3:"BAN";i:1;s:54:"БоÑна и Херцеговина-нов динар";}s:3:"BBD";a:2:{i:0;s:4:"BDS$";i:1;s:33:"БарбейдоÑки долар";}s:3:"BDT";a:2:{i:0;s:2:"Tk";i:1;s:31:"Бангладешка така";}s:3:"BEC";a:2:{i:0;s:3:"BEC";i:1;s:56:"БелгийÑки франк (конвертируем)";}s:3:"BEF";a:2:{i:0;s:2:"BF";i:1;s:29:"БелгийÑки франк";}s:3:"BEL";a:2:{i:0;s:3:"BEL";i:1;s:48:"БелгийÑки франк (финанÑов)";}s:3:"BGL";a:2:{i:0;s:4:"лв";i:1;s:3:"BGL";}s:3:"BGM";a:2:{i:0;s:3:"BGM";i:1;s:56:"БългарÑки ÑоциалиÑтичеÑки лев";}s:3:"BGN";a:2:{i:0;s:5:"лв.";i:1;s:3:"BGN";}s:3:"BGO";a:2:{i:0;s:3:"BGO";i:1;s:37:"БългарÑки лев (1879-1952)";}s:3:"BGX";a:2:{i:0;s:3:"BGX";i:1;s:50:"БългарÑки конвертируем лев";}s:3:"BHD";a:2:{i:0;s:2:"BD";i:1;s:31:"БахрейнÑки динар";}s:3:"BIF";a:2:{i:0;s:3:"Fbu";i:1;s:33:"БурундийÑки франк";}s:3:"BMD";a:2:{i:0;s:4:"Ber$";i:1;s:29:"БермудÑки долар";}s:3:"BMP";a:2:{i:0;s:3:"BMP";i:1;s:27:"БермудÑка лира";}s:3:"BND";a:2:{i:0;s:3:"BND";i:1;s:29:"БрунейÑки долар";}s:3:"BOB";a:2:{i:0;s:2:"Bs";i:1;s:39:"БоливийÑко боливиано";}s:3:"BOL";a:2:{i:0;s:3:"BOL";i:1;s:51:"БоливийÑко боливиано (1863-1962)";}s:3:"BOP";a:2:{i:0;s:3:"BOP";i:1;s:29:"БоливийÑко пеÑо";}s:3:"BRL";a:2:{i:0;s:2:"R$";i:1;s:27:"БразилÑки реал";}s:3:"BSD";a:2:{i:0;s:3:"BSD";i:1;s:27:"БахамÑки долар";}s:3:"BSP";a:2:{i:0;s:3:"BSP";i:1;s:25:"БахамÑка лира";}s:3:"BTN";a:2:{i:0;s:2:"Nu";i:1;s:33:"БутанÑки нгултрум";}s:3:"BTR";a:2:{i:0;s:3:"BTR";i:1;s:27:"БутанÑка рупиÑ";}s:3:"BUR";a:2:{i:0;s:3:"BUR";i:1;s:29:"БирманÑка рупиÑ";}s:3:"BWP";a:2:{i:0;s:3:"BWP";i:1;s:29:"БотÑуанÑка пула";}s:3:"BYB";a:2:{i:0;s:3:"BYB";i:1;s:50:"БеларуÑка нова рубла (1994-1999)";}s:3:"BYL";a:2:{i:0;s:3:"BYL";i:1;s:41:"БеларуÑка рубла (1992-1994)";}s:3:"BYR";a:2:{i:0;s:3:"Rbl";i:1;s:29:"БеларуÑка рубла";}s:3:"BZD";a:2:{i:0;s:3:"BZ$";i:1;s:31:"БелизийÑки долар";}s:3:"BZH";a:2:{i:0;s:3:"BZH";i:1;s:50:"БританÑки хондураÑки долар";}s:3:"CAD";a:2:{i:0;s:4:"Can$";i:1;s:27:"КанадÑки долар";}s:3:"CDF";a:2:{i:0;s:3:"CDF";i:1;s:31:"КонгоанÑки франк";}s:3:"CHF";a:2:{i:0;s:3:"SwF";i:1;s:31:"ШвейцарÑки франк";}s:3:"CKD";a:2:{i:0;s:3:"CKD";i:1;s:32:"ОÑтрови Кук-долар";}s:3:"CLE";a:2:{i:0;s:3:"CLE";i:1;s:29:"ЧилийÑко еÑкудо";}s:3:"CLP";a:2:{i:0;s:3:"Ch$";i:1;s:25:"ЧилийÑко пеÑо";}s:3:"CNY";a:2:{i:0;s:1:"Y";i:1;s:40:"КитайÑки ренминби юан";}s:3:"COP";a:2:{i:0;s:4:"Col$";i:1;s:31:"КолумбийÑко пеÑо";}s:3:"CRC";a:2:{i:0;s:1:"C";i:1;s:37:"КоÑтариканÑки колон";}s:3:"CSC";a:2:{i:0;s:3:"CSC";i:1;s:35:"ЧехоÑловашка крона";}s:3:"CSK";a:2:{i:0;s:3:"CSK";i:1;s:62:"ЧехоÑловашка конвертируема крона";}s:3:"CUP";a:2:{i:0;s:3:"CUP";i:1;s:25:"КубинÑко пеÑо";}s:3:"CVE";a:2:{i:0;s:5:"CVEsc";i:1;s:32:"Кабо Верде еÑкудо";}s:3:"CYP";a:2:{i:0;s:3:"£C";i:1;s:25:"КипърÑка лира";}s:3:"CZK";a:2:{i:0;s:3:"CZK";i:1;s:21:"Чешка крона";}s:3:"DEM";a:2:{i:0;s:3:"DEM";i:1;s:29:"ГерманÑка марка";}s:3:"DJF";a:2:{i:0;s:2:"DF";i:1;s:29:"ДжибутÑки франк";}s:3:"DKK";a:2:{i:0;s:3:"DKr";i:1;s:23:"ДатÑка крона";}s:3:"DOP";a:2:{i:0;s:3:"RD$";i:1;s:33:"ДоминиканÑко пеÑо";}s:3:"DZD";a:2:{i:0;s:2:"DA";i:1;s:27:"ÐлжирÑки динар";}s:3:"DZF";a:2:{i:0;s:3:"DZF";i:1;s:34:"ÐлжирÑки нов франк";}s:3:"ECS";a:2:{i:0;s:3:"ECS";i:1;s:31:"ЕквадорÑко Ñукре";}s:3:"EEK";a:2:{i:0;s:3:"EEK";i:1;s:27:"ЕÑтонÑка крона";}s:3:"EGP";a:2:{i:0;s:3:"EGP";i:1;s:27:"ЕгипетÑка лира";}s:3:"ERN";a:2:{i:0;s:3:"ERN";i:1;s:31:"ЕритрейÑка накфа";}s:3:"ESP";a:2:{i:0;s:3:"ESP";i:1;s:29:"ИÑпанÑка пеÑета";}s:3:"ETB";a:2:{i:0;s:2:"Br";i:1;s:23:"ЕтиопÑки бир";}s:3:"ETD";a:2:{i:0;s:3:"ETD";i:1;s:27:"ЕтиопÑки долар";}s:3:"EUR";a:2:{i:0;s:3:"€";i:1;s:8:"Евро";}s:3:"FIM";a:2:{i:0;s:3:"FIM";i:1;s:31:"ФинландÑка марка";}s:3:"FIN";a:2:{i:0;s:3:"FIN";i:1;s:43:"ФинландÑка марка (1860-1962)";}s:3:"FJD";a:2:{i:0;s:2:"F$";i:1;s:23:"Фиджи - долар";}s:3:"FJP";a:2:{i:0;s:3:"FJP";i:1;s:21:"Фиджи - лира";}s:3:"FKP";a:2:{i:0;s:3:"FKP";i:1;s:31:"ФолкландÑка лира";}s:3:"FRF";a:2:{i:0;s:3:"FRF";i:1;s:25:"ФренÑки франк";}s:3:"GAF";a:2:{i:0;s:3:"GAF";i:1;s:27:"Габон - CFA франк";}s:3:"GBP";a:2:{i:0;s:2:"£";i:1;s:27:"БританÑка лира";}s:3:"GEL";a:2:{i:0;s:4:"lari";i:1;s:27:"ГрузинÑки лари";}s:3:"GHC";a:2:{i:0;s:3:"GHC";i:1;s:25:"ГанайÑки Ñеди";}s:3:"GHO";a:2:{i:0;s:3:"GHO";i:1;s:36:"ГанайÑки Ñтари Ñеди";}s:3:"GHP";a:2:{i:0;s:3:"GHP";i:1;s:25:"ГанайÑка лира";}s:3:"GIP";a:2:{i:0;s:3:"GIP";i:1;s:33:"ГибралтарÑка лира";}s:3:"GLK";a:2:{i:0;s:3:"GLK";i:1;s:33:"ГренландÑка крона";}s:3:"GMD";a:2:{i:0;s:3:"GMD";i:1;s:31:"ГамбийÑки далаÑи";}s:3:"GMP";a:2:{i:0;s:3:"GMP";i:1;s:27:"ГамбийÑка лира";}s:3:"GNF";a:2:{i:0;s:2:"GF";i:1;s:29:"ГвинейÑки франк";}s:3:"GNI";a:2:{i:0;s:3:"GNI";i:1;s:41:"ГвинейÑки франк (1960-1972)";}s:3:"GPF";a:2:{i:0;s:3:"GPF";i:1;s:33:"ГваделупÑки франк";}s:3:"GRD";a:2:{i:0;s:3:"GRD";i:1;s:25:"Гръцка драхма";}s:3:"GRN";a:2:{i:0;s:3:"GRN";i:1;s:34:"Гръцка нова драхма";}s:3:"GTQ";a:2:{i:0;s:1:"Q";i:1;s:37:"ГватемалÑки кветзал";}s:3:"GWP";a:2:{i:0;s:3:"GWP";i:1;s:32:"ГвинеÑ-БиÑау пеÑо";}s:3:"GYD";a:2:{i:0;s:2:"G$";i:1;s:25:"ГаÑнÑки долар";}s:3:"HKD";a:2:{i:0;s:3:"HK$";i:1;s:33:"ХонгконгÑки долар";}s:3:"HNL";a:2:{i:0;s:1:"L";i:1;s:35:"ХондураÑка лемпира";}s:3:"HRD";a:2:{i:0;s:3:"HRD";i:1;s:29:"ХърватÑки динар";}s:3:"HRK";a:2:{i:0;s:3:"HRK";i:1;s:27:"ХърватÑка куна";}s:3:"HTG";a:2:{i:0;s:3:"HTG";i:1;s:23:"ХаитÑки гурд";}s:3:"HUF";a:2:{i:0;s:2:"Ft";i:1;s:29:"УнгарÑки форинт";}s:3:"IDN";a:2:{i:0;s:3:"IDN";i:1;s:44:"ИндонезийÑка нова рупиÑ";}s:3:"IDR";a:2:{i:0;s:2:"Rp";i:1;s:35:"ИндонезийÑка рупиÑ";}s:3:"IEP";a:2:{i:0;s:4:"IR£";i:1;s:27:"ИрландÑка лира";}s:3:"ILL";a:2:{i:0;s:3:"ILL";i:1;s:29:"ИзраелÑки шекел";}s:3:"ILP";a:2:{i:0;s:3:"ILP";i:1;s:27:"ИзраелÑка лира";}s:3:"ILS";a:2:{i:0;s:3:"ILS";i:1;s:36:"ИзраелÑки нов шекел";}s:3:"INR";a:2:{i:0;s:3:"INR";i:1;s:27:"ИндийÑка рупиÑ";}s:3:"IQD";a:2:{i:0;s:2:"ID";i:1;s:25:"ИракÑки динар";}s:3:"IRR";a:2:{i:0;s:2:"RI";i:1;s:23:"ИранÑки риал";}s:3:"ISK";a:2:{i:0;s:3:"ISK";i:1;s:29:"ИÑландÑка крона";}s:3:"ITL";a:2:{i:0;s:3:"₤";i:1;s:29:"ИталианÑка лира";}s:3:"JMD";a:2:{i:0;s:2:"J$";i:1;s:25:"ЯмайÑки долар";}s:3:"JMP";a:2:{i:0;s:3:"JMP";i:1;s:23:"ЯмайÑка лира";}s:3:"JOD";a:2:{i:0;s:2:"JD";i:1;s:29:"ЙорданÑки динар";}s:3:"JPY";a:2:{i:0;s:2:"Â¥";i:1;s:23:"ЯпонÑка йена";}s:3:"KES";a:2:{i:0;s:4:"K Sh";i:1;s:29:"КенийÑки шилинг";}s:3:"KGS";a:2:{i:0;s:3:"som";i:1;s:31:"КиргиÑтанÑки Ñом";}s:3:"KHO";a:2:{i:0;s:3:"KHO";i:1;s:42:"КамбоджанÑки Ñтар риел";}s:3:"KHR";a:2:{i:0;s:2:"CR";i:1;s:33:"КамбоджанÑки риел";}s:3:"KMF";a:2:{i:0;s:2:"CF";i:1;s:27:"КоморÑки франк";}s:3:"KPW";a:2:{i:0;s:3:"KPW";i:1;s:37:"СевернокорейÑки вон";}s:3:"KRW";a:2:{i:0;s:3:"KRW";i:1;s:15:"КÐДРвон";}s:3:"KWD";a:2:{i:0;s:2:"KD";i:1;s:29:"КувейтÑки динар";}s:3:"KYD";a:2:{i:0;s:3:"KYD";i:1;s:46:"Кайманови оÑтрови - долар";}s:3:"KZR";a:2:{i:0;s:3:"KZR";i:1;s:35:"КазахÑтанÑка рубла";}s:3:"KZT";a:2:{i:0;s:1:"T";i:1;s:35:"КазахÑтанÑко тенге";}s:3:"LAK";a:2:{i:0;s:3:"LAK";i:1;s:19:"ЛаоÑки кип";}s:3:"LBP";a:2:{i:0;s:2:"LL";i:1;s:25:"ЛиванÑка лира";}s:3:"LIF";a:2:{i:0;s:3:"LIF";i:1;s:37:"ЛихтенщайнÑки франк";}s:3:"LKR";a:2:{i:0;s:5:"SL Re";i:1;s:31:"ШриланкÑка рупиÑ";}s:3:"LNR";a:2:{i:0;s:3:"LNR";i:1;s:29:"СейлонÑка рупиÑ";}s:3:"LRD";a:2:{i:0;s:3:"LRD";i:1;s:31:"ЛиберийÑки долар";}s:3:"LSL";a:2:{i:0;s:1:"M";i:1;s:25:"ЛеÑотÑко лоти";}s:3:"LTL";a:2:{i:0;s:3:"LTL";i:1;s:27:"ЛитовÑки литаз";}s:3:"LUF";a:2:{i:0;s:3:"LUF";i:1;s:37:"ЛюкÑембургÑки франк";}s:3:"LVL";a:2:{i:0;s:3:"LVL";i:1;s:25:"ЛатвийÑки лат";}s:3:"LVR";a:2:{i:0;s:3:"LVR";i:1;s:29:"ЛатвийÑка рубла";}s:3:"LYD";a:2:{i:0;s:2:"LD";i:1;s:27:"ЛибийÑки динар";}s:3:"LYP";a:2:{i:0;s:3:"LYP";i:1;s:25:"ЛибийÑка лира";}s:3:"MAD";a:2:{i:0;s:3:"MAD";i:1;s:33:"МароканÑки дирхам";}s:3:"MAF";a:2:{i:0;s:3:"MAF";i:1;s:31:"МароканÑки франк";}s:3:"MDL";a:2:{i:0;s:3:"MDL";i:1;s:25:"МолдовÑко леу";}s:3:"MGF";a:2:{i:0;s:3:"MGF";i:1;s:50:"Малгашки франк - МадагаÑкар";}s:3:"MHD";a:2:{i:0;s:3:"MHD";i:1;s:44:"МаршалÑки оÑтрови-долар";}s:3:"MKD";a:2:{i:0;s:4:"MDen";i:1;s:31:"МакедонÑки денар";}s:3:"MKN";a:2:{i:0;s:3:"MKN";i:1;s:43:"МакедонÑки денар (1992-1993)";}s:3:"MMK";a:2:{i:0;s:3:"MMK";i:1;s:42:"МиÑнмарÑки (Бирма) киÑÑ‚";}s:3:"MMX";a:2:{i:0;s:3:"MMX";i:1;s:56:"МиÑнмарÑки конвертируем долар";}s:3:"MNT";a:2:{i:0;s:3:"Tug";i:1;s:31:"МонголÑки тугрик";}s:3:"MOP";a:2:{i:0;s:3:"MOP";i:1;s:25:"Макао - патака";}s:3:"MQF";a:2:{i:0;s:3:"MQF";i:1;s:31:"Мартиника - франк";}s:3:"MRO";a:2:{i:0;s:2:"UM";i:1;s:31:"МавританÑка огиÑ";}s:3:"MTL";a:2:{i:0;s:2:"Lm";i:1;s:27:"МалтийÑка лира";}s:3:"MUR";a:2:{i:0;s:3:"MUR";i:1;s:33:"МаврицийÑка рупиÑ";}s:3:"MVP";a:2:{i:0;s:3:"MVP";i:1;s:46:"МалдивÑка Ñ€ÑƒÐ¿Ð¸Ñ - Малдиви";}s:3:"MVR";a:2:{i:0;s:3:"MVR";i:1;s:29:"МалдивÑка руфиÑ";}s:3:"MWK";a:2:{i:0;s:2:"MK";i:1;s:31:"МалавийÑка квача";}s:3:"MWP";a:2:{i:0;s:3:"MWP";i:1;s:29:"МалавийÑка лира";}s:3:"MXN";a:2:{i:0;s:4:"MEX$";i:1;s:40:"МекÑиканÑко ново пеÑо";}s:3:"MXP";a:2:{i:0;s:3:"MXP";i:1;s:60:"МекÑиканÑко Ñребърно пеÑо (1861-1992)";}s:3:"MYR";a:2:{i:0;s:2:"RM";i:1;s:35:"МалайзийÑки рингит";}s:3:"MZE";a:2:{i:0;s:3:"MZE";i:1;s:35:"МозамбикÑко еÑкудо";}s:3:"MZM";a:2:{i:0;s:2:"Mt";i:1;s:37:"МозамбикÑки метикал";}s:3:"NAD";a:2:{i:0;s:2:"N$";i:1;s:31:"ÐамибийÑки долар";}s:3:"NGN";a:2:{i:0;s:3:"NGN";i:1;s:31:"ÐигерийÑка найра";}s:3:"NGP";a:2:{i:0;s:3:"NGP";i:1;s:29:"ÐигерийÑка лира";}s:3:"NIC";a:2:{i:0;s:3:"NIC";i:1;s:41:"ÐикарагуанÑка кордоба";}s:3:"NIG";a:2:{i:0;s:3:"NIG";i:1;s:54:"ÐикарагуанÑка златна кордоба";}s:3:"NLG";a:2:{i:0;s:3:"NLG";i:1;s:31:"ХоландÑки гулден";}s:3:"NOK";a:2:{i:0;s:3:"NKr";i:1;s:27:"Ðорвежка крона";}s:3:"NPR";a:2:{i:0;s:3:"Nrs";i:1;s:27:"ÐепалÑка рупиÑ";}s:3:"NZD";a:2:{i:0;s:3:"$NZ";i:1;s:37:"ÐовозеландÑки долар";}s:3:"NZP";a:2:{i:0;s:3:"NZP";i:1;s:35:"ÐовозеландÑка лира";}s:3:"OMR";a:2:{i:0;s:2:"RO";i:1;s:23:"ОманÑки риал";}s:3:"PAB";a:2:{i:0;s:3:"PAB";i:1;s:29:"ПанамÑки балбоа";}s:3:"PEN";a:2:{i:0;s:3:"PEN";i:1;s:32:"ПеруанÑки нов Ñол";}s:3:"PES";a:2:{i:0;s:3:"PES";i:1;s:25:"ПеруанÑки Ñол";}s:3:"PGK";a:2:{i:0;s:3:"PGK";i:1;s:46:"Папуа-новогвинейÑка кина";}s:3:"PHP";a:2:{i:0;s:3:"PHP";i:1;s:29:"ФилипинÑко пеÑо";}s:3:"PKR";a:2:{i:0;s:3:"Pra";i:1;s:33:"ПакиÑтанÑка рупиÑ";}s:3:"PLN";a:2:{i:0;s:2:"Zl";i:1;s:23:"ПолÑка злота";}s:3:"PLX";a:2:{i:0;s:3:"PLX";i:1;s:48:"ПолÑки конвентируем долар";}s:3:"PLZ";a:2:{i:0;s:3:"PLZ";i:1;s:35:"ПолÑка злота (1950-1995)";}s:3:"PSP";a:2:{i:0;s:3:"PSP";i:1;s:31:"ПалеÑтинÑка лира";}s:3:"PTE";a:2:{i:0;s:3:"PTE";i:1;s:35:"ПортугалÑко еÑкудо";}s:3:"PYG";a:2:{i:0;s:3:"PYG";i:1;s:37:"ПарагвайÑко гуарани";}s:3:"QAR";a:2:{i:0;s:2:"QR";i:1;s:25:"КатарÑки риал";}s:3:"ROL";a:2:{i:0;s:3:"leu";i:1;s:23:"РумънÑка леÑ";}s:3:"RON";a:2:{i:0;s:3:"RON";i:1;s:32:"РумънÑка нова леÑ";}s:3:"RUB";a:2:{i:0;s:3:"RUB";i:1;s:21:"РуÑка рубла";}s:3:"RUR";a:2:{i:0;s:3:"RUR";i:1;s:33:"РуÑка рубла (1991-1998)";}s:3:"RWF";a:2:{i:0;s:3:"RWF";i:1;s:27:"РуандÑки франк";}s:3:"SAR";a:2:{i:0;s:3:"SRl";i:1;s:41:"СаудитÑкоарабÑки риал";}s:3:"SBD";a:2:{i:0;s:3:"SI$";i:1;s:48:"Соломонови оÑтрови - долар";}s:3:"SCR";a:2:{i:0;s:2:"SR";i:1;s:29:"СейшелÑка рупиÑ";}s:3:"SDD";a:2:{i:0;s:3:"SDD";i:1;s:27:"СуданÑки динар";}s:3:"SDP";a:2:{i:0;s:3:"SDP";i:1;s:25:"СуданÑка лира";}s:3:"SEK";a:2:{i:0;s:3:"SKr";i:1;s:25:"ШведÑка крона";}s:3:"SGD";a:2:{i:0;s:2:"S$";i:1;s:33:"СингапурÑки долар";}s:3:"SHP";a:2:{i:0;s:3:"SHP";i:1;s:30:"Света Елена лира";}s:3:"SIT";a:2:{i:0;s:3:"SIT";i:1;s:29:"СловенÑки толар";}s:3:"SKK";a:2:{i:0;s:2:"Sk";i:1;s:27:"Словашка крона";}s:3:"SLL";a:2:{i:0;s:3:"SLL";i:1;s:35:"СиералеонÑко леоне";}s:3:"SML";a:2:{i:0;s:3:"SML";i:1;s:30:"Сан Марино - лира";}s:3:"SOS";a:2:{i:0;s:7:"So. Sh.";i:1;s:33:"СомалийÑки шилинг";}s:3:"SRG";a:2:{i:0;s:2:"Sf";i:1;s:33:"СуринамÑки гилдер";}s:3:"SSP";a:2:{i:0;s:3:"SSP";i:1;s:29:"ШотландÑка лира";}s:3:"STD";a:2:{i:0;s:2:"Db";i:1;s:48:"Сао Томе и ПринÑипи - добра";}s:3:"STE";a:2:{i:0;s:3:"STE";i:1;s:50:"Сао Томе и ПринÑипи - еÑкудо";}s:3:"SUN";a:2:{i:0;s:3:"SUN";i:1;s:36:"СъветÑка нова рубла";}s:3:"SUR";a:2:{i:0;s:3:"SUR";i:1;s:27:"СъветÑка рубла";}s:3:"SVC";a:2:{i:0;s:3:"SVC";i:1;s:33:"СалвадорÑки колон";}s:3:"SYP";a:2:{i:0;s:2:"LS";i:1;s:25:"СирийÑка лира";}s:3:"SZL";a:2:{i:0;s:1:"E";i:1;s:43:"СвазилендÑки лилангени";}s:3:"THB";a:2:{i:0;s:3:"THB";i:1;s:27:"ТайландÑки бат";}s:3:"TJR";a:2:{i:0;s:3:"TJR";i:1;s:39:"ТаджикиÑтанÑка рубла";}s:3:"TJS";a:2:{i:0;s:3:"TJS";i:1;s:41:"ТаджикиÑтанÑки Ñомони";}s:3:"TMM";a:2:{i:0;s:3:"TMM";i:1;s:41:"ТуркмениÑтанÑки манат";}s:3:"TND";a:2:{i:0;s:3:"TND";i:1;s:31:"ТунизийÑки динар";}s:3:"TOP";a:2:{i:0;s:2:"T$";i:1;s:26:"Тонга - па анга";}s:3:"TPE";a:2:{i:0;s:3:"TPE";i:1;s:29:"ТиморÑко еÑкудо";}s:3:"TPP";a:2:{i:0;s:3:"TPP";i:1;s:29:"ТиморÑка патака";}s:3:"TRL";a:2:{i:0;s:2:"TL";i:1;s:21:"ТурÑка лира";}s:3:"TTD";a:2:{i:0;s:3:"TT$";i:1;s:45:"Тринидат и Тобаго - долар";}s:3:"TTO";a:2:{i:0;s:3:"TTO";i:1;s:54:"Тринидат и Тобаго - Ñтар долар";}s:3:"TWD";a:2:{i:0;s:3:"NT$";i:1;s:29:"ТайванÑки долар";}s:3:"TZS";a:2:{i:0;s:4:"T Sh";i:1;s:35:"ТанзанийÑки шилинг";}s:3:"UAH";a:2:{i:0;s:3:"UAH";i:1;s:31:"УкраинÑка хривнÑ";}s:3:"UAK";a:2:{i:0;s:3:"UAK";i:1;s:39:"УкраинÑки карбованец";}s:3:"UGS";a:2:{i:0;s:3:"UGS";i:1;s:45:"УгандийÑки шилинг (1966-1987)";}s:3:"UGX";a:2:{i:0;s:4:"U Sh";i:1;s:40:"УгандийÑки нов шилинг";}s:3:"USD";a:2:{i:0;s:3:"US$";i:1;s:17:"СÐЩ долар";}s:3:"UYP";a:2:{i:0;s:3:"UYP";i:1;s:41:"УругвайÑко пеÑо (1975-1993)";}s:3:"UYU";a:2:{i:0;s:3:"Ur$";i:1;s:29:"УругвайÑко пеÑо";}s:3:"UZS";a:2:{i:0;s:3:"UZS";i:1;s:33:"УзбекиÑтанÑки Ñум";}s:3:"VAL";a:2:{i:0;s:3:"VAL";i:1;s:27:"Ватикана - лира";}s:3:"VEB";a:2:{i:0;s:2:"Be";i:1;s:37:"ВенеÑуелÑки боливар";}s:3:"VND";a:2:{i:0;s:3:"VND";i:1;s:29:"ВиетнамÑки донг";}s:3:"VNN";a:2:{i:0;s:3:"VNN";i:1;s:36:"ВиетнамÑки нов донг";}s:3:"VNS";a:2:{i:0;s:3:"VNS";i:1;s:50:"ВиетнамÑки национален донг";}s:3:"VUV";a:2:{i:0;s:2:"VT";i:1;s:25:"Вануату - вату";}s:3:"WSP";a:2:{i:0;s:3:"WSP";i:1;s:21:"Самоа - лира";}s:3:"WST";a:2:{i:0;s:3:"WST";i:1;s:21:"Самоа - тала";}s:3:"XAF";a:2:{i:0;s:3:"XAF";i:1;s:42:"Буркина ФаÑо - CFA - франк";}s:3:"XAU";a:2:{i:0;s:3:"XAU";i:1;s:10:"Злато";}s:3:"XCD";a:2:{i:0;s:3:"EC$";i:1;s:58:"ИзточнокарибÑки долар - Ðнтигуа";}s:3:"XEU";a:2:{i:0;s:3:"XEU";i:1;s:18:"Еку на ЕИО";}s:3:"XFO";a:2:{i:0;s:3:"XFO";i:1;s:38:"ФренÑки златен франк";}s:3:"XOF";a:2:{i:0;s:3:"XOF";i:1;s:27:"Бенин - CFA франк";}s:3:"XPF";a:2:{i:0;s:4:"CFPF";i:1;s:49:"ФренÑкополинезийÑки франк";}s:3:"YDD";a:2:{i:0;s:3:"YDD";i:1;s:27:"ЙеменÑки динар";}s:3:"YER";a:2:{i:0;s:3:"YRl";i:1;s:25:"ЙеменÑки риал";}s:3:"YUM";a:2:{i:0;s:3:"YUM";i:1;s:31:"ЮгоÑлавÑки динар";}s:3:"YUN";a:2:{i:0;s:3:"YUN";i:1;s:56:"ЮгоÑлавÑки конвертируем динар";}s:3:"ZAL";a:2:{i:0;s:3:"ZAL";i:1;s:56:"ЮжноафриканÑки ранд (финанÑов)";}s:3:"ZAP";a:2:{i:0;s:3:"ZAP";i:1;s:37:"ЮжноафриканÑка лира";}s:3:"ZAR";a:2:{i:0;s:1:"R";i:1;s:37:"ЮжноафриканÑки ранд";}s:3:"ZMK";a:2:{i:0;s:3:"ZMK";i:1;s:29:"ЗамбийÑка квача";}s:3:"ZMP";a:2:{i:0;s:3:"ZMP";i:1;s:27:"ЗамбийÑка лира";}s:3:"ZRN";a:2:{i:0;s:3:"ZRN";i:1;s:34:"ЗаирÑко ново зайре";}s:3:"ZRZ";a:2:{i:0;s:3:"ZRZ";i:1;s:25:"ЗаирÑко зайре";}s:3:"ZWD";a:2:{i:0;s:2:"Z$";i:1;s:35:"ЗимбабвийÑки долар";}}s:4:"Keys";a:3:{s:8:"calendar";a:1:{i:0;s:16:"Календар";}s:9:"collation";a:1:{i:0;s:18:"Сортиране";}s:8:"currency";a:1:{i:0;s:12:"Валути";}}s:9:"Languages";a:178:{s:2:"ab";a:1:{i:0;s:18:"ÐбкхазÑки";}s:2:"af";a:1:{i:0;s:16:"ÐфриканÑ";}s:3:"afa";a:1:{i:0;s:38:"Ðфро-азиатÑки (други)";}s:3:"afh";a:1:{i:0;s:16:"Ðфрихили";}s:3:"ale";a:1:{i:0;s:16:"ÐлеутÑки";}s:2:"am";a:1:{i:0;s:16:"ÐмхарÑки";}s:3:"ang";a:1:{i:0;s:42:"СтароанглийÑки (ca.450-1100)";}s:3:"apa";a:1:{i:0;s:30:"Езици на апахите";}s:2:"ar";a:1:{i:0;s:14:"ÐрабÑки";}s:3:"art";a:1:{i:0;s:31:"ИзкуÑтвен (други)";}s:3:"aus";a:1:{i:0;s:35:"ÐвÑтралийÑки езици";}s:2:"av";a:1:{i:0;s:14:"ÐварÑки";}s:2:"ay";a:1:{i:0;s:12:"Ðймара";}s:2:"az";a:1:{i:0;s:28:"ÐзербайджанÑки";}s:2:"ba";a:1:{i:0;s:18:"БашкирÑки";}s:3:"bat";a:1:{i:0;s:37:"ПрибалтийÑки (други)";}s:2:"be";a:1:{i:0;s:18:"БеларуÑки";}s:3:"ber";a:1:{i:0;s:18:"берберÑки";}s:2:"bg";a:1:{i:0;s:18:"БългарÑки";}s:2:"bn";a:1:{i:0;s:18:"БенгалÑки";}s:3:"bnt";a:1:{i:0;s:10:"Банту";}s:2:"bo";a:1:{i:0;s:16:"ТибетÑки";}s:2:"br";a:1:{i:0;s:18:"БретонÑки";}s:2:"bs";a:1:{i:0;s:18:"БоÑненÑки";}s:2:"ca";a:1:{i:0;s:20:"КаталонÑки";}s:3:"cai";a:1:{i:0;s:72:"ЦентралноамериканÑки индианÑки (други)";}s:3:"car";a:1:{i:0;s:16:"КарибÑки";}s:3:"cau";a:1:{i:0;s:31:"КавказÑки (други)";}s:2:"ce";a:1:{i:0;s:16:"ЧеченÑки";}s:3:"cel";a:1:{i:0;s:27:"КелтÑки (други)";}s:3:"chr";a:1:{i:0;s:12:"чероки";}s:3:"chy";a:1:{i:0;s:16:"чейенÑки";}s:2:"co";a:1:{i:0;s:22:"КорÑиканÑки";}s:3:"cpe";a:1:{i:0;s:54:"КреолÑки, от английÑки (други)";}s:3:"cpf";a:1:{i:0;s:50:"КреолÑки, от френÑки (други)";}s:3:"cpp";a:1:{i:0;s:58:"КреолÑки, от португалÑки (други)";}s:3:"crp";a:1:{i:0;s:29:"КреолÑки (други)";}s:2:"cs";a:1:{i:0;s:10:"Чешки";}s:2:"cu";a:1:{i:0;s:35:"Църковно ÑлавÑнÑки";}s:2:"cy";a:1:{i:0;s:12:"УелÑки";}s:2:"da";a:1:{i:0;s:12:"ДатÑки";}s:2:"de";a:1:{i:0;s:12:"ÐемÑки";}s:3:"den";a:1:{i:0;s:18:"СлавÑнÑки";}s:3:"dum";a:1:{i:0;s:58:"ХоландÑки, Ñредновековен (1050-1350)";}s:2:"dv";a:1:{i:0;s:12:"Дивехи";}s:3:"egy";a:1:{i:0;s:33:"ЕгипетÑки (древен)";}s:2:"el";a:1:{i:0;s:12:"Гръцки";}s:2:"en";a:1:{i:0;s:18:"ÐнглийÑки";}s:3:"enm";a:1:{i:0;s:30:"ÐнглийÑки (1100-1500)";}s:2:"eo";a:1:{i:0;s:18:"ЕÑперанто";}s:2:"es";a:1:{i:0;s:16:"ИÑпанÑки";}s:2:"et";a:1:{i:0;s:16:"ЕÑтонÑки";}s:2:"eu";a:1:{i:0;s:10:"БаÑки";}s:2:"fa";a:1:{i:0;s:18:"ПерÑийÑки";}s:2:"fi";a:1:{i:0;s:12:"ФинÑки";}s:3:"fiu";a:1:{i:0;s:34:"УгрофинÑка (други)";}s:2:"fr";a:1:{i:0;s:14:"ФренÑки";}s:3:"frm";a:1:{i:0;s:26:"ФренÑки (1400-1600)";}s:3:"fro";a:1:{i:0;s:25:"ФренÑки (842-1400)";}s:2:"ga";a:1:{i:0;s:18:"ИрландÑки";}s:2:"gd";a:1:{i:0;s:33:"ШотландÑки галÑки";}s:3:"gem";a:1:{i:0;s:31:"ГерманÑки (други)";}s:3:"gmh";a:1:{i:0;s:24:"ÐемÑки (1050-1500)";}s:3:"goh";a:1:{i:0;s:23:"ÐемÑки (750-1050)";}s:3:"got";a:1:{i:0;s:18:"ГотичеÑки";}s:3:"grc";a:1:{i:0;s:36:"Древногръцки (до 1453)";}s:2:"gu";a:1:{i:0;s:18:"Гуджарати";}s:3:"haw";a:1:{i:0;s:16:"ХавайÑки";}s:2:"he";a:1:{i:0;s:10:"Иврит";}s:2:"hi";a:1:{i:0;s:10:"Хинди";}s:3:"hit";a:1:{i:0;s:12:"ХитÑки";}s:2:"hr";a:1:{i:0;s:18:"ХърватÑки";}s:2:"ht";a:1:{i:0;s:18:"ХаитÑнÑки";}s:2:"hu";a:1:{i:0;s:16:"УнгарÑки";}s:2:"hy";a:1:{i:0;s:16:"ÐрменÑки";}s:2:"id";a:1:{i:0;s:24:"ИндонезийÑки";}s:3:"inc";a:1:{i:0;s:29:"ИндийÑки (други)";}s:3:"ine";a:1:{i:0;s:42:"Индо-европейÑки (други)";}s:2:"io";a:1:{i:0;s:6:"Идо";}s:3:"ira";a:1:{i:0;s:14:"ИранÑки";}s:2:"is";a:1:{i:0;s:18:"ИÑландÑки";}s:2:"it";a:1:{i:0;s:20:"ИталианÑки";}s:2:"ja";a:1:{i:0;s:14:"ЯпонÑки";}s:3:"jpr";a:1:{i:0;s:35:"еврейÑко-перÑийÑки";}s:3:"jrb";a:1:{i:0;s:31:"еврейÑко-арабÑки";}s:2:"jv";a:1:{i:0;s:14:"ЯванÑки";}s:2:"ka";a:1:{i:0;s:18:"ГрузинÑки";}s:2:"kg";a:1:{i:0;s:20:"КонгоанÑки";}s:2:"ki";a:1:{i:0;s:12:"кикуйу";}s:2:"kk";a:1:{i:0;s:16:"КазахÑки";}s:2:"km";a:1:{i:0;s:16:"КхмерÑки";}s:2:"ko";a:1:{i:0;s:16:"КорейÑки";}s:2:"ks";a:1:{i:0;s:18:"КашмирÑки";}s:2:"ku";a:1:{i:0;s:14:"КюрдÑки";}s:2:"ky";a:1:{i:0;s:18:"КиргизÑки";}s:2:"la";a:1:{i:0;s:16:"ЛатинÑки";}s:2:"lb";a:1:{i:0;s:26:"ЛюкÑембургÑки";}s:2:"lo";a:1:{i:0;s:12:"ЛаоÑки";}s:2:"lt";a:1:{i:0;s:16:"ЛитовÑки";}s:2:"lv";a:1:{i:0;s:18:"ЛатвийÑки";}s:3:"mas";a:1:{i:0;s:16:"маÑайÑки";}s:2:"mg";a:1:{i:0;s:16:"Малгашки";}s:3:"mga";a:1:{i:0;s:29:"ИрландÑки (900-1200)";}s:2:"mi";a:1:{i:0;s:14:"МаорÑки";}s:3:"mis";a:1:{i:0;s:21:"Други езици";}s:2:"mk";a:1:{i:0;s:20:"МакедонÑки";}s:2:"ml";a:1:{i:0;s:16:"МалайÑки";}s:2:"mn";a:1:{i:0;s:18:"МонголÑки";}s:2:"mo";a:1:{i:0;s:18:"МолдовÑки";}s:2:"ms";a:1:{i:0;s:16:"МалайÑки";}s:2:"mt";a:1:{i:0;s:18:"МалтийÑки";}s:2:"my";a:1:{i:0;s:18:"БирманÑки";}s:3:"nai";a:1:{i:0;s:68:"СеверноамериканÑки индианÑки (други)";}s:3:"nap";a:1:{i:0;s:26:"ÐеаполитанÑки";}s:2:"ne";a:1:{i:0;s:16:"ÐепалÑки";}s:2:"nl";a:1:{i:0;s:18:"ХоландÑки";}s:2:"no";a:1:{i:0;s:16:"Ðорвежки";}s:3:"nub";a:1:{i:0;s:27:"ÐубийÑки езици";}s:2:"ny";a:1:{i:0;s:16:"ЧинÑнджа";}s:2:"os";a:1:{i:0;s:14:"ОÑетÑки";}s:3:"ota";a:1:{i:0;s:44:"ТурÑки, отоманÑки (1500-1928)";}s:3:"oto";a:1:{i:0;s:33:"СтаротурÑки езици";}s:2:"pa";a:1:{i:0;s:20:"ПенджабÑки";}s:3:"paa";a:1:{i:0;s:29:"ПапуаÑки (други)";}s:3:"peo";a:1:{i:0;s:50:"СтароперÑийÑки (600-400 пр.н.е.)";}s:3:"phi";a:1:{i:0;s:33:"ФилипинÑки (други)";}s:3:"phn";a:1:{i:0;s:20:"ФиникийÑки";}s:2:"pl";a:1:{i:0;s:12:"ПолÑки";}s:3:"pro";a:1:{i:0;s:34:"ПрованÑалÑки (to 1500)";}s:2:"ps";a:1:{i:0;s:8:"Пущу";}s:2:"pt";a:1:{i:0;s:22:"ПортугалÑки";}s:2:"qu";a:1:{i:0;s:10:"Кечуа";}s:3:"raj";a:1:{i:0;s:24:"РаджаÑтанÑки";}s:2:"rm";a:1:{i:0;s:24:"РетороманÑки";}s:2:"rn";a:1:{i:0;s:10:"Рунди";}s:2:"ro";a:1:{i:0;s:16:"РумънÑки";}s:3:"roa";a:1:{i:0;s:29:"РоманÑки (други)";}s:2:"ru";a:1:{i:0;s:10:"РуÑки";}s:2:"rw";a:1:{i:0;s:20:"КинÑруанда";}s:2:"sa";a:1:{i:0;s:24:"СанкÑкритÑки";}s:3:"sah";a:1:{i:0;s:14:"ЯкутÑки";}s:3:"sai";a:1:{i:0;s:62:"ЮжноамериканÑки индианÑки (други)";}s:2:"sc";a:1:{i:0;s:18:"СардинÑки";}s:3:"sem";a:1:{i:0;s:29:"СемитÑки (други)";}s:2:"sg";a:1:{i:0;s:10:"Санго";}s:3:"sga";a:1:{i:0;s:39:"СтароирландÑки (до 900)";}s:2:"sh";a:1:{i:0;s:28:"СърбохърватÑки";}s:2:"si";a:1:{i:0;s:18:"СинхалÑки";}s:2:"sk";a:1:{i:0;s:16:"Словашки";}s:2:"sl";a:1:{i:0;s:18:"СловенÑки";}s:3:"sla";a:1:{i:0;s:31:"СлавÑнÑки (други)";}s:2:"sm";a:1:{i:0;s:18:"СамоанÑки";}s:2:"so";a:1:{i:0;s:20:"СомалийÑки";}s:2:"sq";a:1:{i:0;s:16:"ÐлбанÑки";}s:2:"sr";a:1:{i:0;s:14:"СръбÑки";}s:2:"ss";a:1:{i:0;s:10:"Суази";}s:2:"st";a:1:{i:0;s:12:"СеÑуто";}s:3:"sux";a:1:{i:0;s:16:"ШумерÑки";}s:2:"sv";a:1:{i:0;s:14:"ШведÑки";}s:2:"sw";a:1:{i:0;s:14:"Суахили";}s:3:"syr";a:1:{i:0;s:16:"СирийÑки";}s:2:"ta";a:1:{i:0;s:16:"ТамилÑки";}s:3:"tai";a:1:{i:0;s:33:"ТайландÑки (други)";}s:2:"te";a:1:{i:0;s:12:"Телугу";}s:2:"tg";a:1:{i:0;s:18:"ТаджикÑки";}s:2:"th";a:1:{i:0;s:6:"Таи";}s:2:"tk";a:1:{i:0;s:20:"ТуркменÑки";}s:2:"tr";a:1:{i:0;s:12:"ТурÑки";}s:2:"tt";a:1:{i:0;s:16:"ТатарÑки";}s:3:"tut";a:1:{i:0;s:29:"ÐлтайÑки (други)";}s:2:"ty";a:1:{i:0;s:18:"ТаитÑнÑки";}s:2:"uk";a:1:{i:0;s:18:"УкраинÑки";}s:3:"und";a:1:{i:0;s:22:"Ðеопределен";}s:2:"ur";a:1:{i:0;s:8:"Урду";}s:2:"uz";a:1:{i:0;s:16:"УзбекÑки";}s:2:"vi";a:1:{i:0;s:20:"ВиетнамÑки";}s:2:"zh";a:1:{i:0;s:16:"КитайÑки";}s:2:"zu";a:1:{i:0;s:14:"ЗулуÑки";}}s:12:"LocaleScript";a:1:{i:0;s:4:"Cyrl";}s:14:"NumberElements";a:12:{i:0;s:1:",";i:1;s:2:" ";i:2;s:1:";";i:3;s:1:"%";i:4;s:1:"0";i:5;s:1:"#";i:6;s:1:"-";i:7;s:1:"E";i:8;s:3:"‰";i:9;s:3:"∞";i:10;s:3:"�";i:11;s:1:"+";}s:7:"Scripts";a:31:{s:4:"Arab";a:1:{i:0;s:14:"ÐрабÑка";}s:4:"Armn";a:1:{i:0;s:16:"ÐрменÑка";}s:4:"Beng";a:1:{i:0;s:18:"БенгалÑка";}s:4:"Brai";a:1:{i:0;s:16:"Брайлова";}s:4:"Cher";a:1:{i:0;s:12:"Чероки";}s:4:"Copt";a:1:{i:0;s:14:"КоптÑка";}s:4:"Cyrl";a:1:{i:0;s:16:"Кирилица";}s:4:"Deva";a:1:{i:0;s:20:"Деванагари";}s:4:"Ethi";a:1:{i:0;s:16:"ЕтиопÑка";}s:4:"Geor";a:1:{i:0;s:18:"ГрузинÑка";}s:4:"Goth";a:1:{i:0;s:18:"ГотичеÑка";}s:4:"Grek";a:1:{i:0;s:12:"Гръцка";}s:4:"Gujr";a:1:{i:0;s:18:"Гуджарати";}s:4:"Hang";a:1:{i:0;s:16:"КорейÑка";}s:4:"Hani";a:1:{i:0;s:16:"КитайÑка";}s:4:"Hans";a:1:{i:0;s:33:"ОпроÑтен китайÑки";}s:4:"Hant";a:1:{i:0;s:39:"Традиционен китайÑки";}s:4:"Hebr";a:1:{i:0;s:10:"Иврит";}s:4:"Hira";a:1:{i:0;s:31:"ЯпонÑки хирагана";}s:4:"Kana";a:1:{i:0;s:31:"ЯпонÑки катакана";}s:4:"Khmr";a:1:{i:0;s:16:"КхмерÑка";}s:4:"Laoo";a:1:{i:0;s:12:"ЛаоÑка";}s:4:"Latn";a:1:{i:0;s:16:"ЛатинÑка";}s:4:"Mong";a:1:{i:0;s:18:"МонголÑка";}s:4:"Mymr";a:1:{i:0;s:18:"БирманÑка";}s:4:"Runr";a:1:{i:0;s:18:"РуничеÑка";}s:4:"Taml";a:1:{i:0;s:16:"ТамилÑка";}s:4:"Telu";a:1:{i:0;s:12:"Телугу";}s:4:"Thai";a:1:{i:0;s:6:"Таи";}s:4:"Tibt";a:1:{i:0;s:16:"ТибетÑка";}s:4:"Zyyy";a:1:{i:0;s:8:"Обща";}}s:5:"Types";a:2:{s:8:"calendar";a:7:{s:8:"buddhist";a:1:{i:0;s:33:"БудиÑтки календар";}s:7:"chinese";a:1:{i:0;s:33:"КитайÑки календар";}s:9:"gregorian";a:1:{i:0;s:41:"ГригорианÑки календар";}s:6:"hebrew";a:1:{i:0;s:33:"ЕврейÑки календар";}s:7:"islamic";a:1:{i:0;s:33:"ИÑлÑмÑки календар";}s:13:"islamic-civil";a:1:{i:0;s:48:"ИÑлÑмÑки цивилен календар";}s:8:"japanese";a:1:{i:0;s:31:"ЯпонÑки календар";}}s:9:"collation";a:5:{s:6:"direct";a:1:{i:0;s:16:"Директно";}s:9:"phonebook";a:1:{i:0;s:21:"Ðзбучен ред";}s:6:"pinyin";a:1:{i:0;s:25:"Сортиране Pinyin";}s:6:"stroke";a:1:{i:0;s:32:"Сортиране по щрих";}s:11:"traditional";a:1:{i:0;s:22:"Традиционно";}}}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:5:{s:26:"DateTimeElements:intvector";a:2:{i:0;i:2;i:1;i:1;}s:16:"DateTimePatterns";a:9:{i:0;s:10:"HH:mm:ss z";i:1;s:8:"HH:mm:ss";i:2;s:8:"HH:mm:ss";i:3;s:5:"HH:mm";i:4;s:18:"dd MMMM yyyy, EEEE";i:5;s:12:"dd MMMM yyyy";i:6;s:10:"dd.MM.yyyy";i:7;s:8:"dd.MM.yy";i:8;s:7:"{1} {0}";}s:8:"dayNames";a:1:{s:6:"format";a:3:{s:11:"abbreviated";a:7:{i:0;s:7:"нед.";i:1;s:7:"пон.";i:2;s:5:"вт.";i:3;s:5:"ÑÑ€.";i:4;s:9:"четв.";i:5;s:7:"пет.";i:6;s:7:"Ñъб.";}s:6:"narrow";a:7:{i:0;s:2:"н";i:1;s:2:"п";i:2;s:2:"в";i:3;s:2:"Ñ";i:4;s:2:"ч";i:5;s:2:"п";i:6;s:2:"Ñ";}s:4:"wide";a:7:{i:0;s:12:"неделÑ";i:1;s:20:"понеделник";i:2;s:14:"вторник";i:3;s:10:"ÑÑ€Ñда";i:4;s:18:"четвъртък";i:5;s:10:"петък";i:6;s:12:"Ñъбота";}}}s:4:"eras";a:1:{s:11:"abbreviated";a:2:{i:0;s:11:"пр.н.е.";i:1;s:6:"н.е.";}}s:10:"monthNames";a:1:{s:6:"format";a:3:{s:11:"abbreviated";a:12:{i:0;s:5:"Ñн.";i:1;s:7:"фев.";i:2;s:8:"март";i:3;s:7:"апр.";i:4;s:6:"май";i:5;s:6:"юни";i:6;s:6:"юли";i:7;s:7:"авг.";i:8;s:7:"Ñеп.";i:9;s:7:"окт.";i:10;s:9:"ноем.";i:11;s:7:"дек.";}s:6:"narrow";a:12:{i:0;s:2:"Ñ";i:1;s:2:"Ñ„";i:2;s:2:"м";i:3;s:2:"а";i:4;s:2:"м";i:5;s:2:"ÑŽ";i:6;s:2:"ÑŽ";i:7;s:2:"а";i:8;s:2:"Ñ";i:9;s:2:"о";i:10;s:2:"н";i:11;s:2:"д";}s:4:"wide";a:12:{i:0;s:12:"Ñнуари";i:1;s:16:"февруари";i:2;s:8:"март";i:3;s:10:"април";i:4;s:6:"май";i:5;s:6:"юни";i:6;s:6:"юли";i:7;s:12:"авгуÑÑ‚";i:8;s:18:"Ñептември";i:9;s:16:"октомври";i:10;s:14:"ноември";i:11;s:16:"декември";}}}}}s:17:"localPatternChars";a:1:{i:0;s:24:"GanjkHmsSEDFwWxhKzAeugXZ";}s:11:"zoneStrings";a:17:{i:0;a:6:{i:0;s:19:"America/Los_Angeles";i:1;s:46:"ТихоокеанÑка чаÑова зона";i:2;s:3:"PST";i:3;s:57:"ТихоокеанÑка лÑтна чаÑова зона";i:4;s:3:"PDT";i:5;s:21:"Ð›Ð¾Ñ ÐнжелиÑ";}i:1;a:6:{i:0;s:14:"America/Denver";i:1;s:63:"ÐмериканÑка планинÑка чаÑова зона";i:2;s:3:"MST";i:3;s:74:"ÐмериканÑка планинÑка лÑтна чаÑова зона";i:4;s:3:"MDT";i:5;s:12:"Денвър";}i:2;a:6:{i:0;s:15:"America/Phoenix";i:1;s:63:"ÐмериканÑка планинÑка чаÑова зона";i:2;s:3:"MST";i:3;s:63:"ÐмериканÑка планинÑка чаÑова зона";i:4;s:3:"MST";i:5;s:12:"ФиникÑ";}i:3;a:6:{i:0;s:15:"America/Chicago";i:1;s:63:"ÐмериканÑка централна чаÑова зона";i:2;s:3:"CST";i:3;s:74:"ÐмериканÑка централна лÑтна чаÑова зона";i:4;s:3:"CDT";i:5;s:12:"Чикаго";}i:4;a:6:{i:0;s:16:"America/New_York";i:1;s:59:"ÐмериканÑка източна чаÑова зона";i:2;s:3:"EST";i:3;s:70:"ÐмериканÑка източна лÑтна чаÑова зона";i:4;s:3:"EDT";i:5;s:13:"ÐÑŽ Йорк";}i:5;a:6:{i:0;s:20:"America/Indianapolis";i:1;s:59:"ÐмериканÑка източна чаÑова зона";i:2;s:3:"EST";i:3;s:59:"ÐмериканÑка източна чаÑова зона";i:4;s:3:"EST";i:5;s:24:"ИндианополиÑ";}i:6;a:6:{i:0;s:16:"Pacific/Honolulu";i:1;s:32:"ЧаÑова зона Хавай";i:2;s:3:"HST";i:3;s:43:"ЛÑтна чаÑова зона Хавай";i:4;s:3:"HST";i:5;s:16:"Хонолулу";}i:7;a:6:{i:0;s:17:"America/Anchorage";i:1;s:34:"ЧаÑова зона ÐлÑÑка";i:2;s:3:"AST";i:3;s:45:"ЛÑтна чаÑова зона ÐлÑÑка";i:4;s:3:"ADT";i:5;s:9:"Anchorage";}i:8;a:6:{i:0;s:15:"America/Halifax";i:1;s:46:"ÐтлантичеÑка чаÑова зона";i:2;s:3:"AST";i:3;s:57:"ÐтлантичеÑка лÑтна чаÑова зона";i:4;s:3:"ADT";i:5;s:16:"ХалифакÑ";}i:9;a:6:{i:0;s:16:"America/St_Johns";i:1;s:44:"ЧаÑова зона Ðюфаундленд";i:2;s:3:"CNT";i:3;s:55:"ЛÑтна чаÑова зона Ðюфаундленд";i:4;s:3:"CDT";i:5;s:23:"Сейнт ДжоунÑ";}i:10;a:6:{i:0;s:12:"Europe/Paris";i:1;s:60:"ЦентралноевропейÑка чаÑова зона";i:2;s:3:"CET";i:3;s:69:"ЦентралноевропеÑка лÑтна чаÑова зона";i:4;s:4:"CEST";i:5;s:10:"Париж";}i:11;a:6:{i:0;s:7:"Etc/GMT";i:1;s:36:"ЧаÑова зона Гринуич";i:2;s:3:"GMT";i:3;s:36:"ЧаÑова зона Гринуич";i:4;s:3:"GMT";i:5;s:12:"Лондон";}i:12;a:6:{i:0;s:17:"Africa/Casablanca";i:1;s:36:"ЧаÑова зона Гринуич";i:2;s:3:"GMT";i:3;s:36:"ЧаÑова зона Гринуич";i:4;s:3:"GMT";i:5;s:20:"Казабланка";}i:13;a:6:{i:0;s:14:"Asia/Jerusalem";i:1;s:34:"ЧаÑова зона Израел";i:2;s:3:"IST";i:3;s:45:"ЛÑтна чаÑова зона Израел";i:4;s:3:"IDT";i:5;s:18:"ЙеруÑалим";}i:14;a:6:{i:0;s:10:"Asia/Tokyo";i:1;s:36:"ЯпонÑка чаÑова зона";i:2;s:3:"JST";i:3;s:36:"ЯпонÑка чаÑова зона";i:4;s:3:"JST";i:5;s:10:"Токио";}i:15;a:6:{i:0;s:16:"Europe/Bucharest";i:1;s:56:"ИзточноевропейÑка чаÑова зона";i:2;s:3:"EET";i:3;s:67:"ИзточноевропейÑка лÑтна чаÑова зона";i:4;s:4:"EEST";i:5;s:14:"Букурещ";}i:16;a:6:{i:0;s:13:"Asia/Shanghai";i:1;s:38:"КитайÑка чаÑова зона";i:2;s:3:"CTT";i:3;s:38:"КитайÑка чаÑова зона";i:4;s:3:"CDT";i:5;s:12:"Шанхай";}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/bg_BG.dat b/framework/I18N/core/data/bg_BG.dat
new file mode 100644
index 00000000..6ecaa281
--- /dev/null
+++ b/framework/I18N/core/data/bg_BG.dat
@@ -0,0 +1 @@
+a:2:{s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;-#,##0.###";i:1;s:24:"#,##0.00 ¤;-#,##0.00 ¤";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/bn.dat b/framework/I18N/core/data/bn.dat
new file mode 100644
index 00000000..bbb46606
--- /dev/null
+++ b/framework/I18N/core/data/bn.dat
@@ -0,0 +1 @@
+a:6:{s:9:"Countries";a:107:{s:2:"AF";a:1:{i:0;s:33:"আফগানিসà§à¦¤à¦¾à¦¨";}s:2:"AL";a:1:{i:0;s:30:"আলবà§à¦¯à¦¾à¦¨à¦¿à§Ÿà¦¾";}s:2:"AM";a:1:{i:0;s:27:"আরà§à¦®à§‡à¦¨à¦¿à§Ÿà¦¾";}s:2:"AR";a:1:{i:0;s:36:"আরà§à¦œà§‡à¦£à§à¦Ÿà¦¾à¦‡à¦¨à¦¾";}s:2:"AT";a:1:{i:0;s:27:"অসà§à¦Ÿà§à¦°à¦¿à§Ÿà¦¾";}s:2:"AU";a:1:{i:0;s:33:"অসà§à¦Ÿà§à¦°à§‡à¦²à¦¿à§Ÿà¦¾";}s:2:"AZ";a:1:{i:0;s:30:"আজারবাইজান";}s:2:"BD";a:1:{i:0;s:24:"বাংলাদেশ";}s:2:"BE";a:1:{i:0;s:24:"বেলà§à¦œà¦¿à§Ÿà¦®";}s:2:"BG";a:1:{i:0;s:27:"বà§à¦²à¦—েরিয়া";}s:2:"BO";a:1:{i:0;s:24:"বোলিà¦à¦¿à§Ÿà¦¾";}s:2:"BR";a:1:{i:0;s:21:"বà§à¦°à¦¾à¦œà¦¿à¦²";}s:2:"BT";a:1:{i:0;s:15:"à¦à§à¦Ÿà¦¾à¦¨";}s:2:"BY";a:1:{i:0;s:30:"বেলোরà§à¦¶à¦¿à§Ÿà¦¾";}s:2:"CG";a:1:{i:0;s:15:"কঙà§à¦—ো";}s:2:"CH";a:1:{i:0;s:30:"সà§à¦‡à¦œà¦°à§à¦²à¦£à§à¦¡";}s:2:"CL";a:1:{i:0;s:12:"চিলি";}s:2:"CN";a:1:{i:0;s:9:"চীন";}s:2:"CO";a:1:{i:0;s:30:"কোলোমà§à¦¬à¦¿à§Ÿà¦¾";}s:2:"CR";a:1:{i:0;s:30:"কোসà§à¦Ÿà¦¾à¦°à¦¿à¦•à¦¾";}s:2:"CU";a:1:{i:0;s:15:"কিউবা";}s:2:"CZ";a:1:{i:0;s:18:"চেকিয়া";}s:2:"DE";a:1:{i:0;s:24:"জারà§à¦®à¦¾à¦¨à¦¿";}s:2:"DK";a:1:{i:0;s:27:"ডেনà§à¦®à¦¾à¦°à§à¦•";}s:2:"DZ";a:1:{i:0;s:24:"à¦à¦²à¦œà¦¿à¦°à¦¿à§Ÿà¦¾";}s:2:"EC";a:1:{i:0;s:21:"ইকোয়াডর";}s:2:"EE";a:1:{i:0;s:27:"à¦à¦¸à§à¦¤à§‹à¦¨à¦¿à§Ÿà¦¾";}s:2:"EG";a:1:{i:0;s:12:"মিশর";}s:2:"EH";a:1:{i:0;s:40:"পশà§à¦šà¦¿à¦®à§€ সাহারা";}s:2:"ES";a:1:{i:0;s:15:"সà§à¦ªà§‡à¦¨";}s:2:"ET";a:1:{i:0;s:24:"ইফিওপিয়া";}s:2:"FI";a:1:{i:0;s:33:"ফিনà§à¦²à§à¦¯à¦¾à¦£à§à¦¡";}s:2:"FR";a:1:{i:0;s:21:"ফà§à¦°à¦¾à¦¨à§à¦¸";}s:2:"GB";a:1:{i:0;s:30:"গà§à¦°à§‡à¦Ÿà¦¬à§ƒà¦Ÿà§‡à¦¨";}s:2:"GE";a:1:{i:0;s:21:"জরà§à¦œà¦¿à§Ÿà¦¾";}s:2:"GH";a:1:{i:0;s:12:"গানা";}s:2:"GR";a:1:{i:0;s:18:"গà§à¦°à§€à¦¸à§";}s:2:"GT";a:1:{i:0;s:30:"গোয়াটিমালা";}s:2:"GY";a:1:{i:0;s:18:"গিয়ানা";}s:2:"HN";a:1:{i:0;s:24:"হণà§à¦¡à§à¦°à¦¾à¦¸";}s:2:"HU";a:1:{i:0;s:24:"হাঙà§à¦—েরি";}s:2:"ID";a:1:{i:0;s:33:"ইনà§à¦¦à§‹à¦¨à§‡à¦¶à¦¿à§Ÿà¦¾";}s:2:"IE";a:1:{i:0;s:27:"আয়ারà§à¦²à¦£à§à¦¡";}s:2:"IL";a:1:{i:0;s:24:"ইসà§à¦°à¦¾à§Ÿà§‡à¦²";}s:2:"IN";a:1:{i:0;s:12:"à¦à¦¾à¦°à¦¤";}s:2:"IQ";a:1:{i:0;s:12:"ইরাক";}s:2:"IR";a:1:{i:0;s:12:"ইরান";}s:2:"IS";a:1:{i:0;s:21:"আইসলণà§à¦¡";}s:2:"IT";a:1:{i:0;s:15:"ইতালী";}s:2:"JM";a:1:{i:0;s:24:"জà§à¦¯à¦¾à¦®à§‡à¦•à¦¾";}s:2:"JO";a:1:{i:0;s:15:"জরà§à¦¡à¦¨";}s:2:"JP";a:1:{i:0;s:15:"জাপান";}s:2:"KE";a:1:{i:0;s:18:"কেনিয়া";}s:2:"KG";a:1:{i:0;s:30:"কিরà§à¦—িজিয়া";}s:2:"KH";a:1:{i:0;s:21:"কামà§à¦¬à§‹à¦œ";}s:2:"KR";a:1:{i:0;s:37:"দকà§à¦·à¦¿à¦£ কোরিয়া";}s:2:"KZ";a:1:{i:0;s:30:"কাজাকসà§à¦¥à¦¾à¦¨";}s:2:"LA";a:1:{i:0;s:12:"লাওস";}s:2:"LB";a:1:{i:0;s:18:"লেবানন";}s:2:"LK";a:1:{i:0;s:27:"শà§à¦°à§€à¦²à¦™à§à¦•à¦¾";}s:2:"LR";a:1:{i:0;s:27:"লাইবিরিয়া";}s:2:"LT";a:1:{i:0;s:18:"লিতà§à¦à¦¾";}s:2:"LU";a:1:{i:0;s:36:"লাকà§à¦¸à§‡à¦®à¦¬à¦¾à¦°à§à¦—";}s:2:"LV";a:1:{i:0;s:24:"লাতà§à¦à¦¿à§Ÿà¦¾";}s:2:"LY";a:1:{i:0;s:18:"লিবিয়া";}s:2:"MA";a:1:{i:0;s:21:"মোরকà§à¦•à§‹";}s:2:"MD";a:1:{i:0;s:30:"মোলà§à¦¦à¦¾à¦à¦¿à§Ÿà¦¾";}s:2:"MG";a:1:{i:0;s:33:"মাদাগাসà§à¦•à¦¾à¦°";}s:2:"MN";a:1:{i:0;s:27:"মঙà§à¦—োলিয়া";}s:2:"MX";a:1:{i:0;s:21:"মকà§à¦¸à¦¿à¦•à§‹";}s:2:"MY";a:1:{i:0;s:30:"মালà§à¦¯à¦¾à¦¶à¦¿à§Ÿà¦¾";}s:2:"NI";a:1:{i:0;s:30:"নিকারাগোয়া";}s:2:"NL";a:1:{i:0;s:15:"হলণà§à¦¡";}s:2:"NO";a:1:{i:0;s:15:"নরওয়ে";}s:2:"NP";a:1:{i:0;s:15:"নেপাল";}s:2:"NZ";a:1:{i:0;s:28:"নিউ জিলণà§à¦¡";}s:2:"PA";a:1:{i:0;s:18:"পানামা";}s:2:"PE";a:1:{i:0;s:12:"পিরà§";}s:2:"PH";a:1:{i:0;s:24:"ফিলিপাইন";}s:2:"PK";a:1:{i:0;s:27:"পাকিসà§à¦¤à¦¾à¦¨";}s:2:"PL";a:1:{i:0;s:27:"পোলà§à¦¯à¦¾à¦£à§à¦¡";}s:2:"PT";a:1:{i:0;s:24:"পরà§à¦¤à§à¦—াল";}s:2:"PY";a:1:{i:0;s:30:"পà§à¦¯à¦¾à¦°à¦¾à¦—োয়ে";}s:2:"RO";a:1:{i:0;s:24:"রà§à¦®à¦¾à¦¨à¦¿à§Ÿà¦¾";}s:2:"RU";a:1:{i:0;s:18:"রাশিয়া";}s:2:"SA";a:1:{i:0;s:25:"সাউদি আরব";}s:2:"SD";a:1:{i:0;s:15:"সà§à¦¦à¦¾à¦¨";}s:2:"SE";a:1:{i:0;s:18:"সà§à¦‡à¦¡à§‡à¦¨";}s:2:"SG";a:1:{i:0;s:27:"সিঙà§à¦—াপà§à¦°";}s:2:"SK";a:1:{i:0;s:30:"শà§à¦²à§‹à¦à¦¾à¦•à¦¿à§Ÿà¦¾";}s:2:"SO";a:1:{i:0;s:18:"সোমালি";}s:2:"SV";a:1:{i:0;s:21:"সালà¦à§‡à¦¡à¦°";}s:2:"SY";a:1:{i:0;s:18:"সিরিয়া";}s:2:"TH";a:1:{i:0;s:9:"থাই";}s:2:"TJ";a:1:{i:0;s:30:"তাজিকসà§à¦¥à¦¾à¦¨";}s:2:"TM";a:1:{i:0;s:33:"তà§à¦°à§à¦•à¦®à§‡à¦¨à¦¿à§Ÿà¦¾";}s:2:"TN";a:1:{i:0;s:21:"টিউনিসà§";}s:2:"TR";a:1:{i:0;s:18:"তà§à¦°à¦¸à§à¦•";}s:2:"TW";a:1:{i:0;s:21:"তাইওয়ান";}s:2:"UA";a:1:{i:0;s:24:"ইউকà§à¦°à§‡à¦‡à¦¨";}s:2:"US";a:1:{i:0;s:58:"মারà§à¦•à¦¿à¦¨ যà§à¦•à§à¦¤à¦°à¦¾à¦·à§à¦Ÿà§à¦°";}s:2:"UY";a:1:{i:0;s:21:"উরà§à¦—োয়ে";}s:2:"UZ";a:1:{i:0;s:36:"উজà§à¦¬à§‡à¦•à¦¿à¦¸à§à¦¥à¦¾à¦¨";}s:2:"VE";a:1:{i:0;s:30:"à¦à§‡à¦¨à§‡à¦œà§à§Ÿà§‡à¦²à¦¾";}s:2:"VN";a:1:{i:0;s:24:"à¦à¦¿à§Ÿà§‡à¦¤à¦¨à¦¾à¦®";}s:2:"YE";a:1:{i:0;s:12:"ইমেন";}s:2:"ZA";a:1:{i:0;s:40:"দকà§à¦·à¦¿à¦£ আফà§à¦°à¦¿à¦•à¦¾";}}s:10:"Currencies";a:2:{s:3:"BDT";a:2:{i:0;s:3:"৳";i:1;s:3:"BDT";}s:3:"INR";a:2:{i:0;s:12:"টাকা";i:1;s:3:"INR";}}s:9:"Languages";a:1:{s:2:"bn";a:1:{i:0;s:15:"বাংলা";}}s:12:"LocaleScript";a:1:{i:0;s:4:"Beng";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:3:{s:11:"AmPmMarkers";a:2:{i:0;s:27:"পূরà§à¦¬à¦¾à¦¹à§à¦£";i:1;s:21:"অপরাহà§à¦£";}s:8:"dayNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:7:{i:0;s:9:"রবি";i:1;s:9:"সোম";i:2;s:15:"মঙà§à¦—ল";i:3;s:9:"বà§à¦§";i:4;s:24:"বৃহসà§à¦ªà¦¤à¦¿";i:5;s:15:"শà§à¦•à§à¦°";i:6;s:9:"শনি";}s:4:"wide";a:7:{i:0;s:18:"রবিবার";i:1;s:18:"সোমবার";i:2;s:24:"মঙà§à¦—লবার";i:3;s:18:"বà§à¦§à¦¬à¦¾à¦°";i:4;s:33:"বৃহষà§à¦ªà¦¤à¦¿à¦¬à¦¾à¦°";i:5;s:24:"শà§à¦•à§à¦°à¦¬à¦¾à¦°";i:6;s:18:"শনিবার";}}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:12:{i:0;s:24:"জানà§à§Ÿà¦¾à¦°à§€";i:1;s:30:"ফেবà§à¦°à§à§Ÿà¦¾à¦°à§€";i:2;s:15:"মারà§à¦š";i:3;s:18:"à¦à¦ªà§à¦°à¦¿à¦²";i:4;s:6:"মে";i:5;s:9:"জà§à¦¨";i:6;s:15:"জà§à¦²à¦¾à¦‡";i:7;s:15:"আগসà§à¦Ÿ";i:8;s:30:"সেপà§à¦Ÿà§‡à¦®à§à¦¬à¦°";i:9;s:21:"অকà§à¦Ÿà§‹à¦¬à¦°";i:10;s:21:"নà¦à§‡à¦®à§à¦¬à¦°";i:11;s:24:"ডিসেমà§à¦¬à¦°";}s:4:"wide";a:12:{i:0;s:24:"জানà§à§Ÿà¦¾à¦°à§€";i:1;s:30:"ফেবà§à¦°à§à§Ÿà¦¾à¦°à§€";i:2;s:15:"মারà§à¦š";i:3;s:18:"à¦à¦ªà§à¦°à¦¿à¦²";i:4;s:6:"মে";i:5;s:9:"জà§à¦¨";i:6;s:15:"জà§à¦²à¦¾à¦‡";i:7;s:15:"আগসà§à¦Ÿ";i:8;s:30:"সেপà§à¦Ÿà§‡à¦®à§à¦¬à¦°";i:9;s:21:"অকà§à¦Ÿà§‹à¦¬à¦°";i:10;s:21:"নà¦à§‡à¦®à§à¦¬à¦°";i:11;s:24:"ডিসেমà§à¦¬à¦°";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/bn_IN.dat b/framework/I18N/core/data/bn_IN.dat
new file mode 100644
index 00000000..e13234cb
--- /dev/null
+++ b/framework/I18N/core/data/bn_IN.dat
@@ -0,0 +1 @@
+a:3:{s:14:"NumberPatterns";a:4:{i:0;s:28:"##,##,##0.###;-##,##,##0.###";i:1;s:32:"¤ ##,##,##0.00;-¤ ##,##,##0.00";i:2;s:10:"##,##,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:3:{s:26:"DateTimeElements:intvector";a:2:{i:0;i:2;i:1;i:1;}s:16:"DateTimePatterns";a:9:{i:0;s:11:"h:mm:ss a z";i:1;s:11:"h:mm:ss a z";i:2;s:9:"h:mm:ss a";i:3;s:6:"h:mm a";i:4;s:16:"EEEE d MMMM yyyy";i:5;s:11:"d MMMM yyyy";i:6;s:10:"dd-MM-yyyy";i:7;s:6:"d-M-yy";i:8;s:7:"{1} {0}";}s:17:"weekend:intvector";a:4:{i:0;i:1;i:1;i:0;i:2;i:1;i:3;i:86400000;}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ca.dat b/framework/I18N/core/data/ca.dat
new file mode 100644
index 00000000..df2a2d9a
--- /dev/null
+++ b/framework/I18N/core/data/ca.dat
@@ -0,0 +1 @@
+a:8:{s:9:"Countries";a:196:{s:2:"AD";a:1:{i:0;s:7:"Andorra";}s:2:"AE";a:1:{i:0;s:25:"Unió dels Emirats Àrabs";}s:2:"AF";a:1:{i:0;s:10:"Afganistan";}s:2:"AI";a:1:{i:0;s:8:"Anguilla";}s:2:"AL";a:1:{i:0;s:8:"Albà nia";}s:2:"AM";a:1:{i:0;s:8:"Armènia";}s:2:"AN";a:1:{i:0;s:19:"Antilles Holandeses";}s:2:"AO";a:1:{i:0;s:6:"Angola";}s:2:"AR";a:1:{i:0;s:9:"Argentina";}s:2:"AT";a:1:{i:0;s:8:"Âustria";}s:2:"AU";a:1:{i:0;s:10:"Austrà lia";}s:2:"AW";a:1:{i:0;s:5:"Aruba";}s:2:"AZ";a:1:{i:0;s:11:"Azerbaidjan";}s:2:"BA";a:1:{i:0;s:21:"Bòsnia i Hercegovina";}s:2:"BB";a:1:{i:0;s:8:"Barbados";}s:2:"BD";a:1:{i:0;s:11:"Bangla Desh";}s:2:"BE";a:1:{i:0;s:8:"Bèlgica";}s:2:"BF";a:1:{i:0;s:12:"Burkina Faso";}s:2:"BG";a:1:{i:0;s:9:"Bulgà ria";}s:2:"BH";a:1:{i:0;s:7:"Bahrain";}s:2:"BI";a:1:{i:0;s:7:"Burundi";}s:2:"BJ";a:1:{i:0;s:5:"Benin";}s:2:"BM";a:1:{i:0;s:8:"Bermudes";}s:2:"BN";a:1:{i:0;s:6:"Brunei";}s:2:"BO";a:1:{i:0;s:8:"BolÃvia";}s:2:"BR";a:1:{i:0;s:6:"Brasil";}s:2:"BS";a:1:{i:0;s:7:"Bahames";}s:2:"BT";a:1:{i:0;s:6:"Bhutan";}s:2:"BW";a:1:{i:0;s:8:"Botswana";}s:2:"BY";a:1:{i:0;s:12:"Bielorússia";}s:2:"BZ";a:1:{i:0;s:6:"Belize";}s:2:"CA";a:1:{i:0;s:7:"Canadà ";}s:2:"CF";a:1:{i:0;s:24:"República Centrafricana";}s:2:"CG";a:1:{i:0;s:5:"Congo";}s:2:"CH";a:1:{i:0;s:11:"Switzerland";}s:2:"CI";a:1:{i:0;s:15:"Costa d’Ivori";}s:2:"CL";a:1:{i:0;s:4:"Xile";}s:2:"CM";a:1:{i:0;s:7:"Camerun";}s:2:"CN";a:1:{i:0;s:4:"Xina";}s:2:"CO";a:1:{i:0;s:9:"Colòmbia";}s:2:"CR";a:1:{i:0;s:10:"Costa Rica";}s:2:"CU";a:1:{i:0;s:4:"Cuba";}s:2:"CV";a:1:{i:0;s:8:"Cap Verd";}s:2:"CY";a:1:{i:0;s:5:"Xipre";}s:2:"CZ";a:1:{i:0;s:16:"República Txeca";}s:2:"DE";a:1:{i:0;s:8:"Alemanya";}s:2:"DJ";a:1:{i:0;s:8:"Djibouti";}s:2:"DK";a:1:{i:0;s:9:"Dinamarca";}s:2:"DM";a:1:{i:0;s:8:"Dominica";}s:2:"DO";a:1:{i:0;s:21:"República Dominicana";}s:2:"DZ";a:1:{i:0;s:8:"Algèria";}s:2:"EC";a:1:{i:0;s:7:"Equador";}s:2:"EE";a:1:{i:0;s:8:"Estònia";}s:2:"EG";a:1:{i:0;s:6:"Egipte";}s:2:"EH";a:1:{i:0;s:18:"Sà hara Occidental";}s:2:"ER";a:1:{i:0;s:7:"Eritrea";}s:2:"ES";a:1:{i:0;s:7:"Espanya";}s:2:"ET";a:1:{i:0;s:8:"Etiòpia";}s:2:"FI";a:1:{i:0;s:10:"Finlà ndia";}s:2:"FJ";a:1:{i:0;s:4:"Fiji";}s:2:"FM";a:1:{i:0;s:11:"Micronèsia";}s:2:"FR";a:1:{i:0;s:7:"França";}s:2:"GA";a:1:{i:0;s:5:"Gabon";}s:2:"GB";a:1:{i:0;s:10:"Regne Unit";}s:2:"GE";a:1:{i:0;s:8:"Geòrgia";}s:2:"GF";a:1:{i:0;s:16:"Guaiana Francesa";}s:2:"GH";a:1:{i:0;s:5:"Ghana";}s:2:"GM";a:1:{i:0;s:7:"Gà mbia";}s:2:"GN";a:1:{i:0;s:6:"Guinea";}s:2:"GP";a:1:{i:0;s:10:"Guadeloupe";}s:2:"GQ";a:1:{i:0;s:17:"Guinea Equatorial";}s:2:"GR";a:1:{i:0;s:7:"Grècia";}s:2:"GT";a:1:{i:0;s:9:"Guatemala";}s:2:"GW";a:1:{i:0;s:13:"Guinea Bissau";}s:2:"GY";a:1:{i:0;s:6:"Guyana";}s:2:"HN";a:1:{i:0;s:8:"Hondures";}s:2:"HR";a:1:{i:0;s:8:"Croà cia";}s:2:"HT";a:1:{i:0;s:6:"HaitÃ";}s:2:"HU";a:1:{i:0;s:7:"Hongria";}s:2:"ID";a:1:{i:0;s:10:"Indonèsia";}s:2:"IE";a:1:{i:0;s:7:"Irlanda";}s:2:"IL";a:1:{i:0;s:6:"Israel";}s:2:"IN";a:1:{i:0;s:6:"Ãndia";}s:2:"IQ";a:1:{i:0;s:4:"Iraq";}s:2:"IR";a:1:{i:0;s:4:"Iran";}s:2:"IS";a:1:{i:0;s:9:"Islà ndia";}s:2:"IT";a:1:{i:0;s:7:"Ità lia";}s:2:"JM";a:1:{i:0;s:7:"Jamaica";}s:2:"JO";a:1:{i:0;s:9:"Jordà nia";}s:2:"JP";a:1:{i:0;s:5:"Japó";}s:2:"KE";a:1:{i:0;s:5:"Kenya";}s:2:"KG";a:1:{i:0;s:11:"Kirgizistan";}s:2:"KH";a:1:{i:0;s:8:"Cambodja";}s:2:"KI";a:1:{i:0;s:8:"Kiribati";}s:2:"KM";a:1:{i:0;s:7:"Comores";}s:2:"KP";a:1:{i:0;s:14:"Corea del Nord";}s:2:"KR";a:1:{i:0;s:13:"Corea del Sud";}s:2:"KW";a:1:{i:0;s:6:"Kuwait";}s:2:"KZ";a:1:{i:0;s:10:"Kazakhstan";}s:2:"LA";a:1:{i:0;s:4:"Laos";}s:2:"LB";a:1:{i:0;s:6:"LÃban";}s:2:"LI";a:1:{i:0;s:13:"Liechtenstein";}s:2:"LK";a:1:{i:0;s:9:"Sri Lanka";}s:2:"LR";a:1:{i:0;s:8:"Libèria";}s:2:"LS";a:1:{i:0;s:7:"Lesotho";}s:2:"LT";a:1:{i:0;s:9:"Lituà nia";}s:2:"LU";a:1:{i:0;s:9:"Luxemburg";}s:2:"LV";a:1:{i:0;s:8:"Letònia";}s:2:"LY";a:1:{i:0;s:6:"LÃbia";}s:2:"MA";a:1:{i:0;s:6:"Marroc";}s:2:"MC";a:1:{i:0;s:7:"Mònaco";}s:2:"MD";a:1:{i:0;s:9:"Moldà via";}s:2:"MG";a:1:{i:0;s:10:"Madagascar";}s:2:"MK";a:1:{i:0;s:10:"Macedònia";}s:2:"ML";a:1:{i:0;s:4:"Mali";}s:2:"MM";a:1:{i:0;s:7:"Myanmar";}s:2:"MN";a:1:{i:0;s:9:"Mongòlia";}s:2:"MQ";a:1:{i:0;s:9:"Martinica";}s:2:"MR";a:1:{i:0;s:11:"Maurità nia";}s:2:"MS";a:1:{i:0;s:10:"Montserrat";}s:2:"MT";a:1:{i:0;s:5:"Malta";}s:2:"MU";a:1:{i:0;s:7:"Maurici";}s:2:"MX";a:1:{i:0;s:6:"Mèxic";}s:2:"MY";a:1:{i:0;s:9:"Malà isia";}s:2:"MZ";a:1:{i:0;s:9:"Moçambic";}s:2:"NA";a:1:{i:0;s:8:"NamÃbia";}s:2:"NC";a:1:{i:0;s:15:"Nova Caledònia";}s:2:"NE";a:1:{i:0;s:6:"NÃger";}s:2:"NG";a:1:{i:0;s:8:"Nigèria";}s:2:"NI";a:1:{i:0;s:9:"Nicaragua";}s:2:"NL";a:1:{i:0;s:14:"Països Baixos";}s:2:"NO";a:1:{i:0;s:7:"Noruega";}s:2:"NP";a:1:{i:0;s:5:"Nepal";}s:2:"NU";a:1:{i:0;s:4:"Niue";}s:2:"NZ";a:1:{i:0;s:12:"Nova Zelanda";}s:2:"OM";a:1:{i:0;s:4:"Oman";}s:2:"PA";a:1:{i:0;s:7:"Panamà ";}s:2:"PE";a:1:{i:0;s:5:"Perú";}s:2:"PF";a:1:{i:0;s:19:"Polinèsia Francesa";}s:2:"PG";a:1:{i:0;s:17:"Papua Nova Guinea";}s:2:"PH";a:1:{i:0;s:9:"Filipines";}s:2:"PK";a:1:{i:0;s:8:"Pakistan";}s:2:"PL";a:1:{i:0;s:8:"Polònia";}s:2:"PR";a:1:{i:0;s:11:"Puerto Rico";}s:2:"PT";a:1:{i:0;s:8:"Portugal";}s:2:"PY";a:1:{i:0;s:8:"Paraguai";}s:2:"QA";a:1:{i:0;s:5:"Qatar";}s:2:"RO";a:1:{i:0;s:7:"Romania";}s:2:"RU";a:1:{i:0;s:7:"Rússia";}s:2:"RW";a:1:{i:0;s:6:"Rwanda";}s:2:"SA";a:1:{i:0;s:14:"Arà bia SaudÃ";}s:2:"SC";a:1:{i:0;s:10:"Seychelles";}s:2:"SD";a:1:{i:0;s:5:"Sudan";}s:2:"SE";a:1:{i:0;s:7:"Suècia";}s:2:"SG";a:1:{i:0;s:8:"Singapur";}s:2:"SI";a:1:{i:0;s:10:"Eslovènia";}s:2:"SK";a:1:{i:0;s:11:"Eslovà quia";}s:2:"SL";a:1:{i:0;s:12:"Sierra Leone";}s:2:"SN";a:1:{i:0;s:7:"Senegal";}s:2:"SO";a:1:{i:0;s:8:"Somà lia";}s:2:"SP";a:1:{i:0;s:7:"Sèrbia";}s:2:"SR";a:1:{i:0;s:7:"Surinam";}s:2:"SV";a:1:{i:0;s:11:"El Salvador";}s:2:"SY";a:1:{i:0;s:6:"SÃria";}s:2:"SZ";a:1:{i:0;s:12:"Swazilà ndia";}s:2:"TD";a:1:{i:0;s:4:"Txad";}s:2:"TF";a:1:{i:0;s:32:"Territoris Meridionals Francesos";}s:2:"TG";a:1:{i:0;s:4:"Togo";}s:2:"TH";a:1:{i:0;s:10:"Tailà ndia";}s:2:"TJ";a:1:{i:0;s:11:"Tadjikistan";}s:2:"TK";a:1:{i:0;s:7:"Tokelau";}s:2:"TL";a:1:{i:0;s:5:"Timor";}s:2:"TM";a:1:{i:0;s:12:"Turkmenistan";}s:2:"TN";a:1:{i:0;s:8:"TunÃsia";}s:2:"TO";a:1:{i:0;s:5:"Tonga";}s:2:"TR";a:1:{i:0;s:7:"Turquia";}s:2:"TT";a:1:{i:0;s:17:"Trinitat i Tobago";}s:2:"TW";a:1:{i:0;s:6:"Taiwan";}s:2:"TZ";a:1:{i:0;s:9:"Tanzà nia";}s:2:"UA";a:1:{i:0;s:8:"Ucraïna";}s:2:"UG";a:1:{i:0;s:6:"Uganda";}s:2:"US";a:1:{i:0;s:12:"Estats Units";}s:2:"UY";a:1:{i:0;s:7:"Uruguai";}s:2:"UZ";a:1:{i:0;s:10:"Uzbekistan";}s:2:"VA";a:1:{i:0;s:7:"Vaticà ";}s:2:"VE";a:1:{i:0;s:10:"Veneçuela";}s:2:"VG";a:1:{i:0;s:25:"Illes Verges Brità niques";}s:2:"VI";a:1:{i:0;s:21:"Illes Verges dels USA";}s:2:"VN";a:1:{i:0;s:7:"Vietnam";}s:2:"VU";a:1:{i:0;s:7:"Vanuatu";}s:2:"YE";a:1:{i:0;s:5:"Iemen";}s:2:"YT";a:1:{i:0;s:7:"Mayotte";}s:2:"YU";a:1:{i:0;s:11:"Iugoslà via";}s:2:"ZA";a:1:{i:0;s:11:"Sud-à frica";}s:2:"ZM";a:1:{i:0;s:7:"Zà mbia";}s:2:"ZW";a:1:{i:0;s:8:"Zimbabwe";}}s:10:"Currencies";a:1:{s:3:"ESP";a:3:{i:0;s:3:"₧";i:1;s:3:"ESP";i:2;a:3:{i:0;s:18:"¤ #,##0;-¤ #,##0";i:1;s:1:",";i:2;s:1:".";}}}s:9:"Languages";a:139:{s:2:"aa";a:1:{i:0;s:5:"à far";}s:2:"ab";a:1:{i:0;s:6:"abkhaz";}s:2:"af";a:1:{i:0;s:9:"afrikaans";}s:2:"am";a:1:{i:0;s:8:"amhà ric";}s:2:"ar";a:1:{i:0;s:5:"ârab";}s:2:"as";a:1:{i:0;s:8:"assamès";}s:2:"ay";a:1:{i:0;s:6:"aimara";}s:2:"az";a:1:{i:0;s:6:"à zeri";}s:2:"ba";a:1:{i:0;s:7:"baixkir";}s:2:"be";a:1:{i:0;s:9:"bielorús";}s:2:"bg";a:1:{i:0;s:7:"búlgar";}s:2:"bh";a:1:{i:0;s:6:"bihari";}s:2:"bi";a:1:{i:0;s:7:"bislama";}s:2:"bn";a:1:{i:0;s:8:"bengalÃ";}s:2:"bo";a:1:{i:0;s:7:"tibetà ";}s:2:"br";a:1:{i:0;s:6:"bretó";}s:2:"ca";a:1:{i:0;s:7:"català ";}s:2:"co";a:1:{i:0;s:4:"cors";}s:2:"cs";a:1:{i:0;s:4:"txec";}s:2:"cy";a:1:{i:0;s:9:"gal·lès";}s:2:"da";a:1:{i:0;s:6:"danès";}s:2:"de";a:1:{i:0;s:7:"alemany";}s:2:"dz";a:1:{i:0;s:9:"bhutanès";}s:2:"el";a:1:{i:0;s:4:"grec";}s:2:"en";a:1:{i:0;s:7:"anglès";}s:2:"eo";a:1:{i:0;s:9:"esperanto";}s:2:"es";a:1:{i:0;s:8:"espanyol";}s:2:"et";a:1:{i:0;s:8:"estonià ";}s:2:"eu";a:1:{i:0;s:4:"basc";}s:2:"fa";a:1:{i:0;s:5:"persa";}s:2:"fi";a:1:{i:0;s:6:"finès";}s:2:"fj";a:1:{i:0;s:6:"fijià ";}s:2:"fo";a:1:{i:0;s:7:"feroès";}s:2:"fr";a:1:{i:0;s:8:"francès";}s:2:"fy";a:1:{i:0;s:6:"frisó";}s:2:"ga";a:1:{i:0;s:9:"irlandès";}s:2:"gd";a:1:{i:0;s:8:"escocès";}s:2:"gl";a:1:{i:0;s:6:"gallec";}s:2:"gn";a:1:{i:0;s:8:"guaranÃ";}s:2:"gu";a:1:{i:0;s:8:"gujarati";}s:2:"ha";a:1:{i:0;s:5:"hausa";}s:2:"he";a:1:{i:0;s:6:"hebreu";}s:2:"hi";a:1:{i:0;s:5:"hindi";}s:2:"hr";a:1:{i:0;s:5:"croat";}s:2:"hu";a:1:{i:0;s:9:"hongarès";}s:2:"hy";a:1:{i:0;s:6:"armeni";}s:2:"ia";a:1:{i:0;s:11:"interlingua";}s:2:"id";a:1:{i:0;s:8:"indonesi";}s:2:"ie";a:1:{i:0;s:11:"interlingue";}s:2:"ik";a:1:{i:0;s:7:"inupiak";}s:2:"is";a:1:{i:0;s:9:"islandès";}s:2:"it";a:1:{i:0;s:7:"italià ";}s:2:"iu";a:1:{i:0;s:9:"inuktitut";}s:2:"ja";a:1:{i:0;s:8:"japonès";}s:2:"jv";a:1:{i:0;s:8:"javanès";}s:2:"ka";a:1:{i:0;s:8:"georgià ";}s:2:"kk";a:1:{i:0;s:6:"kazakh";}s:2:"kl";a:1:{i:0;s:12:"greenlandès";}s:2:"km";a:1:{i:0;s:9:"cambodjà ";}s:2:"kn";a:1:{i:0;s:7:"kannada";}s:2:"ko";a:1:{i:0;s:6:"coreà ";}s:2:"ks";a:1:{i:0;s:8:"caixmiri";}s:2:"ku";a:1:{i:0;s:4:"kurd";}s:2:"ky";a:1:{i:0;s:8:"kirguÃs";}s:2:"la";a:1:{i:0;s:6:"llatÃ";}s:2:"ln";a:1:{i:0;s:7:"lingala";}s:2:"lo";a:1:{i:0;s:7:"laosià ";}s:2:"lt";a:1:{i:0;s:6:"lituà ";}s:2:"lv";a:1:{i:0;s:5:"letó";}s:2:"mg";a:1:{i:0;s:7:"malgaix";}s:2:"mi";a:1:{i:0;s:5:"maori";}s:2:"mk";a:1:{i:0;s:8:"macedoni";}s:2:"ml";a:1:{i:0;s:9:"malaialam";}s:2:"mn";a:1:{i:0;s:6:"mongol";}s:2:"mo";a:1:{i:0;s:6:"moldau";}s:2:"mr";a:1:{i:0;s:7:"marathi";}s:2:"ms";a:1:{i:0;s:5:"malai";}s:2:"mt";a:1:{i:0;s:7:"maltès";}s:2:"my";a:1:{i:0;s:6:"birmà ";}s:2:"na";a:1:{i:0;s:7:"nauruà ";}s:2:"ne";a:1:{i:0;s:8:"nepalès";}s:2:"nl";a:1:{i:0;s:11:"neerlandès";}s:2:"no";a:1:{i:0;s:6:"noruec";}s:2:"oc";a:1:{i:0;s:7:"occità ";}s:2:"om";a:1:{i:0;s:12:"oromo (afan)";}s:2:"or";a:1:{i:0;s:5:"oriya";}s:2:"pa";a:1:{i:0;s:7:"panjabi";}s:2:"pl";a:1:{i:0;s:8:"polonès";}s:2:"ps";a:1:{i:0;s:6:"paixto";}s:2:"pt";a:1:{i:0;s:10:"portuguès";}s:2:"qu";a:1:{i:0;s:8:"quètxua";}s:2:"rm";a:1:{i:0;s:12:"retoromà nic";}s:2:"rn";a:1:{i:0;s:7:"kirundi";}s:2:"ro";a:1:{i:0;s:8:"romanès";}s:2:"ru";a:1:{i:0;s:3:"rus";}s:2:"rw";a:1:{i:0;s:11:"kinyarwanda";}s:2:"sa";a:1:{i:0;s:9:"sà nscrit";}s:2:"sd";a:1:{i:0;s:6:"sindhi";}s:2:"sg";a:1:{i:0;s:5:"sango";}s:2:"sh";a:1:{i:0;s:11:"serbo-croat";}s:2:"si";a:1:{i:0;s:9:"sinhalès";}s:2:"sk";a:1:{i:0;s:7:"eslovac";}s:2:"sl";a:1:{i:0;s:7:"eslovè";}s:2:"sm";a:1:{i:0;s:6:"samoà ";}s:2:"sn";a:1:{i:0;s:5:"shona";}s:2:"so";a:1:{i:0;s:6:"somali";}s:2:"sq";a:1:{i:0;s:8:"albanès";}s:2:"sr";a:1:{i:0;s:5:"serbi";}s:2:"ss";a:1:{i:0;s:7:"siswati";}s:2:"st";a:1:{i:0;s:5:"sotho";}s:2:"su";a:1:{i:0;s:9:"sundanès";}s:2:"sv";a:1:{i:0;s:4:"suec";}s:2:"sw";a:1:{i:0;s:7:"swahili";}s:2:"ta";a:1:{i:0;s:6:"tà mil";}s:2:"te";a:1:{i:0;s:6:"telugu";}s:2:"tg";a:1:{i:0;s:6:"tadjik";}s:2:"th";a:1:{i:0;s:4:"thai";}s:2:"ti";a:1:{i:0;s:8:"tigrinya";}s:2:"tk";a:1:{i:0;s:7:"turcman";}s:2:"tl";a:1:{i:0;s:8:"tagà log";}s:2:"tn";a:1:{i:0;s:6:"tswana";}s:2:"to";a:1:{i:0;s:5:"tonga";}s:2:"tr";a:1:{i:0;s:4:"turc";}s:2:"ts";a:1:{i:0;s:6:"tsonga";}s:2:"tt";a:1:{i:0;s:6:"tà tar";}s:2:"tw";a:1:{i:0;s:3:"twi";}s:2:"ug";a:1:{i:0;s:5:"uigur";}s:2:"uk";a:1:{i:0;s:10:"ucraïnès";}s:2:"ur";a:1:{i:0;s:5:"urdú";}s:2:"uz";a:1:{i:0;s:5:"uzbek";}s:2:"vi";a:1:{i:0;s:10:"vietnamita";}s:2:"vo";a:1:{i:0;s:7:"volapuk";}s:2:"wo";a:1:{i:0;s:6:"wòlof";}s:2:"xh";a:1:{i:0;s:4:"xosa";}s:2:"yi";a:1:{i:0;s:7:"jiddish";}s:2:"yo";a:1:{i:0;s:6:"ioruba";}s:2:"za";a:1:{i:0;s:6:"zhuang";}s:2:"zh";a:1:{i:0;s:6:"xinés";}s:2:"zu";a:1:{i:0;s:4:"zulu";}}s:12:"LocaleScript";a:1:{i:0;s:4:"Latn";}s:14:"NumberElements";a:12:{i:0;s:1:",";i:1;s:1:".";i:2;s:1:";";i:3;s:1:"%";i:4;s:1:"0";i:5;s:1:"#";i:6;s:1:"-";i:7;s:1:"E";i:8;s:3:"‰";i:9;s:3:"∞";i:10;s:3:"�";i:11;s:1:"+";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:3:{s:26:"DateTimeElements:intvector";a:2:{i:0;i:2;i:1;i:1;}s:8:"dayNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:7:{i:0;s:3:"dg.";i:1;s:3:"dl.";i:2;s:3:"dt.";i:3;s:3:"dc.";i:4;s:3:"dj.";i:5;s:3:"dv.";i:6;s:3:"ds.";}s:4:"wide";a:7:{i:0;s:8:"diumenge";i:1;s:7:"dilluns";i:2;s:7:"dimarts";i:3;s:8:"dimecres";i:4;s:6:"dijous";i:5;s:9:"divendres";i:6;s:8:"dissabte";}}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:12:{i:0;s:4:"gen.";i:1;s:4:"feb.";i:2;s:5:"març";i:3;s:4:"abr.";i:4;s:4:"maig";i:5;s:4:"juny";i:6;s:4:"jul.";i:7;s:3:"ag.";i:8;s:4:"set.";i:9;s:4:"oct.";i:10;s:4:"nov.";i:11;s:4:"des.";}s:4:"wide";a:12:{i:0;s:5:"gener";i:1;s:6:"febrer";i:2;s:5:"març";i:3;s:5:"abril";i:4;s:4:"maig";i:5;s:4:"juny";i:6;s:6:"juliol";i:7;s:5:"agost";i:8;s:8:"setembre";i:9;s:7:"octubre";i:10;s:8:"novembre";i:11;s:8:"desembre";}}}}}s:17:"localPatternChars";a:1:{i:0;s:24:"GuMtkHmsSEDFwWahKzUeygAZ";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/ca_ES.dat b/framework/I18N/core/data/ca_ES.dat
new file mode 100644
index 00000000..6ecaa281
--- /dev/null
+++ b/framework/I18N/core/data/ca_ES.dat
@@ -0,0 +1 @@
+a:2:{s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;-#,##0.###";i:1;s:24:"#,##0.00 ¤;-#,##0.00 ¤";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/cs.dat b/framework/I18N/core/data/cs.dat
new file mode 100644
index 00000000..947762ce
--- /dev/null
+++ b/framework/I18N/core/data/cs.dat
@@ -0,0 +1 @@
+a:11:{s:9:"Countries";a:240:{s:2:"AD";a:1:{i:0;s:7:"Andorra";}s:2:"AE";a:1:{i:0;s:26:"Spojené arabské emiráty";}s:2:"AF";a:1:{i:0;s:13:"Afghánistán";}s:2:"AG";a:1:{i:0;s:17:"Antigua a Barbuda";}s:2:"AI";a:1:{i:0;s:7:"Anguila";}s:2:"AL";a:1:{i:0;s:8:"Albánie";}s:2:"AM";a:1:{i:0;s:8:"Arménie";}s:2:"AN";a:1:{i:0;s:18:"Nizozemské Antily";}s:2:"AO";a:1:{i:0;s:6:"Angola";}s:2:"AQ";a:1:{i:0;s:10:"Antarktida";}s:2:"AR";a:1:{i:0;s:9:"Argentina";}s:2:"AS";a:1:{i:0;s:15:"Americká Samoa";}s:2:"AT";a:1:{i:0;s:8:"Rakousko";}s:2:"AU";a:1:{i:0;s:10:"Austrálie";}s:2:"AW";a:1:{i:0;s:5:"Aruba";}s:2:"AZ";a:1:{i:0;s:15:"Ãzerbájdžán";}s:2:"BA";a:1:{i:0;s:19:"Bosna a Hercegovina";}s:2:"BB";a:1:{i:0;s:8:"Barbados";}s:2:"BD";a:1:{i:0;s:11:"Bangladéš";}s:2:"BE";a:1:{i:0;s:6:"Belgie";}s:2:"BF";a:1:{i:0;s:12:"Burkina Faso";}s:2:"BG";a:1:{i:0;s:9:"Bulharsko";}s:2:"BH";a:1:{i:0;s:7:"Bahrajn";}s:2:"BI";a:1:{i:0;s:7:"Burundi";}s:2:"BJ";a:1:{i:0;s:5:"Benin";}s:2:"BM";a:1:{i:0;s:7:"Bermudy";}s:2:"BN";a:1:{i:0;s:17:"Brunej Darussalam";}s:2:"BO";a:1:{i:0;s:8:"BolÃvie";}s:2:"BR";a:1:{i:0;s:9:"BrazÃlie";}s:2:"BS";a:1:{i:0;s:6:"Bahamy";}s:2:"BT";a:1:{i:0;s:8:"Bhútán";}s:2:"BV";a:1:{i:0;s:13:"Ostrov Bouvet";}s:2:"BW";a:1:{i:0;s:8:"Botswana";}s:2:"BY";a:1:{i:0;s:10:"BÄ›lorusko";}s:2:"BZ";a:1:{i:0;s:6:"Belize";}s:2:"CA";a:1:{i:0;s:6:"Kanada";}s:2:"CC";a:1:{i:0;s:17:"Kokosové ostrovy";}s:2:"CD";a:1:{i:0;s:30:"Kongo, demokratická republika";}s:2:"CF";a:1:{i:0;s:25:"StÅ™edoafrická republika";}s:2:"CG";a:1:{i:0;s:5:"Kongo";}s:2:"CH";a:1:{i:0;s:11:"Å výcarsko";}s:2:"CI";a:1:{i:0;s:20:"PobÅ™ežà slonoviny";}s:2:"CK";a:1:{i:0;s:15:"Cookovy ostrovy";}s:2:"CL";a:1:{i:0;s:5:"Chile";}s:2:"CM";a:1:{i:0;s:7:"Kamerun";}s:2:"CN";a:1:{i:0;s:6:"ÄŒÃna";}s:2:"CO";a:1:{i:0;s:8:"Kolumbie";}s:2:"CR";a:1:{i:0;s:9:"Kostarika";}s:2:"CU";a:1:{i:0;s:4:"Kuba";}s:2:"CV";a:1:{i:0;s:8:"Kapverdy";}s:2:"CX";a:1:{i:0;s:18:"VánoÄnà ostrovy";}s:2:"CY";a:1:{i:0;s:4:"Kypr";}s:2:"CZ";a:1:{i:0;s:17:"ÄŒeská republika";}s:2:"DE";a:1:{i:0;s:8:"NÄ›mecko";}s:2:"DJ";a:1:{i:0;s:8:"Džibuti";}s:2:"DK";a:1:{i:0;s:7:"Dánsko";}s:2:"DM";a:1:{i:0;s:8:"Dominika";}s:2:"DO";a:1:{i:0;s:24:"Dominikánská republika";}s:2:"DZ";a:1:{i:0;s:10:"AlžÃrsko";}s:2:"EC";a:1:{i:0;s:8:"Ekvádor";}s:2:"EE";a:1:{i:0;s:8:"Estonsko";}s:2:"EG";a:1:{i:0;s:5:"Egypt";}s:2:"EH";a:1:{i:0;s:16:"Západnà Sahara";}s:2:"ER";a:1:{i:0;s:7:"Eritrea";}s:2:"ES";a:1:{i:0;s:11:"Å panÄ›lsko";}s:2:"ET";a:1:{i:0;s:7:"Etiopie";}s:2:"FI";a:1:{i:0;s:6:"Finsko";}s:2:"FJ";a:1:{i:0;s:6:"Fidži";}s:2:"FK";a:1:{i:0;s:20:"Falklandské ostrovy";}s:2:"FM";a:1:{i:0;s:31:"Mikronésie, federativnà stát";}s:2:"FO";a:1:{i:0;s:16:"Faerské ostrovy";}s:2:"FR";a:1:{i:0;s:7:"Francie";}s:2:"GA";a:1:{i:0;s:5:"Gabon";}s:2:"GB";a:1:{i:0;s:16:"Velká Británie";}s:2:"GD";a:1:{i:0;s:7:"Grenada";}s:2:"GE";a:1:{i:0;s:6:"Gruzie";}s:2:"GF";a:1:{i:0;s:19:"Francouzská Guyana";}s:2:"GH";a:1:{i:0;s:5:"Ghana";}s:2:"GI";a:1:{i:0;s:9:"Gibraltar";}s:2:"GL";a:1:{i:0;s:8:"Grónsko";}s:2:"GM";a:1:{i:0;s:6:"Gambie";}s:2:"GN";a:1:{i:0;s:6:"Guinea";}s:2:"GP";a:1:{i:0;s:10:"Guadeloupe";}s:2:"GQ";a:1:{i:0;s:18:"RovnÃková Guinea";}s:2:"GR";a:1:{i:0;s:6:"Řecko";}s:2:"GS";a:1:{i:0;s:45:"Jižnà Georgie a Jižnà Sandwichovy ostrovy";}s:2:"GT";a:1:{i:0;s:9:"Guatemala";}s:2:"GU";a:1:{i:0;s:4:"Guam";}s:2:"GW";a:1:{i:0;s:13:"Guinea-Bissau";}s:2:"GY";a:1:{i:0;s:6:"Guyana";}s:2:"HK";a:1:{i:0;s:52:"Hongkong, zvláštnà administrativnà oblast ÄŒÃny";}s:2:"HM";a:1:{i:0;s:24:"Ostrovy Heard a McDonald";}s:2:"HN";a:1:{i:0;s:8:"Honduras";}s:2:"HR";a:1:{i:0;s:10:"Chorvatsko";}s:2:"HT";a:1:{i:0;s:5:"Haiti";}s:2:"HU";a:1:{i:0;s:9:"MaÄarsko";}s:2:"ID";a:1:{i:0;s:10:"Indonésie";}s:2:"IE";a:1:{i:0;s:5:"Irsko";}s:2:"IL";a:1:{i:0;s:6:"Izrael";}s:2:"IN";a:1:{i:0;s:5:"Indie";}s:2:"IO";a:1:{i:0;s:36:"Britské územà v Indickém oceánu";}s:2:"IQ";a:1:{i:0;s:5:"Irák";}s:2:"IR";a:1:{i:0;s:6:"Ãrán";}s:2:"IS";a:1:{i:0;s:6:"Island";}s:2:"IT";a:1:{i:0;s:7:"Itálie";}s:2:"JM";a:1:{i:0;s:7:"Jamajka";}s:2:"JO";a:1:{i:0;s:10:"Jordánsko";}s:2:"JP";a:1:{i:0;s:8:"Japonsko";}s:2:"KE";a:1:{i:0;s:5:"Keňa";}s:2:"KG";a:1:{i:0;s:11:"Kyrgyzstán";}s:2:"KH";a:1:{i:0;s:9:"Kambodža";}s:2:"KI";a:1:{i:0;s:8:"Kiribati";}s:2:"KM";a:1:{i:0;s:6:"Komory";}s:2:"KN";a:1:{i:0;s:20:"Svatý Kitts a Nevis";}s:2:"KP";a:1:{i:0;s:14:"Severnà Korea";}s:2:"KR";a:1:{i:0;s:13:"Jižnà Korea";}s:2:"KW";a:1:{i:0;s:6:"Kuvajt";}s:2:"KY";a:1:{i:0;s:18:"Kajmanské ostrovy";}s:2:"KZ";a:1:{i:0;s:11:"Kazachstán";}s:2:"LA";a:1:{i:0;s:36:"LidovÄ› demokratická republika Laos";}s:2:"LB";a:1:{i:0;s:7:"Libanon";}s:2:"LC";a:1:{i:0;s:12:"Svatá Lucie";}s:2:"LI";a:1:{i:0;s:16:"LichtenÅ¡tejnsko";}s:2:"LK";a:1:{i:0;s:10:"Srà Lanka";}s:2:"LR";a:1:{i:0;s:8:"Libérie";}s:2:"LS";a:1:{i:0;s:7:"Lesotho";}s:2:"LT";a:1:{i:0;s:5:"Litva";}s:2:"LU";a:1:{i:0;s:11:"Lucembursko";}s:2:"LV";a:1:{i:0;s:9:"LotyÅ¡sko";}s:2:"LY";a:1:{i:0;s:5:"Libye";}s:2:"MA";a:1:{i:0;s:6:"Maroko";}s:2:"MC";a:1:{i:0;s:6:"Monako";}s:2:"MD";a:1:{i:0;s:20:"Moldavsko, republika";}s:2:"MG";a:1:{i:0;s:10:"Madagaskar";}s:2:"MH";a:1:{i:0;s:19:"Marshallovy ostrovy";}s:2:"MK";a:1:{i:0;s:9:"Macedonia";}s:2:"ML";a:1:{i:0;s:4:"Mali";}s:2:"MM";a:1:{i:0;s:15:"Myanmar (Burma)";}s:2:"MN";a:1:{i:0;s:9:"Mongolsko";}s:2:"MO";a:1:{i:0;s:19:"Macao S.A.R., China";}s:2:"MP";a:1:{i:0;s:16:"Severnà Mariany";}s:2:"MQ";a:1:{i:0;s:8:"Martinik";}s:2:"MR";a:1:{i:0;s:11:"Mauritánie";}s:2:"MS";a:1:{i:0;s:10:"Montserrat";}s:2:"MT";a:1:{i:0;s:5:"Malta";}s:2:"MU";a:1:{i:0;s:9:"Mauricius";}s:2:"MV";a:1:{i:0;s:8:"Maladivy";}s:2:"MW";a:1:{i:0;s:6:"Malawi";}s:2:"MX";a:1:{i:0;s:6:"Mexiko";}s:2:"MY";a:1:{i:0;s:8:"Malajsie";}s:2:"MZ";a:1:{i:0;s:8:"Mosambik";}s:2:"NA";a:1:{i:0;s:7:"Namibie";}s:2:"NC";a:1:{i:0;s:15:"Nová Kaledonie";}s:2:"NE";a:1:{i:0;s:5:"Niger";}s:2:"NF";a:1:{i:0;s:7:"Norfolk";}s:2:"NG";a:1:{i:0;s:8:"Nigérie";}s:2:"NI";a:1:{i:0;s:9:"Nikaragua";}s:2:"NL";a:1:{i:0;s:10:"Nizozemsko";}s:2:"NO";a:1:{i:0;s:6:"Norsko";}s:2:"NP";a:1:{i:0;s:6:"Nepál";}s:2:"NR";a:1:{i:0;s:5:"Nauru";}s:2:"NU";a:1:{i:0;s:4:"Niue";}s:2:"NZ";a:1:{i:0;s:13:"Nový Zéland";}s:2:"OM";a:1:{i:0;s:5:"Omán";}s:2:"PA";a:1:{i:0;s:6:"Panama";}s:2:"PE";a:1:{i:0;s:4:"Peru";}s:2:"PF";a:1:{i:0;s:23:"Francouzská Polynésie";}s:2:"PG";a:1:{i:0;s:18:"Papua-Nová Guinea";}s:2:"PH";a:1:{i:0;s:9:"FilipÃny";}s:2:"PK";a:1:{i:0;s:10:"Pákistán";}s:2:"PL";a:1:{i:0;s:6:"Polsko";}s:2:"PM";a:1:{i:0;s:24:"Svatý Pierre a Miquelon";}s:2:"PN";a:1:{i:0;s:8:"Pitcairn";}s:2:"PR";a:1:{i:0;s:9:"Portoriko";}s:2:"PS";a:1:{i:0;s:21:"Palestinian Territory";}s:2:"PT";a:1:{i:0;s:11:"Portugalsko";}s:2:"PW";a:1:{i:0;s:5:"Palau";}s:2:"PY";a:1:{i:0;s:8:"Paraguay";}s:2:"QA";a:1:{i:0;s:5:"Katar";}s:2:"RE";a:1:{i:0;s:8:"Réunion";}s:2:"RO";a:1:{i:0;s:8:"Rumunsko";}s:2:"RU";a:1:{i:0;s:5:"Rusko";}s:2:"RW";a:1:{i:0;s:6:"Rwanda";}s:2:"SA";a:1:{i:0;s:17:"Saúdská Arábie";}s:2:"SB";a:1:{i:0;s:20:"Å alamounovy ostrovy";}s:2:"SC";a:1:{i:0;s:8:"Seychely";}s:2:"SD";a:1:{i:0;s:7:"Súdán";}s:2:"SE";a:1:{i:0;s:9:"Å védsko";}s:2:"SG";a:1:{i:0;s:8:"Singapur";}s:2:"SH";a:1:{i:0;s:13:"Svatá Helena";}s:2:"SI";a:1:{i:0;s:9:"Slovinsko";}s:2:"SJ";a:1:{i:0;s:20:"Svalbard a Jan Mayen";}s:2:"SK";a:1:{i:0;s:9:"Slovensko";}s:2:"SL";a:1:{i:0;s:12:"Sierra Leone";}s:2:"SM";a:1:{i:0;s:10:"San Marino";}s:2:"SN";a:1:{i:0;s:7:"Senegal";}s:2:"SO";a:1:{i:0;s:9:"Somálsko";}s:2:"SP";a:1:{i:0;s:6:"Serbia";}s:2:"SR";a:1:{i:0;s:7:"Surinam";}s:2:"ST";a:1:{i:0;s:14:"Svatý Tomáš";}s:2:"SV";a:1:{i:0;s:11:"El Salvador";}s:2:"SY";a:1:{i:0;s:6:"Sýrie";}s:2:"SZ";a:1:{i:0;s:9:"Svazijsko";}s:2:"TC";a:1:{i:0;s:22:"Ostrovy Caicos a Turks";}s:2:"TD";a:1:{i:0;s:4:"ÄŒad";}s:2:"TF";a:1:{i:0;s:30:"Francouzská jižnà teritoria";}s:2:"TG";a:1:{i:0;s:4:"Togo";}s:2:"TH";a:1:{i:0;s:7:"Thajsko";}s:2:"TJ";a:1:{i:0;s:14:"Tádžikistán";}s:2:"TK";a:1:{i:0;s:7:"Tokelau";}s:2:"TL";a:1:{i:0;s:16:"Východnà Timor";}s:2:"TM";a:1:{i:0;s:13:"Turkmenistán";}s:2:"TN";a:1:{i:0;s:7:"Tunisko";}s:2:"TO";a:1:{i:0;s:5:"Tonga";}s:2:"TR";a:1:{i:0;s:7:"Turecko";}s:2:"TT";a:1:{i:0;s:17:"Trinidad a Tobago";}s:2:"TV";a:1:{i:0;s:6:"Tuvalu";}s:2:"TW";a:1:{i:0;s:9:"Tchaj-wan";}s:2:"TZ";a:1:{i:0;s:8:"Tanzanie";}s:2:"UA";a:1:{i:0;s:8:"Ukrajina";}s:2:"UG";a:1:{i:0;s:6:"Uganda";}s:2:"UM";a:1:{i:0;s:28:"MenÅ¡Ã odlehlé ostrovy USA";}s:2:"US";a:1:{i:0;s:15:"Spojené státy";}s:2:"UY";a:1:{i:0;s:7:"Uruguay";}s:2:"UZ";a:1:{i:0;s:11:"Uzbekistán";}s:2:"VA";a:1:{i:0;s:13:"Svatý stolec";}s:2:"VC";a:1:{i:0;s:26:"Svatý Vincent a Grenadiny";}s:2:"VE";a:1:{i:0;s:9:"Venezuela";}s:2:"VG";a:1:{i:0;s:26:"Britské Panenské ostrovy";}s:2:"VI";a:1:{i:0;s:27:"Americké Panenské ostrovy";}s:2:"VN";a:1:{i:0;s:7:"Vietnam";}s:2:"VU";a:1:{i:0;s:7:"Vanuatu";}s:2:"WF";a:1:{i:0;s:15:"Wallis a Futuna";}s:2:"WS";a:1:{i:0;s:5:"Samoa";}s:2:"YE";a:1:{i:0;s:5:"Jemen";}s:2:"YT";a:1:{i:0;s:7:"Mayotte";}s:2:"YU";a:1:{i:0;s:11:"Jugoslávie";}s:2:"ZA";a:1:{i:0;s:14:"Jižnà Afrika";}s:2:"ZM";a:1:{i:0;s:6:"Zambie";}s:2:"ZW";a:1:{i:0;s:8:"Zimbabwe";}}s:10:"Currencies";a:360:{s:3:"ADD";a:2:{i:0;s:3:"ADD";i:1;s:16:"Diner andorrský";}s:3:"ADP";a:2:{i:0;s:3:"ADP";i:1;s:17:"Peseta andorrská";}s:3:"AED";a:2:{i:0;s:3:"AED";i:1;s:10:"Dirham SAE";}s:3:"AFA";a:2:{i:0;s:3:"AFA";i:1;s:19:"Afghán (1927-2002)";}s:3:"AFN";a:2:{i:0;s:2:"Af";i:1;s:7:"Afghán";}s:3:"AIF";a:2:{i:0;s:3:"AIF";i:1;s:22:"Affars and Issas Franc";}s:3:"ALK";a:2:{i:0;s:3:"ALK";i:1;s:15:"Lek (1946-1961)";}s:3:"ALL";a:2:{i:0;s:3:"lek";i:1;s:3:"Lek";}s:3:"ALV";a:2:{i:0;s:3:"ALV";i:1;s:19:"Albanian Lek Valute";}s:3:"AMD";a:2:{i:0;s:4:"dram";i:1;s:15:"Dram arménský";}s:3:"ANG";a:2:{i:0;s:5:"NA f.";i:1;s:26:"Zlatý Nizozemských Antil";}s:3:"AOA";a:2:{i:0;s:3:"AOA";i:1;s:6:"Kwanza";}s:3:"AOK";a:2:{i:0;s:3:"AOK";i:1;s:18:"Kwanza (1977-1990)";}s:3:"AON";a:2:{i:0;s:3:"AON";i:1;s:24:"Kwanza nová (1990-2000)";}s:3:"AOR";a:2:{i:0;s:3:"AOR";i:1;s:29:"Kwanza reajustado (1995-1999)";}s:3:"AOS";a:2:{i:0;s:3:"AOS";i:1;s:16:"Escudo angolské";}s:3:"ARA";a:2:{i:0;s:3:"ARA";i:1;s:7:"Austral";}s:3:"ARM";a:2:{i:0;s:3:"ARM";i:1;s:33:"Peso argentinské Moneda Nacional";}s:3:"ARP";a:2:{i:0;s:3:"ARP";i:1;s:29:"Peso argentinské (1983-1985)";}s:3:"ARS";a:2:{i:0;s:4:"Arg$";i:1;s:17:"Peso argentinské";}s:3:"ATS";a:2:{i:0;s:3:"ATS";i:1;s:7:"Å ilink";}s:3:"AUD";a:2:{i:0;s:2:"$A";i:1;s:17:"Dolar australský";}s:3:"AUP";a:2:{i:0;s:3:"AUP";i:1;s:17:"Libra australská";}s:3:"AWG";a:2:{i:0;s:3:"AWG";i:1;s:15:"Zlatý arubský";}s:3:"AZM";a:2:{i:0;s:3:"AZM";i:1;s:24:"Manat ázerbajdžánský";}s:3:"BAD";a:2:{i:0;s:3:"BAD";i:1;s:26:"Dinár Bosny a Hercegoviny";}s:3:"BAM";a:2:{i:0;s:2:"KM";i:1;s:20:"Marka konvertibilnÃ";}s:3:"BAN";a:2:{i:0;s:3:"BAN";i:1;s:32:"Nový Dinár Bosny a Hercegoviny";}s:3:"BBD";a:2:{i:0;s:4:"BDS$";i:1;s:17:"Dolar barbadoský";}s:3:"BDT";a:2:{i:0;s:2:"Tk";i:1;s:4:"Taka";}s:3:"BEC";a:2:{i:0;s:3:"BEC";i:1;s:20:"Frank konvertibilnÃ";}s:3:"BEF";a:2:{i:0;s:2:"BF";i:1;s:15:"Frank belgický";}s:3:"BEL";a:2:{i:0;s:3:"BEL";i:1;s:16:"Frank finanÄnÃ";}s:3:"BGL";a:2:{i:0;s:3:"lev";i:1;s:3:"Lev";}s:3:"BGM";a:2:{i:0;s:3:"BGM";i:1;s:29:"Lev Bulharský socialistický";}s:3:"BGN";a:2:{i:0;s:3:"BGN";i:1;s:14:"Lev Bulharský";}s:3:"BGO";a:2:{i:0;s:3:"BGO";i:1;s:26:"Lev Bulharský (1879-1952)";}s:3:"BHD";a:2:{i:0;s:2:"BD";i:1;s:18:"Dinár bahrajnský";}s:3:"BIF";a:2:{i:0;s:3:"Fbu";i:1;s:16:"Frank burundský";}s:3:"BMD";a:2:{i:0;s:4:"Ber$";i:1;s:16:"Dolar bermudský";}s:3:"BMP";a:2:{i:0;s:3:"BMP";i:1;s:16:"Libra bermudská";}s:3:"BND";a:2:{i:0;s:3:"BND";i:1;s:16:"Dolar brunejský";}s:3:"BOB";a:2:{i:0;s:2:"Bs";i:1;s:9:"Boliviano";}s:3:"BOL";a:2:{i:0;s:3:"BOL";i:1;s:21:"Boliviano (1863-1962)";}s:3:"BOP";a:2:{i:0;s:3:"BOP";i:1;s:4:"Peso";}s:3:"BOV";a:2:{i:0;s:3:"BOV";i:1;s:5:"Mvdol";}s:3:"BRB";a:2:{i:0;s:3:"BRB";i:1;s:20:"Cruzeiro (1967-1986)";}s:3:"BRC";a:2:{i:0;s:3:"BRC";i:1;s:7:"Cruzado";}s:3:"BRE";a:2:{i:0;s:3:"BRE";i:1;s:20:"Cruzeiro (1990-1993)";}s:3:"BRL";a:2:{i:0;s:2:"R$";i:1;s:15:"Real brazilský";}s:3:"BRN";a:2:{i:0;s:3:"BRN";i:1;s:13:"Cruzado nové";}s:3:"BRR";a:2:{i:0;s:3:"BRR";i:1;s:13:"Cruzeiro real";}s:3:"BRZ";a:2:{i:0;s:3:"BRZ";i:1;s:20:"Cruzeiro (1942-1967)";}s:3:"BSD";a:2:{i:0;s:3:"BSD";i:1;s:15:"Dolar bahamský";}s:3:"BSP";a:2:{i:0;s:3:"BSP";i:1;s:15:"Libra bahamská";}s:3:"BTN";a:2:{i:0;s:2:"Nu";i:1;s:8:"Ngultrum";}s:3:"BTR";a:2:{i:0;s:3:"BTR";i:1;s:18:"Rupie bhútánská";}s:3:"BUK";a:2:{i:0;s:3:"BUK";i:1;s:13:"Kyat barmský";}s:3:"BUR";a:2:{i:0;s:3:"BUR";i:1;s:14:"Rupie barmská";}s:3:"BWP";a:2:{i:0;s:3:"BWP";i:1;s:4:"Pula";}s:3:"BYB";a:2:{i:0;s:3:"BYB";i:1;s:34:"Rubl nový bÄ›loruský (1994-1999)";}s:3:"BYL";a:2:{i:0;s:3:"BYL";i:1;s:28:"Rubl bÄ›loruský (1992-1994)";}s:3:"BYR";a:2:{i:0;s:3:"Rbl";i:1;s:16:"Rubl bÄ›loruský";}s:3:"BZD";a:2:{i:0;s:3:"BZ$";i:1;s:15:"Dolar belizský";}s:3:"BZH";a:2:{i:0;s:3:"BZH";i:1;s:26:"Dolar Britského Hondurasu";}s:3:"CAD";a:2:{i:0;s:4:"Can$";i:1;s:15:"Dolar kanadský";}s:3:"CDF";a:2:{i:0;s:3:"CDF";i:1;s:15:"Frank konžský";}s:3:"CDG";a:2:{i:0;s:3:"CDG";i:1;s:25:"Frank Konžské republiky";}s:3:"CDL";a:2:{i:0;s:3:"CDL";i:1;s:15:"Zaire konžský";}s:3:"CFF";a:2:{i:0;s:3:"CFF";i:1;s:35:"Frank StÅ™edoafrické republiky CFA";}s:3:"CHF";a:2:{i:0;s:3:"SwF";i:1;s:18:"Frank Å¡výcarský";}s:3:"CKD";a:2:{i:0;s:3:"CKD";i:1;s:25:"Dolar Cookových ostrovů";}s:3:"CLC";a:2:{i:0;s:3:"CLC";i:1;s:15:"Condor chilský";}s:3:"CLE";a:2:{i:0;s:3:"CLE";i:1;s:15:"Escudo chilské";}s:3:"CLF";a:2:{i:0;s:3:"CLF";i:1;s:19:"Unidades de fomento";}s:3:"CLP";a:2:{i:0;s:3:"Ch$";i:1;s:13:"Peso chilské";}s:3:"CMF";a:2:{i:0;s:3:"CMF";i:1;s:21:"Frank kamerunský CFA";}s:3:"CNP";a:2:{i:0;s:3:"CNP";i:1;s:17:"Juan jen min piao";}s:3:"CNX";a:2:{i:0;s:3:"CNX";i:1;s:19:"Dolar lidové banky";}s:3:"CNY";a:2:{i:0;s:1:"Y";i:1;s:13:"Juan renminbi";}s:3:"COB";a:2:{i:0;s:3:"COB";i:1;s:17:"Peso kolumbijské";}s:3:"COF";a:2:{i:0;s:3:"COF";i:1;s:19:"Krank konžský CFA";}s:3:"COP";a:2:{i:0;s:4:"Col$";i:1;s:17:"Peso kolumbijské";}s:3:"CRC";a:2:{i:0;s:1:"C";i:1;s:18:"Colón kostarický";}s:3:"CSC";a:2:{i:0;s:3:"CSC";i:1;s:23:"Koruna Äeskoslovenská";}s:3:"CSK";a:2:{i:0;s:3:"CSK";i:1;s:23:"Koruna Äeskoslovenská";}s:3:"CUP";a:2:{i:0;s:3:"CUP";i:1;s:15:"Peso kubánské";}s:3:"CVE";a:2:{i:0;s:5:"CVEsc";i:1;s:18:"Escudo kapverdské";}s:3:"CWG";a:2:{i:0;s:3:"CWG";i:1;s:14:"Zlatý Curacao";}s:3:"CYP";a:2:{i:0;s:2:"£";i:1;s:15:"Libra kyperská";}s:3:"CZK";a:2:{i:0;s:3:"KÄ";i:1;s:14:"Koruna Äeská";}s:3:"DDM";a:2:{i:0;s:3:"DDM";i:1;s:9:"Marka NDR";}s:3:"DEM";a:2:{i:0;s:3:"DEM";i:1;s:15:"Marka nÄ›mecká";}s:3:"DES";a:2:{i:0;s:3:"DES";i:1;s:19:"Sperrmark nÄ›mecká";}s:3:"DJF";a:2:{i:0;s:2:"DF";i:1;s:17:"Frank džibutský";}s:3:"DKK";a:2:{i:0;s:3:"DKr";i:1;s:15:"Koruna dánská";}s:3:"DOP";a:2:{i:0;s:3:"RD$";i:1;s:19:"Peso dominikánské";}s:3:"DZD";a:2:{i:0;s:2:"DA";i:1;s:18:"Dinár alžÃrský";}s:3:"DZF";a:2:{i:0;s:3:"DZF";i:1;s:23:"Frank nový alžÃrský";}s:3:"DZG";a:2:{i:0;s:3:"DZG";i:1;s:26:"Frank alžÃrský germinal";}s:3:"ECS";a:2:{i:0;s:3:"ECS";i:1;s:18:"Sucre ekvádorský";}s:3:"ECV";a:2:{i:0;s:3:"ECV";i:1;s:39:"Ecuador Unidad de Valor Constante (UVC)";}s:3:"EEK";a:2:{i:0;s:3:"EEK";i:1;s:5:"Kroon";}s:3:"EGP";a:2:{i:0;s:3:"EGP";i:1;s:15:"Libra egyptská";}s:3:"ERN";a:2:{i:0;s:3:"ERN";i:1;s:5:"Nakfa";}s:3:"ESP";a:2:{i:0;s:3:"ESP";i:1;s:19:"Peseta Å¡panÄ›lská";}s:3:"ETB";a:2:{i:0;s:2:"Br";i:1;s:14:"Birr etiopský";}s:3:"ETD";a:2:{i:0;s:3:"ETD";i:1;s:15:"Dolar etiopský";}s:3:"EUR";a:2:{i:0;s:3:"€";i:1;s:4:"Euro";}s:3:"FIM";a:2:{i:0;s:3:"FIM";i:1;s:6:"Markka";}s:3:"FIN";a:2:{i:0;s:3:"FIN";i:1;s:18:"Markka (1860-1962)";}s:3:"FJD";a:2:{i:0;s:2:"F$";i:1;s:17:"Dolar fidžijský";}s:3:"FJP";a:2:{i:0;s:3:"FJP";i:1;s:17:"Libra fidžijská";}s:3:"FKP";a:2:{i:0;s:3:"FKP";i:1;s:18:"Libra falklandská";}s:3:"FOK";a:2:{i:0;s:3:"FOK";i:1;s:26:"Koruna Faerských ostrovů";}s:3:"FRF";a:2:{i:0;s:3:"FRF";i:1;s:18:"Frank francouzský";}s:3:"FRG";a:2:{i:0;s:3:"FRG";i:1;s:42:"Frank francouzský germinal/Frank poincare";}s:3:"GAF";a:2:{i:0;s:3:"GAF";i:1;s:19:"Frank gabonský CFA";}s:3:"GBP";a:2:{i:0;s:2:"£";i:1;s:17:"Libra Å¡terlinků";}s:3:"GEK";a:2:{i:0;s:3:"GEK";i:1;s:20:"Georgian Kupon Larit";}s:3:"GEL";a:2:{i:0;s:4:"lari";i:1;s:4:"Lari";}s:3:"GHC";a:2:{i:0;s:3:"GHC";i:1;s:4:"Cedi";}s:3:"GHO";a:2:{i:0;s:3:"GHO";i:1;s:14:"Ghana Old Cedi";}s:3:"GHP";a:2:{i:0;s:3:"GHP";i:1;s:14:"Libra ghanská";}s:3:"GHR";a:2:{i:0;s:3:"GHR";i:1;s:19:"Ghana Revalued Cedi";}s:3:"GIP";a:2:{i:0;s:3:"GIP";i:1;s:19:"Libra gibraltarská";}s:3:"GLK";a:2:{i:0;s:3:"GLK";i:1;s:15:"Greenland Krone";}s:3:"GMD";a:2:{i:0;s:3:"GMD";i:1;s:6:"Dalasi";}s:3:"GMP";a:2:{i:0;s:3:"GMP";i:1;s:16:"Libra gambijská";}s:3:"GNF";a:2:{i:0;s:2:"GF";i:1;s:16:"Frank guinejský";}s:3:"GNI";a:2:{i:0;s:3:"GNI";i:1;s:28:"Frank guinejský (1960-1972)";}s:3:"GNS";a:2:{i:0;s:3:"GNS";i:1;s:11:"Guinea Syli";}s:3:"GPF";a:2:{i:0;s:3:"GPF";i:1;s:19:"Frank guadeloupský";}s:3:"GQE";a:2:{i:0;s:3:"GQE";i:1;s:33:"Equatorial Guinea Ekwele Guineana";}s:3:"GQF";a:2:{i:0;s:3:"GQF";i:1;s:24:"Equatorial Guinea Franco";}s:3:"GQP";a:2:{i:0;s:3:"GQP";i:1;s:33:"Equatorial Guinea Peseta Guineana";}s:3:"GRD";a:2:{i:0;s:3:"GRD";i:1;s:7:"Drachma";}s:3:"GRN";a:2:{i:0;s:3:"GRN";i:1;s:21:"Drachma nová Å™ecká";}s:3:"GTQ";a:2:{i:0;s:1:"Q";i:1;s:7:"Quetzal";}s:3:"GUF";a:2:{i:0;s:3:"GUF";i:1;s:26:"French Guyana Franc Guiana";}s:3:"GWE";a:2:{i:0;s:3:"GWE";i:1;s:17:"Escudo guinejské";}s:3:"GWM";a:2:{i:0;s:3:"GWM";i:1;s:26:"Portuguese Guinea Mil Reis";}s:3:"GWP";a:2:{i:0;s:3:"GWP";i:1;s:19:"Peso Guinnea-Bissau";}s:3:"GYD";a:2:{i:0;s:2:"G$";i:1;s:15:"Dolar guyanský";}s:3:"HKD";a:2:{i:0;s:3:"HK$";i:1;s:18:"Dolar hongkongský";}s:3:"HNL";a:2:{i:0;s:1:"L";i:1;s:7:"Lempira";}s:3:"HRD";a:2:{i:0;s:3:"HRD";i:1;s:17:"Dinar chorvatský";}s:3:"HRK";a:2:{i:0;s:3:"HRK";i:1;s:16:"Kuna chorvatská";}s:3:"HTG";a:2:{i:0;s:3:"HTG";i:1;s:6:"Gourde";}s:3:"HUF";a:2:{i:0;s:2:"Ft";i:1;s:6:"Forint";}s:3:"IBP";a:2:{i:0;s:3:"IBP";i:1;s:18:"Libra severoirská";}s:3:"IDG";a:2:{i:0;s:3:"IDG";i:1;s:23:"Indonesian Nica Guilder";}s:3:"IDJ";a:2:{i:0;s:3:"IDJ";i:1;s:22:"Indonesian Java Rupiah";}s:3:"IDN";a:2:{i:0;s:3:"IDN";i:1;s:21:"Indonesian New Rupiah";}s:3:"IDR";a:2:{i:0;s:2:"Rp";i:1;s:18:"Rupie indonézská";}s:3:"IEP";a:2:{i:0;s:4:"IR£";i:1;s:12:"Libra irská";}s:3:"ILL";a:2:{i:0;s:3:"ILL";i:1;s:17:"Å ekel izraelský";}s:3:"ILP";a:2:{i:0;s:3:"ILP";i:1;s:16:"Libra izraelská";}s:3:"ILS";a:2:{i:0;s:3:"ILS";i:1;s:23:"Å ekel nový izraelský";}s:3:"IMP";a:2:{i:0;s:3:"IMP";i:1;s:28:"Libra Å¡terlinků Ostrov Man";}s:3:"INR";a:2:{i:0;s:3:"INR";i:1;s:14:"Rupie indická";}s:3:"IQD";a:2:{i:0;s:2:"ID";i:1;s:15:"Dinár irácký";}s:3:"IRR";a:2:{i:0;s:2:"RI";i:1;s:17:"Rijál Ãránský";}s:3:"ISK";a:2:{i:0;s:3:"ISK";i:1;s:17:"Koruna islandská";}s:3:"ITL";a:2:{i:0;s:3:"₤";i:1;s:13:"Lira italská";}s:3:"JEP";a:2:{i:0;s:3:"JEP";i:1;s:24:"Libra Å¡terlinků Jersey";}s:3:"JMD";a:2:{i:0;s:2:"J$";i:1;s:15:"Dolar jamajský";}s:3:"JMP";a:2:{i:0;s:3:"JMP";i:1;s:15:"Libra jamajská";}s:3:"JOD";a:2:{i:0;s:2:"JD";i:1;s:18:"Dinár jordánský";}s:3:"JPY";a:2:{i:0;s:2:"Â¥";i:1;s:3:"Jen";}s:3:"KES";a:2:{i:0;s:4:"K Sh";i:1;s:16:"Å ilink keňský";}s:3:"KGS";a:2:{i:0;s:3:"som";i:1;s:3:"Som";}s:3:"KHO";a:2:{i:0;s:3:"KHO";i:1;s:11:"Riel starý";}s:3:"KHR";a:2:{i:0;s:2:"CR";i:1;s:4:"Riel";}s:3:"KID";a:2:{i:0;s:3:"KID";i:1;s:17:"Dolar kiribatský";}s:3:"KMF";a:2:{i:0;s:2:"CF";i:1;s:15:"Frank komorský";}s:3:"KPW";a:2:{i:0;s:3:"KPW";i:1;s:19:"Won severokorejský";}s:3:"KRH";a:2:{i:0;s:3:"KRH";i:1;s:18:"Hwan jihokorejský";}s:3:"KRO";a:2:{i:0;s:3:"KRO";i:1;s:24:"Won starý jihokorejský";}s:3:"KRW";a:2:{i:0;s:3:"KRW";i:1;s:17:"Won jihokorejský";}s:3:"KWD";a:2:{i:0;s:2:"KD";i:1;s:17:"Dinár kuvajtský";}s:3:"KYD";a:2:{i:0;s:3:"KYD";i:1;s:27:"Dolar Kajmanských ostrovů";}s:3:"KZR";a:2:{i:0;s:3:"KZR";i:1;s:15:"Rubl kazaÅ¡ský";}s:3:"KZT";a:2:{i:0;s:1:"T";i:1;s:5:"Tenge";}s:3:"LAK";a:2:{i:0;s:3:"LAK";i:1;s:3:"Kip";}s:3:"LBP";a:2:{i:0;s:2:"LL";i:1;s:17:"Libra libanonská";}s:3:"LIF";a:2:{i:0;s:3:"LIF";i:1;s:23:"Frank lichtenÅ¡tejnský";}s:3:"LKR";a:2:{i:0;s:5:"SL Re";i:1;s:17:"Rupie srÃlanská";}s:3:"LNR";a:2:{i:0;s:3:"LNR";i:1;s:16:"Rupie cejlonská";}s:3:"LRD";a:2:{i:0;s:3:"LRD";i:1;s:17:"Dolar liberijský";}s:3:"LSL";a:2:{i:0;s:1:"M";i:1;s:4:"Loti";}s:3:"LTL";a:2:{i:0;s:3:"LTL";i:1;s:15:"Litus litevský";}s:3:"LTT";a:2:{i:0;s:3:"LTT";i:1;s:5:"Talon";}s:3:"LUF";a:2:{i:0;s:3:"LUF";i:1;s:18:"Frank lucemburský";}s:3:"LVL";a:2:{i:0;s:3:"LVL";i:1;s:14:"Lat lotyÅ¡ský";}s:3:"LVR";a:2:{i:0;s:3:"LVR";i:1;s:15:"Rubl lotyÅ¡ský";}s:3:"LYD";a:2:{i:0;s:2:"LD";i:1;s:16:"Dinár lybijský";}s:3:"LYP";a:2:{i:0;s:3:"LYP";i:1;s:15:"Libra lybijská";}s:3:"MAD";a:2:{i:0;s:3:"MAD";i:1;s:15:"Dirham marocký";}s:3:"MAF";a:2:{i:0;s:3:"MAF";i:1;s:14:"Frank marocký";}s:3:"MCF";a:2:{i:0;s:3:"MCF";i:1;s:22:"Frank nouveau monacký";}s:3:"MCG";a:2:{i:0;s:3:"MCG";i:1;s:23:"Frank monacký germinal";}s:3:"MDC";a:2:{i:0;s:3:"MDC";i:1;s:18:"Moldovan Leu Cupon";}s:3:"MDL";a:2:{i:0;s:3:"MDL";i:1;s:14:"Leu moldavský";}s:3:"MDR";a:2:{i:0;s:3:"MDR";i:1;s:20:"Moldovan Ruble Cupon";}s:3:"MGA";a:2:{i:0;s:3:"MGA";i:1;s:21:"Ariary madagaskarský";}s:3:"MGF";a:2:{i:0;s:3:"MGF";i:1;s:20:"Frank madagaskarský";}s:3:"MHD";a:2:{i:0;s:3:"MHD";i:1;s:29:"Dolar Marshallových ostrovů";}s:3:"MKD";a:2:{i:0;s:4:"MDen";i:1;s:6:"Denár";}s:3:"MKN";a:2:{i:0;s:3:"MKN";i:1;s:18:"Denár (1992-1993)";}s:3:"MLF";a:2:{i:0;s:3:"MLF";i:1;s:15:"Frank malijský";}s:3:"MMK";a:2:{i:0;s:3:"MMK";i:1;s:4:"Kyat";}s:3:"MNT";a:2:{i:0;s:3:"Tug";i:1;s:6:"Tugrik";}s:3:"MOP";a:2:{i:0;s:3:"MOP";i:1;s:6:"Pataca";}s:3:"MQF";a:2:{i:0;s:3:"MQF";i:1;s:18:"Frank martinikský";}s:3:"MRO";a:2:{i:0;s:2:"UM";i:1;s:7:"Ouguiya";}s:3:"MTL";a:2:{i:0;s:2:"Lm";i:1;s:13:"Lira maltská";}s:3:"MTP";a:2:{i:0;s:3:"MTP";i:1;s:14:"Libra maltská";}s:3:"MUR";a:2:{i:0;s:3:"MUR";i:1;s:18:"Rupie mauricijská";}s:3:"MVP";a:2:{i:0;s:3:"MVP";i:1;s:17:"Rupie maledivská";}s:3:"MVR";a:2:{i:0;s:3:"MVR";i:1;s:7:"Rufiyaa";}s:3:"MWK";a:2:{i:0;s:2:"MK";i:1;s:6:"Kwacha";}s:3:"MWP";a:2:{i:0;s:3:"MWP";i:1;s:17:"Libra malawijská";}s:3:"MXN";a:2:{i:0;s:4:"MEX$";i:1;s:13:"Peso mexické";}s:3:"MXP";a:2:{i:0;s:3:"MXP";i:1;s:37:"Peso stÅ™Ãbrné mexické (1861-1992)";}s:3:"MXV";a:2:{i:0;s:3:"MXV";i:1;s:33:"Mexican Unidad de Inversion (UDI)";}s:3:"MYR";a:2:{i:0;s:2:"RM";i:1;s:21:"Ringgit malajskijský";}s:3:"MZE";a:2:{i:0;s:3:"MZE";i:1;s:16:"Escudo Mosambiku";}s:3:"MZM";a:2:{i:0;s:2:"Mt";i:1;s:7:"Metical";}s:3:"NAD";a:2:{i:0;s:2:"N$";i:1;s:17:"Dolar namibijský";}s:3:"NCF";a:2:{i:0;s:3:"NCF";i:1;s:30:"Frank Nové Kaledonie germinal";}s:3:"NGN";a:2:{i:0;s:3:"NGN";i:1;s:5:"Naira";}s:3:"NGP";a:2:{i:0;s:3:"NGP";i:1;s:17:"Libra nigerijská";}s:3:"NHF";a:2:{i:0;s:3:"NHF";i:1;s:24:"Frank Nových Hebrid CFP";}s:3:"NIC";a:2:{i:0;s:3:"NIC";i:1;s:7:"Cordoba";}s:3:"NIG";a:2:{i:0;s:3:"NIG";i:1;s:14:"Cordoba zlatá";}s:3:"NIO";a:2:{i:0;s:3:"NIO";i:1;s:11:"Cordoba oro";}s:3:"NLG";a:2:{i:0;s:3:"NLG";i:1;s:17:"Zlatý holandský";}s:3:"NOK";a:2:{i:0;s:3:"NKr";i:1;s:14:"Koruna norská";}s:3:"NPR";a:2:{i:0;s:3:"Nrs";i:1;s:16:"Rupie nepálská";}s:3:"NZD";a:2:{i:0;s:3:"$NZ";i:1;s:21:"Dolar novozélandský";}s:3:"NZP";a:2:{i:0;s:3:"NZP";i:1;s:21:"Libra novozélandská";}s:3:"OMR";a:2:{i:0;s:2:"RO";i:1;s:16:"Rijál ománský";}s:3:"OMS";a:2:{i:0;s:3:"OMS";i:1;s:22:"Rijál ománský saidi";}s:3:"PAB";a:2:{i:0;s:3:"PAB";i:1;s:6:"Balboa";}s:3:"PDK";a:2:{i:0;s:3:"PDK";i:1;s:26:"Transdniestria Ruble Kupon";}s:3:"PDN";a:2:{i:0;s:3:"PDN";i:1;s:24:"Transdniestria New Ruble";}s:3:"PDR";a:2:{i:0;s:3:"PDR";i:1;s:20:"Transdniestria Ruble";}s:3:"PEI";a:2:{i:0;s:3:"PEI";i:1;s:4:"Inti";}s:3:"PEN";a:2:{i:0;s:3:"PEN";i:1;s:9:"Nuevo sol";}s:3:"PES";a:2:{i:0;s:3:"PES";i:1;s:3:"Sol";}s:3:"PGK";a:2:{i:0;s:3:"PGK";i:1;s:4:"Kina";}s:3:"PHP";a:2:{i:0;s:3:"PHP";i:1;s:17:"Peso filipÃnské";}s:3:"PKR";a:2:{i:0;s:3:"Pra";i:1;s:20:"Rupie pákistánská";}s:3:"PLN";a:2:{i:0;s:2:"Zl";i:1;s:6:"Zlotý";}s:3:"PLZ";a:2:{i:0;s:3:"PLZ";i:1;s:18:"Zlotý (1950-1995)";}s:3:"PSP";a:2:{i:0;s:3:"PSP";i:1;s:18:"Libra palestinská";}s:3:"PTC";a:2:{i:0;s:3:"PTC";i:1;s:18:"Conto portugalské";}s:3:"PTE";a:2:{i:0;s:3:"PTE";i:1;s:19:"Escudo portugalské";}s:3:"PYG";a:2:{i:0;s:3:"PYG";i:1;s:7:"Guarani";}s:3:"QAR";a:2:{i:0;s:2:"QR";i:1;s:16:"Rijál katarský";}s:3:"REF";a:2:{i:0;s:3:"REF";i:1;s:13:"Frank Reunion";}s:3:"ROL";a:2:{i:0;s:3:"leu";i:1;s:3:"Lei";}s:3:"RON";a:2:{i:0;s:3:"RON";i:1;s:9:"Lei nový";}s:3:"RUB";a:2:{i:0;s:3:"RUB";i:1;s:11:"Rubl ruský";}s:3:"RUR";a:2:{i:0;s:3:"RUR";i:1;s:23:"Rubl ruský (1991-1998)";}s:3:"RWF";a:2:{i:0;s:3:"RWF";i:1;s:15:"Frank rwandský";}s:3:"SAR";a:2:{i:0;s:3:"SRl";i:1;s:15:"Rijál saudský";}s:3:"SAS";a:2:{i:0;s:3:"SAS";i:1;s:25:"Rijál saudský sovereign";}s:3:"SBD";a:2:{i:0;s:3:"SI$";i:1;s:30:"Dolar Å alamounových ostrovů";}s:3:"SCR";a:2:{i:0;s:2:"SR";i:1;s:17:"Rupie seychelská";}s:3:"SDD";a:2:{i:0;s:3:"SDD";i:1;s:18:"Dinár súdánský";}s:3:"SDP";a:2:{i:0;s:3:"SDP";i:1;s:17:"Libra súdánská";}s:3:"SEK";a:2:{i:0;s:3:"SKr";i:1;s:17:"Koruna Å¡védská";}s:3:"SGD";a:2:{i:0;s:2:"S$";i:1;s:18:"Dolar singapurský";}s:3:"SHP";a:2:{i:0;s:3:"SHP";i:1;s:19:"Libra Svaté Heleny";}s:3:"SIB";a:2:{i:0;s:3:"SIB";i:1;s:19:"Slovenia Tolar Bons";}s:3:"SIT";a:2:{i:0;s:3:"SIT";i:1;s:5:"Tolar";}s:3:"SKK";a:2:{i:0;s:2:"Sk";i:1;s:17:"Koruna slovenská";}s:3:"SML";a:2:{i:0;s:3:"SML";i:1;s:15:"Lira San Marino";}s:3:"SOS";a:2:{i:0;s:7:"So. Sh.";i:1;s:18:"Å ilink somálský";}s:3:"SQS";a:2:{i:0;s:3:"SQS";i:1;s:19:"Somaliland Shilling";}s:3:"SRG";a:2:{i:0;s:2:"Sf";i:1;s:18:"Zlatý surinamský";}s:3:"SSP";a:2:{i:0;s:3:"SSP";i:1;s:14:"Libra skotská";}s:3:"STD";a:2:{i:0;s:2:"Db";i:1;s:5:"Dobra";}s:3:"STE";a:2:{i:0;s:3:"STE";i:1;s:24:"Escudo Svatého Tomáše";}s:3:"SUN";a:2:{i:0;s:3:"SUN";i:1;s:10:"Rubl nový";}s:3:"SUR";a:2:{i:0;s:3:"SUR";i:1;s:4:"Rubl";}s:3:"SVC";a:2:{i:0;s:3:"SVC";i:1;s:18:"Colon salvadorský";}s:3:"SYP";a:2:{i:0;s:2:"LS";i:1;s:13:"Libra syrská";}s:3:"SZL";a:2:{i:0;s:1:"E";i:1;s:9:"Lilangeni";}s:3:"TCC";a:2:{i:0;s:3:"TCC";i:1;s:21:"Koruna Turks a Caicos";}s:3:"TDF";a:2:{i:0;s:3:"TDF";i:1;s:18:"Frank Äadský CFA";}s:3:"THB";a:2:{i:0;s:3:"THB";i:1;s:4:"Baht";}s:3:"TJR";a:2:{i:0;s:3:"TJR";i:1;s:16:"Tajikistan Ruble";}s:3:"TJS";a:2:{i:0;s:3:"TJS";i:1;s:6:"Somoni";}s:3:"TMM";a:2:{i:0;s:3:"TMM";i:1;s:5:"Manat";}s:3:"TND";a:2:{i:0;s:3:"TND";i:1;s:15:"Dinár tuniský";}s:3:"TOS";a:2:{i:0;s:3:"TOS";i:1;s:27:"Libra Å¡terlinků tonžská";}s:3:"TPE";a:2:{i:0;s:3:"TPE";i:1;s:16:"Escudo timorské";}s:3:"TPP";a:2:{i:0;s:3:"TPP";i:1;s:16:"Pataca timorská";}s:3:"TRL";a:2:{i:0;s:2:"TL";i:1;s:13:"Lira turecká";}s:3:"TTD";a:2:{i:0;s:3:"TT$";i:1;s:23:"Dolar Trinidad a Tobago";}s:3:"TTO";a:2:{i:0;s:3:"TTO";i:1;s:30:"Dolar starý Trinidad a Tobago";}s:3:"TVD";a:2:{i:0;s:3:"TVD";i:1;s:15:"Dolar tuvalský";}s:3:"TWD";a:2:{i:0;s:3:"NT$";i:1;s:24:"Dolar tchajvanský nový";}s:3:"TZS";a:2:{i:0;s:4:"T Sh";i:1;s:18:"Å ilink tanzanský";}s:3:"UAH";a:2:{i:0;s:3:"UAH";i:1;s:7:"HÅ™ivna";}s:3:"UAK";a:2:{i:0;s:3:"UAK";i:1;s:10:"Karbovanec";}s:3:"UGS";a:2:{i:0;s:3:"UGS";i:1;s:29:"Å ilink ugandský (1966-1987)";}s:3:"UGX";a:2:{i:0;s:4:"U Sh";i:1;s:17:"Å ilink ugandský";}s:3:"USD";a:2:{i:0;s:3:"US$";i:1;s:15:"Dolar americký";}s:3:"USN";a:2:{i:0;s:3:"USN";i:1;s:32:"Dolar americký (pÅ™ÃÅ¡tà den)";}s:3:"USS";a:2:{i:0;s:3:"USS";i:1;s:27:"Dolar americký (týž den)";}s:3:"UYF";a:2:{i:0;s:3:"UYF";i:1;s:23:"Peso uruguayské fuerte";}s:3:"UYP";a:2:{i:0;s:3:"UYP";i:1;s:28:"Peso uruguayské (1975-1993)";}s:3:"UYU";a:2:{i:0;s:3:"Ur$";i:1;s:16:"Peso uruguayské";}s:3:"UZC";a:2:{i:0;s:3:"UZC";i:1;s:21:"Uzbekistan Coupon Som";}s:3:"UZS";a:2:{i:0;s:3:"UZS";i:1;s:12:"Sum uzbecký";}s:3:"VAL";a:2:{i:0;s:3:"VAL";i:1;s:14:"Lira Vatikánu";}s:3:"VEB";a:2:{i:0;s:2:"Be";i:1;s:7:"Bolivar";}s:3:"VGD";a:2:{i:0;s:3:"VGD";i:1;s:37:"Dolar Britských Panenských ostrovů";}s:3:"VUV";a:2:{i:0;s:2:"VT";i:1;s:4:"Vatu";}s:3:"WSP";a:2:{i:0;s:3:"WSP";i:1;s:21:"Libra Západnà Samoa";}s:3:"WST";a:2:{i:0;s:3:"WST";i:1;s:4:"Tala";}s:3:"XAF";a:2:{i:0;s:3:"XAF";i:1;s:14:"Frank BEAC/CFA";}s:3:"XAM";a:2:{i:0;s:3:"XAM";i:1;s:28:"Asijská peněžnà jednotka";}s:3:"XAU";a:2:{i:0;s:3:"XAU";i:1;s:5:"Zlato";}s:3:"XBA";a:2:{i:0;s:3:"XBA";i:1;s:29:"Evropská smÃÅ¡ená jednotka";}s:3:"XBB";a:2:{i:0;s:3:"XBB";i:1;s:29:"Evropská peněžnà jednotka";}s:3:"XBC";a:2:{i:0;s:3:"XBC";i:1;s:33:"Evropská jednotka úÄtu 9 (XBC)";}s:3:"XBD";a:2:{i:0;s:3:"XBD";i:1;s:34:"Evropská jednotka úÄtu 17 (XBD)";}s:3:"XCD";a:2:{i:0;s:3:"EC$";i:1;s:23:"Dolar východokaribský";}s:3:"XCF";a:2:{i:0;s:3:"XCF";i:1;s:17:"Frank Nouveau CFA";}s:3:"XDR";a:2:{i:0;s:3:"XDR";i:1;s:3:"SDR";}s:3:"XEF";a:2:{i:0;s:3:"XEF";i:1;s:16:"Frank BCEAEC/CFA";}s:3:"XEU";a:2:{i:0;s:3:"XEU";i:1;s:27:"Evropská mÄ›nová jednotka";}s:3:"XFO";a:2:{i:0;s:3:"XFO";i:1;s:12:"Frank zlatý";}s:3:"XFU";a:2:{i:0;s:3:"XFU";i:1;s:9:"Frank UIC";}s:3:"XID";a:2:{i:0;s:3:"XID";i:1;s:17:"Dinár islámský";}s:3:"XNF";a:2:{i:0;s:3:"XNF";i:1;s:30:"Frank Francouzských Antil CFA";}s:3:"XOF";a:2:{i:0;s:3:"XOF";i:1;s:15:"Frank BCEAO/CFA";}s:3:"XPF";a:2:{i:0;s:4:"CFPF";i:1;s:9:"Frank CFP";}s:3:"YDD";a:2:{i:0;s:3:"YDD";i:1;s:16:"Dinár jemenský";}s:3:"YEI";a:2:{i:0;s:3:"YEI";i:1;s:22:"Rijál jemenský imadi";}s:3:"YER";a:2:{i:0;s:3:"YRl";i:1;s:16:"Rijál jemenský";}s:3:"YUD";a:2:{i:0;s:3:"YUD";i:1;s:26:"Dinár jugoslávský nový";}s:3:"YUF";a:2:{i:0;s:3:"YUF";i:1;s:33:"Dinár jugoslávský federativnÃ";}s:3:"YUG";a:2:{i:0;s:3:"YUG";i:1;s:25:"Dinár jugoslávský 1994";}s:3:"YUM";a:2:{i:0;s:3:"YUM";i:1;s:20:"Dinár jugoslávský";}s:3:"YUN";a:2:{i:0;s:3:"YUN";i:1;s:20:"Dinár jugoslávský";}s:3:"YUR";a:2:{i:0;s:3:"YUR";i:1;s:33:"Dinár jugoslávský reformovaný";}s:3:"ZAL";a:2:{i:0;s:3:"ZAL";i:1;s:15:"Rand finanÄnÃ";}s:3:"ZAP";a:2:{i:0;s:3:"ZAP";i:1;s:18:"Libra jihoafrická";}s:3:"ZAR";a:2:{i:0;s:1:"R";i:1;s:4:"Rand";}s:3:"ZMK";a:2:{i:0;s:3:"ZMK";i:1;s:6:"Kwacha";}s:3:"ZMP";a:2:{i:0;s:3:"ZMP";i:1;s:16:"Libra zambijská";}s:3:"ZRN";a:2:{i:0;s:3:"ZRN";i:1;s:11:"Zaire nový";}s:3:"ZRZ";a:2:{i:0;s:3:"ZRZ";i:1;s:5:"Zaire";}s:3:"ZWD";a:2:{i:0;s:2:"Z$";i:1;s:17:"Dolar zimbabwský";}}s:4:"Keys";a:3:{s:8:"calendar";a:1:{i:0;s:10:"Kalendář";}s:9:"collation";a:1:{i:0;s:11:"TÅ™ÃdÄ›nÃ";}s:8:"currency";a:1:{i:0;s:5:"MÄ›na";}}s:9:"Languages";a:139:{s:2:"aa";a:1:{i:0;s:10:"AfarÅ¡tina";}s:2:"ab";a:1:{i:0;s:13:"AbcházÅ¡tina";}s:2:"af";a:1:{i:0;s:14:"AfrikánÅ¡tina";}s:2:"am";a:1:{i:0;s:11:"AmharÅ¡tina";}s:2:"ar";a:1:{i:0;s:10:"ArabÅ¡tina";}s:2:"as";a:1:{i:0;s:13:"Assaméština";}s:2:"ay";a:1:{i:0;s:12:"AymárÅ¡tina";}s:2:"az";a:1:{i:0;s:19:"AzerbajdžánÅ¡tina";}s:2:"ba";a:1:{i:0;s:12:"BaskirÅ¡tina";}s:2:"be";a:1:{i:0;s:13:"BÄ›loruÅ¡tina";}s:2:"bg";a:1:{i:0;s:12:"BulharÅ¡tina";}s:2:"bh";a:1:{i:0;s:11:"BiharÅ¡tina";}s:2:"bi";a:1:{i:0;s:13:"BislámÅ¡tina";}s:2:"bn";a:1:{i:0;s:13:"BengálÅ¡tina";}s:2:"bo";a:1:{i:0;s:11:"TibetÅ¡tina";}s:2:"br";a:1:{i:0;s:13:"Bretaňština";}s:2:"ca";a:1:{i:0;s:14:"KatalánÅ¡tina";}s:2:"co";a:1:{i:0;s:11:"KorsiÄtina";}s:2:"cs";a:1:{i:0;s:9:"ÄŒeÅ¡tina";}s:2:"cy";a:1:{i:0;s:9:"VelÅ¡tina";}s:2:"da";a:1:{i:0;s:10:"DánÅ¡tina";}s:2:"de";a:1:{i:0;s:9:"NÄ›mÄina";}s:2:"dz";a:1:{i:0;s:14:"BhútánÅ¡tina";}s:2:"el";a:1:{i:0;s:9:"ŘeÄtina";}s:2:"en";a:1:{i:0;s:11:"AngliÄtina";}s:2:"eo";a:1:{i:0;s:9:"Esperanto";}s:2:"es";a:1:{i:0;s:14:"Å panÄ›lÅ¡tina";}s:2:"et";a:1:{i:0;s:11:"EstonÅ¡tina";}s:2:"eu";a:1:{i:0;s:11:"BaskiÄtina";}s:2:"fa";a:1:{i:0;s:9:"PerÅ¡tina";}s:2:"fi";a:1:{i:0;s:9:"FinÅ¡tina";}s:2:"fj";a:1:{i:0;s:6:"Fidži";}s:2:"fo";a:1:{i:0;s:10:"FaerÅ¡tina";}s:2:"fr";a:1:{i:0;s:14:"FrancouzÅ¡tina";}s:2:"fy";a:1:{i:0;s:10:"FrÃÅ¡tina";}s:2:"ga";a:1:{i:0;s:8:"IrÅ¡tina";}s:2:"gd";a:1:{i:0;s:18:"Skotská galÅ¡tina";}s:2:"gl";a:1:{i:0;s:12:"HaliÄÅ¡tina";}s:2:"gn";a:1:{i:0;s:12:"GuaranÅ¡tina";}s:2:"gu";a:1:{i:0;s:13:"GujaratÅ¡tina";}s:2:"ha";a:1:{i:0;s:5:"Hausa";}s:2:"he";a:1:{i:0;s:12:"HebrejÅ¡tina";}s:2:"hi";a:1:{i:0;s:10:"HindÅ¡tina";}s:2:"hr";a:1:{i:0;s:13:"ChorvatÅ¡tina";}s:2:"hu";a:1:{i:0;s:12:"MaÄarÅ¡tina";}s:2:"hy";a:1:{i:0;s:12:"ArménÅ¡tina";}s:2:"ia";a:1:{i:0;s:11:"Interlingua";}s:2:"id";a:1:{i:0;s:13:"Indonéština";}s:2:"ie";a:1:{i:0;s:11:"Interlingue";}s:2:"ik";a:1:{i:0;s:13:"InupiakÅ¡tina";}s:2:"is";a:1:{i:0;s:12:"IslandÅ¡tina";}s:2:"it";a:1:{i:0;s:10:"ItalÅ¡tina";}s:2:"iu";a:1:{i:0;s:15:"InuktitutÅ¡tina";}s:2:"ja";a:1:{i:0;s:11:"JaponÅ¡tina";}s:2:"jv";a:1:{i:0;s:12:"JavánÅ¡tina";}s:2:"ka";a:1:{i:0;s:13:"GruzÃnÅ¡tina";}s:2:"kk";a:1:{i:0;s:12:"KazachÅ¡tina";}s:2:"kl";a:1:{i:0;s:11:"GrónÅ¡tina";}s:2:"km";a:1:{i:0;s:14:"Kambodžština";}s:2:"kn";a:1:{i:0;s:12:"KannadÅ¡tina";}s:2:"ko";a:1:{i:0;s:11:"KorejÅ¡tina";}s:2:"ks";a:1:{i:0;s:14:"KaÅ¡mÃrÅ¡tina";}s:2:"ku";a:1:{i:0;s:10:"KurdÅ¡tina";}s:2:"ky";a:1:{i:0;s:12:"KirgizÅ¡tina";}s:2:"la";a:1:{i:0;s:6:"Latina";}s:2:"ln";a:1:{i:0;s:12:"LingalÅ¡tina";}s:2:"lo";a:1:{i:0;s:9:"LaoÅ¡tina";}s:2:"lt";a:1:{i:0;s:11:"LitevÅ¡tina";}s:2:"lv";a:1:{i:0;s:10:"LotyÅ¡tina";}s:2:"mg";a:1:{i:0;s:11:"MalgaÅ¡tina";}s:2:"mi";a:1:{i:0;s:10:"MaorÅ¡tina";}s:2:"mk";a:1:{i:0;s:13:"MakedonÅ¡tina";}s:2:"ml";a:1:{i:0;s:13:"MalabarÅ¡tina";}s:2:"mn";a:1:{i:0;s:12:"MongolÅ¡tina";}s:2:"mo";a:1:{i:0;s:12:"MoldavÅ¡tina";}s:2:"mr";a:1:{i:0;s:7:"Marathi";}s:2:"ms";a:1:{i:0;s:11:"MalajÅ¡tina";}s:2:"mt";a:1:{i:0;s:10:"MaltÅ¡tina";}s:2:"my";a:1:{i:0;s:10:"BarmÅ¡tina";}s:2:"na";a:1:{i:0;s:5:"Nauru";}s:2:"ne";a:1:{i:0;s:12:"NepálÅ¡tina";}s:2:"nl";a:1:{i:0;s:12:"HolandÅ¡tina";}s:2:"no";a:1:{i:0;s:9:"NorÅ¡tina";}s:2:"oc";a:1:{i:0;s:7:"Occitan";}s:2:"om";a:1:{i:0;s:12:"Oromo (Afan)";}s:2:"or";a:1:{i:0;s:5:"Oriya";}s:2:"pa";a:1:{i:0;s:16:"PaňdžábÅ¡tina";}s:2:"pl";a:1:{i:0;s:9:"PolÅ¡tina";}s:2:"ps";a:1:{i:0;s:15:"Pashto (Pushto)";}s:2:"pt";a:1:{i:0;s:14:"PortugalÅ¡tina";}s:2:"qu";a:1:{i:0;s:14:"KeÄuánÅ¡tina";}s:2:"rm";a:1:{i:0;s:17:"RétorománÅ¡tina";}s:2:"rn";a:1:{i:0;s:7:"Kirundi";}s:2:"ro";a:1:{i:0;s:11:"RumunÅ¡tina";}s:2:"ru";a:1:{i:0;s:8:"RuÅ¡tina";}s:2:"rw";a:1:{i:0;s:16:"KinyarwandÅ¡tina";}s:2:"sa";a:1:{i:0;s:7:"Sanskrt";}s:2:"sd";a:1:{i:0;s:6:"Sindhi";}s:2:"sg";a:1:{i:0;s:6:"Sangho";}s:2:"sh";a:1:{i:0;s:17:"SrbochorvatÅ¡tina";}s:2:"si";a:1:{i:0;s:13:"SinhálÅ¡tina";}s:2:"sk";a:1:{i:0;s:12:"SlovenÅ¡tina";}s:2:"sl";a:1:{i:0;s:12:"SlovinÅ¡tina";}s:2:"sm";a:1:{i:0;s:11:"SamoyÅ¡tina";}s:2:"sn";a:1:{i:0;s:5:"Shona";}s:2:"so";a:1:{i:0;s:12:"SomálÅ¡tina";}s:2:"sq";a:1:{i:0;s:12:"AlbánÅ¡tina";}s:2:"sr";a:1:{i:0;s:9:"SrbÅ¡tina";}s:2:"ss";a:1:{i:0;s:12:"SiswatÅ¡tina";}s:2:"st";a:1:{i:0;s:7:"Sesotho";}s:2:"su";a:1:{i:0;s:12:"SundanÅ¡tina";}s:2:"sv";a:1:{i:0;s:12:"Å védÅ¡tina";}s:2:"sw";a:1:{i:0;s:12:"SvahilÅ¡tina";}s:2:"ta";a:1:{i:0;s:11:"TamilÅ¡tina";}s:2:"te";a:1:{i:0;s:11:"TelugÅ¡tina";}s:2:"tg";a:1:{i:0;s:13:"TádžiÄtina";}s:2:"th";a:1:{i:0;s:10:"ThajÅ¡tina";}s:2:"ti";a:1:{i:0;s:14:"TigrinijÅ¡tina";}s:2:"tk";a:1:{i:0;s:13:"TurkmenÅ¡tina";}s:2:"tl";a:1:{i:0;s:7:"Tagalog";}s:2:"tn";a:1:{i:0;s:13:"SetswanÅ¡tina";}s:2:"to";a:1:{i:0;s:5:"Tonga";}s:2:"tr";a:1:{i:0;s:10:"TureÄtina";}s:2:"ts";a:1:{i:0;s:6:"Tsonga";}s:2:"tt";a:1:{i:0;s:11:"TatarÅ¡tina";}s:2:"tw";a:1:{i:0;s:3:"Twi";}s:2:"ug";a:1:{i:0;s:12:"UighurÅ¡tina";}s:2:"uk";a:1:{i:0;s:13:"UkrajinÅ¡tina";}s:2:"ur";a:1:{i:0;s:9:"UrdÅ¡tina";}s:2:"uz";a:1:{i:0;s:10:"UzbeÄtina";}s:2:"vi";a:1:{i:0;s:13:"VietnamÅ¡tina";}s:2:"vo";a:1:{i:0;s:7:"Volapuk";}s:2:"wo";a:1:{i:0;s:5:"Wolof";}s:2:"xh";a:1:{i:0;s:5:"Xhosa";}s:2:"yi";a:1:{i:0;s:6:"JidiÅ¡";}s:2:"yo";a:1:{i:0;s:6:"Yoruba";}s:2:"za";a:1:{i:0;s:6:"Zhuang";}s:2:"zh";a:1:{i:0;s:11:"ÄŒÃnÅ¡tina";}s:2:"zu";a:1:{i:0;s:4:"Zulu";}}s:12:"LocaleScript";a:1:{i:0;s:4:"Latn";}s:14:"NumberElements";a:12:{i:0;s:1:",";i:1;s:2:" ";i:2;s:1:";";i:3;s:1:"%";i:4;s:1:"0";i:5;s:1:"#";i:6;s:1:"-";i:7;s:1:"E";i:8;s:3:"‰";i:9;s:3:"∞";i:10;s:3:"�";i:11;s:1:"+";}s:5:"Types";a:1:{s:8:"calendar";a:7:{s:8:"buddhist";a:1:{i:0;s:23:"Budhistický kalendář";}s:7:"chinese";a:1:{i:0;s:20:"ÄŒÃnský kalendář";}s:9:"gregorian";a:1:{i:0;s:25:"Gregoriánský kalendář";}s:6:"hebrew";a:1:{i:0;s:21:"Hebrejský kalendář";}s:7:"islamic";a:1:{i:0;s:21:"Muslimský kalendář";}s:13:"islamic-civil";a:1:{i:0;s:32:"Muslimský obÄanský kalendář";}s:8:"japanese";a:1:{i:0;s:20:"Japonský kalendář";}}}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:6:{s:11:"AmPmMarkers";a:2:{i:0;s:4:"dop.";i:1;s:4:"odp.";}s:26:"DateTimeElements:intvector";a:2:{i:0;i:2;i:1;i:1;}s:16:"DateTimePatterns";a:9:{i:0;s:9:"H:mm:ss z";i:1;s:9:"H:mm:ss z";i:2;s:7:"H:mm:ss";i:3;s:4:"H:mm";i:4;s:18:"EEEE, d. MMMM yyyy";i:5;s:12:"d. MMMM yyyy";i:6;s:8:"d.M.yyyy";i:7;s:6:"d.M.yy";i:8;s:7:"{1} {0}";}s:8:"dayNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:7:{i:0;s:2:"ne";i:1;s:2:"po";i:2;s:3:"út";i:3;s:2:"st";i:4;s:3:"Ät";i:5;s:3:"pá";i:6;s:2:"so";}s:4:"wide";a:7:{i:0;s:7:"nedÄ›le";i:1;s:9:"pondÄ›lÃ";i:2;s:7:"úterý";i:3;s:7:"stÅ™eda";i:4;s:8:"Ätvrtek";i:5;s:6:"pátek";i:6;s:6:"sobota";}}}s:4:"eras";a:1:{s:11:"abbreviated";a:2:{i:0;s:7:"pÅ™.Kr.";i:1;s:6:"po Kr.";}}s:10:"monthNames";a:2:{s:6:"format";a:3:{s:11:"abbreviated";a:12:{i:0;s:2:"1.";i:1;s:2:"2.";i:2;s:2:"3.";i:3;s:2:"4.";i:4;s:2:"5.";i:5;s:2:"6.";i:6;s:2:"7.";i:7;s:2:"8.";i:8;s:2:"9.";i:9;s:3:"10.";i:10;s:3:"11.";i:11;s:3:"12.";}s:6:"narrow";a:12:{i:0;s:1:"l";i:1;s:2:"ú";i:2;s:1:"b";i:3;s:1:"d";i:4;s:1:"k";i:5;s:2:"Ä";i:6;s:2:"Ä";i:7;s:1:"s";i:8;s:1:"z";i:9;s:2:"Å™";i:10;s:1:"l";i:11;s:1:"p";}s:4:"wide";a:12:{i:0;s:5:"ledna";i:1;s:6:"února";i:2;s:7:"bÅ™ezna";i:3;s:5:"dubna";i:4;s:7:"kvÄ›tna";i:5;s:7:"Äervna";i:6;s:9:"Äervence";i:7;s:5:"srpna";i:8;s:7:"zářÃ";i:9;s:7:"Å™Ãjna";i:10;s:9:"listopadu";i:11;s:8:"prosince";}}s:11:"stand-alone";a:3:{s:11:"abbreviated";a:12:{i:0;s:2:"1.";i:1;s:2:"2.";i:2;s:2:"3.";i:3;s:2:"4.";i:4;s:2:"5.";i:5;s:2:"6.";i:6;s:2:"7.";i:7;s:2:"8.";i:8;s:2:"9.";i:9;s:3:"10.";i:10;s:3:"11.";i:11;s:3:"12.";}s:6:"narrow";a:12:{i:0;s:1:"l";i:1;s:2:"ú";i:2;s:1:"b";i:3;s:1:"d";i:4;s:1:"k";i:5;s:2:"Ä";i:6;s:2:"Ä";i:7;s:1:"s";i:8;s:1:"z";i:9;s:2:"Å™";i:10;s:1:"l";i:11;s:1:"p";}s:4:"wide";a:12:{i:0;s:5:"Leden";i:1;s:5:"Únor";i:2;s:7:"BÅ™ezen";i:3;s:5:"Duben";i:4;s:7:"KvÄ›ten";i:5;s:7:"ÄŒerven";i:6;s:9:"ÄŒervenec";i:7;s:5:"Srpen";i:8;s:7:"ZářÃ";i:9;s:7:"ŘÃjen";i:10;s:8:"Listopad";i:11;s:8:"Prosinec";}}}}}s:17:"localPatternChars";a:1:{i:0;s:24:"GuMtkHmsSEDFwWahKzUeygAZ";}s:11:"zoneStrings";a:17:{i:0;a:6:{i:0;s:19:"America/Los_Angeles";i:1;s:27:"Pacifický standardnà Äas";i:2;s:3:"PST";i:3;s:22:"Pacifický letnà Äas";i:4;s:3:"PDT";i:5;s:11:"Los Angeles";}i:1;a:6:{i:0;s:14:"America/Denver";i:1;s:24:"Horský standardnà Äas";i:2;s:3:"MST";i:3;s:19:"Horský letnà Äas";i:4;s:3:"MDT";i:5;s:6:"Denver";}i:2;a:6:{i:0;s:15:"America/Phoenix";i:1;s:24:"Horský standardnà Äas";i:2;s:3:"MST";i:3;s:24:"Horský standardnà Äas";i:4;s:3:"MST";i:5;s:7:"Phoenix";}i:3;a:6:{i:0;s:15:"America/Chicago";i:1;s:28:"Centrálnà standardnà Äas";i:2;s:3:"CST";i:3;s:23:"Centrálnà letnà Äas";i:4;s:3:"CDT";i:5;s:7:"Chicago";}i:4;a:6:{i:0;s:16:"America/New_York";i:1;s:27:"Východnà standardnà Äas";i:2;s:3:"EST";i:3;s:22:"Východnà letnà Äas";i:4;s:3:"EDT";i:5;s:8:"New York";}i:5;a:6:{i:0;s:20:"America/Indianapolis";i:1;s:27:"Východnà standardnà Äas";i:2;s:3:"EST";i:3;s:27:"Východnà standardnà Äas";i:4;s:3:"EST";i:5;s:12:"Indianapolis";}i:6;a:6:{i:0;s:16:"Pacific/Honolulu";i:1;s:26:"Havajský standardnà Äas";i:2;s:3:"HST";i:3;s:26:"Havajský standardnà Äas";i:4;s:3:"HST";i:5;s:8:"Honolulu";}i:7;a:6:{i:0;s:17:"America/Anchorage";i:1;s:27:"AljaÅ¡ský standardnà Äas";i:2;s:3:"AST";i:3;s:22:"AljaÅ¡ský letnà Äas";i:4;s:3:"ADT";i:5;s:9:"Anchorage";}i:8;a:6:{i:0;s:15:"America/Halifax";i:1;s:28:"Atlantický standardnà Äas";i:2;s:3:"AST";i:3;s:23:"Atlantický letnà Äas";i:4;s:3:"ADT";i:5;s:7:"Halifax";}i:9;a:6:{i:0;s:16:"America/St_Johns";i:1;s:33:"Newfoundlandský standardnà Äas";i:2;s:3:"CNT";i:3;s:28:"Newfoundlandský letnà Äas";i:4;s:3:"CDT";i:5;s:9:"St. Johns";}i:10;a:6:{i:0;s:12:"Europe/Paris";i:1;s:33:"StÅ™edoevropský standardnà Äas";i:2;s:3:"CET";i:3;s:28:"StÅ™edoevropský letnà Äas";i:4;s:4:"CEST";i:5;s:8:"PařÞ";}i:11;a:6:{i:0;s:7:"Etc/GMT";i:1;s:28:"Greenwichský stÅ™ednà Äas";i:2;s:3:"GMT";i:3;s:28:"Greenwichský stÅ™ednà Äas";i:4;s:3:"GMT";i:5;s:7:"Londýn";}i:12;a:6:{i:0;s:17:"Africa/Casablanca";i:1;s:28:"Greenwichský stÅ™ednà Äas";i:2;s:3:"GMT";i:3;s:28:"Greenwichský stÅ™ednà Äas";i:4;s:3:"GMT";i:5;s:10:"Casablanca";}i:13;a:6:{i:0;s:14:"Asia/Jerusalem";i:1;s:27:"Izraelský standardnà Äas";i:2;s:3:"IST";i:3;s:22:"Izraelský letnà Äas";i:4;s:3:"IDT";i:5;s:10:"Jeruzalém";}i:14;a:6:{i:0;s:10:"Asia/Tokyo";i:1;s:26:"Japonský standardnà Äas";i:2;s:3:"JST";i:3;s:26:"Japonský standardnà Äas";i:4;s:3:"JST";i:5;s:5:"Tokio";}i:15;a:6:{i:0;s:16:"Europe/Bucharest";i:1;s:34:"Východoevropský standardnà Äas";i:2;s:3:"EET";i:3;s:29:"Východoevropský letnà Äas";i:4;s:4:"EEST";i:5;s:10:"BukureÅ¡Å¥";}i:16;a:6:{i:0;s:13:"Asia/Shanghai";i:1;s:26:"ÄŒÃnský standardnà Äas";i:2;s:3:"CTT";i:3;s:26:"ÄŒÃnský standardnà Äas";i:4;s:3:"CDT";i:5;s:8:"Å anghaj";}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/cs_CZ.dat b/framework/I18N/core/data/cs_CZ.dat
new file mode 100644
index 00000000..f4c2e7ec
--- /dev/null
+++ b/framework/I18N/core/data/cs_CZ.dat
@@ -0,0 +1 @@
+a:2:{s:14:"NumberPatterns";a:4:{i:0;s:18:"#,##0.##;-#,##0.##";i:1;s:24:"#,##0.00 ¤;-#,##0.00 ¤";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/cy.dat b/framework/I18N/core/data/cy.dat
new file mode 100644
index 00000000..0f7babb7
--- /dev/null
+++ b/framework/I18N/core/data/cy.dat
@@ -0,0 +1 @@
+a:5:{s:9:"Countries";a:1:{s:2:"GB";a:1:{i:0;s:12:"Prydain Fawr";}}s:9:"Languages";a:1:{s:2:"cy";a:1:{i:0;s:7:"Cymraeg";}}s:12:"LocaleScript";a:1:{i:0;s:4:"Latn";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:2:{s:8:"dayNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:7:{i:0;s:3:"Sul";i:1;s:4:"Llun";i:2;s:3:"Maw";i:3;s:3:"Mer";i:4;s:3:"Iau";i:5;s:4:"Gwen";i:6;s:3:"Sad";}s:4:"wide";a:7:{i:0;s:8:"Dydd Sul";i:1;s:9:"Dydd Llun";i:2;s:11:"Dydd Mawrth";i:3;s:12:"Dydd Mercher";i:4;s:8:"Dydd Iau";i:5;s:11:"Dydd Gwener";i:6;s:11:"Dydd Sadwrn";}}}s:10:"monthNames";a:1:{s:6:"format";a:2:{s:11:"abbreviated";a:12:{i:0;s:3:"Ion";i:1;s:5:"Chwef";i:2;s:6:"Mawrth";i:3;s:6:"Ebrill";i:4;s:3:"Mai";i:5;s:3:"Meh";i:6;s:5:"Gorff";i:7;s:4:"Awst";i:8;s:4:"Medi";i:9;s:3:"Hyd";i:10;s:4:"Tach";i:11;s:4:"Rhag";}s:4:"wide";a:12:{i:0;s:6:"Ionawr";i:1;s:8:"Chwefror";i:2;s:6:"Mawrth";i:3;s:6:"Ebrill";i:4;s:3:"Mai";i:5;s:7:"Mehefin";i:6;s:9:"Gorffenaf";i:7;s:4:"Awst";i:8;s:4:"Medi";i:9;s:6:"Hydref";i:10;s:8:"Tachwedd";i:11;s:7:"Rhagfyr";}}}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/cy_GB.dat b/framework/I18N/core/data/cy_GB.dat
new file mode 100644
index 00000000..82dfff88
--- /dev/null
+++ b/framework/I18N/core/data/cy_GB.dat
@@ -0,0 +1 @@
+a:3:{s:14:"NumberPatterns";a:4:{i:0;s:20:"#,##0.###;-#,##0.###";i:1;s:22:"¤#,##0.00;-¤#,##0.00";i:2;s:6:"#,##0%";i:3;s:3:"#E0";}s:7:"Version";a:1:{i:0;s:3:"1.2";}s:8:"calendar";a:1:{s:9:"gregorian";a:2:{s:26:"DateTimeElements:intvector";a:2:{i:0;i:2;i:1;i:1;}s:16:"DateTimePatterns";a:9:{i:0;s:10:"HH:mm:ss z";i:1;s:10:"HH:mm:ss z";i:2;s:8:"HH:mm:ss";i:3;s:5:"HH:mm";i:4;s:18:"EEEE, dd MMMM yyyy";i:5;s:12:"dd MMMM yyyy";i:6;s:10:"d MMM yyyy";i:7;s:10:"dd/MM/yyyy";i:8;s:7:"{1} {0}";}}}}
\ No newline at end of file
diff --git a/framework/I18N/core/data/da.dat b/framework/I18N/core/data/da.dat
new file mode 100644
index 00000000..ff9b7422
--- /dev/null
+++ b/framework/I18N/core/data/da.dat
@@ -0,0 +1 @@
+a:12:{s:9:"Countries";a:240:{s:2:"AD";a:1:{i:0;s:7:"Andorra";}s:2:"AE";a:1:{i:0;s:26:"Forenede Arabiske Emirater";}s:2:"AF";a:1:{i:0;s:11:"Afghanistan";}s:2:"AG";a:1:{i:0;s:18:"Antigua og Barbuda";}s:2:"AI";a:1:{i:0;s:8:"Anguilla";}s:2:"AL";a:1:{i:0;s:8:"Albanien";}s:2:"AM";a:1:{i:0;s:8:"Armenien";}s:2:"AN";a:1:{i:0;s:19:"Hollandske Antiller";}s:2:"AO";a:1:{i:0;s:6:"Angola";}s:2:"AQ";a:1:{i:0;s:9:"Antarktis";}s:2:"AR";a:1:{i:0;s:9:"Argentina";}s:2:"AS";a:1:{i:0;s:16:"Amerikansk Samoa";}s:2:"AT";a:1:{i:0;s:7:"Østrig";}s:2:"AU";a:1:{i:0;s:10:"Australien";}s:2:"AW";a:1:{i:0;s:5:"Aruba";}s:2:"AZ";a:1:{i:0;s:12:"Aserbajdsjan";}s:2:"BA";a:1:{i:0;s:19:"Bosnien-Hercegovina";}s:2:"BB";a:1:{i:0;s:8:"Barbados";}s:2:"BD";a:1:{i:0;s:10:"Bangladesh";}s:2:"BE";a:1:{i:0;s:7:"Belgien";}s:2:"BF";a:1:{i:0;s:12:"Burkina Faso";}s:2:"BG";a:1:{i:0;s:9:"Bulgarien";}s:2:"BH";a:1:{i:0;s:7:"Bahrain";}s:2:"BI";a:1:{i:0;s:7:"Burundi";}s:2:"BJ";a:1:{i:0;s:5:"Benin";}s:2:"BM";a:1:{i:0;s:7:"Bermuda";}s:2:"BN";a:1:{i:0;s:17:"Brunei Darussalam";}s:2:"BO";a:1:{i:0;s:7:"Bolivia";}s:2:"BR";a:1:{i:0;s:9:"Brasilien";}s:2:"BS";a:1:{i:0;s:7:"Bahamas";}s:2:"BT";a:1:{i:0;s:6:"Bhutan";}s:2:"BV";a:1:{i:0;s:8:"Bouvetø";}s:2:"BW";a:1:{i:0;s:8:"Botswana";}s:2:"BY";a:1:{i:0;s:12:"Hviderusland";}s:2:"BZ";a:1:{i:0;s:6:"Belize";}s:2:"CA";a:1:{i:0;s:6:"Canada";}s:2:"CC";a:1:{i:0;s:28:"Cocos-øerne (Keelingøerne)";}s:2:"CD";a:1:{i:0;s:31:"Den Demokratiske Republik Congo";}s:2:"CF";a:1:{i:0;s:26:"Centralafrikanske Republik";}s:2:"CG";a:1:{i:0;s:5:"Congo";}s:2:"CH";a:1:{i:0;s:7:"Schweiz";}s:2:"CI";a:1:{i:0;s:15:"Elfenbenskysten";}s:2:"CK";a:1:{i:0;s:11:"Cook-øerne";}s:2:"CL";a:1:{i:0;s:5:"Chile";}s:2:"CM";a:1:{i:0;s:8:"Cameroun";}s:2:"CN";a:1:{i:0;s:4:"Kina";}s:2:"CO";a:1:{i:0;s:8:"Colombia";}s:2:"CR";a:1:{i:0;s:10:"Costa Rica";}s:2:"CU";a:1:{i:0;s:4:"Cuba";}s:2:"CV";a:1:{i:0;s:9:"Kap Verde";}s:2:"CX";a:1:{i:0;s:8:"Juleøen";}s:2:"CY";a:1:{i:0;s:6:"Cypern";}s:2:"CZ";a:1:{i:0;s:8:"Tjekkiet";}s:2:"DE";a:1:{i:0;s:8:"Tyskland";}s:2:"DJ";a:1:{i:0;s:8:"Djibouti";}s:2:"DK";a:1:{i:0;s:7:"Danmark";}s:2:"DM";a:1:{i:0;s:8:"Dominica";}s:2:"DO";a:1:{i:0;s:25:"Den Dominikanske Republik";}s:2:"DZ";a:1:{i:0;s:8:"Algeriet";}s:2:"EC";a:1:{i:0;s:7:"Ecuador";}s:2:"EE";a:1:{i:0;s:7:"Estland";}s:2:"EG";a:1:{i:0;s:7:"Egypten";}s:2:"EH";a:1:{i:0;s:10:"Vestsahara";}s:2:"ER";a:1:{i:0;s:7:"Eritrea";}s:2:"ES";a:1:{i:0;s:7:"Spanien";}s:2:"ET";a:1:{i:0;s:8:"Etiopien";}s:2:"FI";a:1:{i:0;s:7:"Finland";}s:2:"FJ";a:1:{i:0;s:11:"Fiji-øerne";}s:2:"FK";a:1:{i:0;s:15:"Falklandsøerne";}s:2:"FM";a:1:{i:0;s:28:"Mikronesiens Forenede Stater";}s:2:"FO";a:1:{i:0;s:10:"Færøerne";}s:2:"FR";a:1:{i:0;s:8:"Frankrig";}s:2:"GA";a:1:{i:0;s:5:"Gabon";}s:2:"GB";a:1:{i:0;s:14:"Storbritannien";}s:2:"GD";a:1:{i:0;s:7:"Grenada";}s:2:"GE";a:1:{i:0;s:8:"Georgien";}s:2:"GF";a:1:{i:0;s:13:"Fransk Guyana";}s:2:"GH";a:1:{i:0;s:5:"Ghana";}s:2:"GI";a:1:{i:0;s:9:"Gibraltar";}s:2:"GL";a:1:{i:0;s:9:"Grønland";}s:2:"GM";a:1:{i:0;s:6:"Gambia";}s:2:"GN";a:1:{i:0;s:6:"Guinea";}s:2:"GP";a:1:{i:0;s:10:"Guadeloupe";}s:2:"GQ";a:1:{i:0;s:17:"Ækvatorialguinea";}s:2:"GR";a:1:{i:0;s:11:"Grækenland";}s:2:"GS";a:1:{i:0;s:40:"South Georgia og De Sydlige Sandwichøer";}s:2:"GT";a:1:{i:0;s:9:"Guatemala";}s:2:"GU";a:1:{i:0;s:4:"Guam";}s:2:"GW";a:1:{i:0;s:13:"Guinea-Bissau";}s:2:"GY";a:1:{i:0;s:6:"Guyana";}s:2:"HK";a:1:{i:0;s:12:"SAR Hongkong";}s:2:"HM";a:1:{i:0;s:25:"Heard- og McDonald-øerne";}s:2:"HN";a:1:{i:0;s:8:"Honduras";}s:2:"HR";a:1:{i:0;s:8:"Kroatien";}s:2:"HT";a:1:{i:0;s:5:"Haiti";}s:2:"HU";a:1:{i:0;s:6:"Ungarn";}s:2:"ID";a:1:{i:0;s:10:"Indonesien";}s:2:"IE";a:1:{i:0;s:6:"Irland";}s:2:"IL";a:1:{i:0;s:6:"Israel";}s:2:"IN";a:1:{i:0;s:6:"Indien";}s:2:"IO";a:1:{i:0;s:44:"Det Britiske Territorium i Det Indiske Ocean";}s:2:"IQ";a:1:{i:0;s:4:"Irak";}s:2:"IR";a:1:{i:0;s:4:"Iran";}s:2:"IS";a:1:{i:0;s:6:"Island";}s:2:"IT";a:1:{i:0;s:7:"Italien";}s:2:"JM";a:1:{i:0;s:7:"Jamaica";}s:2:"JO";a:1:{i:0;s:6:"Jordan";}s:2:"JP";a:1:{i:0;s:5:"Japan";}s:2:"KE";a:1:{i:0;s:5:"Kenya";}s:2:"KG";a:1:{i:0;s:11:"Kirgisistan";}s:2:"KH";a:1:{i:0;s:8:"Cambodja";}s:2:"KI";a:1:{i:0;s:8:"Kiribati";}s:2:"KM";a:1:{i:0;s:9:"Comorerne";}s:2:"KN";a:1:{i:0;s:20:"Saint Kitts og Nevis";}s:2:"KP";a:1:{i:0;s:9:"Nordkorea";}s:2:"KR";a:1:{i:0;s:8:"Sydkorea";}s:2:"KW";a:1:{i:0;s:6:"Kuwait";}s:2:"KY";a:1:{i:0;s:12:"Caymanøerne";}s:2:"KZ";a:1:{i:0;s:10:"Kasakhstan";}s:2:"LA";a:1:{i:0;s:4:"Laos";}s:2:"LB";a:1:{i:0;s:7:"Libanon";}s:2:"LC";a:1:{i:0;s:11:"Saint Lucia";}s:2:"LI";a:1:{i:0;s:13:"Liechtenstein";}s:2:"LK";a:1:{i:0;s:9:"Sri Lanka";}s:2:"LR";a:1:{i:0;s:7:"Liberia";}s:2:"LS";a:1:{i:0;s:7:"Lesotho";}s:2:"LT";a:1:{i:0;s:7:"Litauen";}s:2:"LU";a:1:{i:0;s:10:"Luxembourg";}s:2:"LV";a:1:{i:0;s:7:"Letland";}s:2:"LY";a:1:{i:0;s:6:"Libyen";}s:2:"MA";a:1:{i:0;s:7:"Marokko";}s:2:"MC";a:1:{i:0;s:6:"Monaco";}s:2:"MD";a:1:{i:0;s:19:"Republikken Moldova";}s:2:"MG";a:1:{i:0;s:10:"Madagaskar";}s:2:"MH";a:1:{i:0;s:14:"Marshalløerne";}s:2:"MK";a:1:{i:0;s:22:"Republikken Makedonien";}s:2:"ML";a:1:{i:0;s:4:"Mali";}s:2:"MM";a:1:{i:0;s:7:"Myanmar";}s:2:"MN";a:1:{i:0;s:9:"Mongoliet";}s:2:"MO";a:1:{i:0;s:9:"SAR Macao";}s:2:"MP";a:1:{i:0;s:14:"Nordmarianerne";}s:2:"MQ";a:1:{i:0;s:10:"Martinique";}s:2:"MR";a:1:{i:0;s:11:"Mauretanien";}s:2:"MS";a:1:{i:0;s:10:"Montserrat";}s:2:"MT";a:1:{i:0;s:5:"Malta";}s:2:"MU";a:1:{i:0;s:9:"Mauritius";}s:2:"MV";a:1:{i:0;s:10:"Maldiverne";}s:2:"MW";a:1:{i:0;s:6:"Malawi";}s:2:"MX";a:1:{i:0;s:6:"Mexico";}s:2:"MY";a:1:{i:0;s:8:"Malaysia";}s:2:"MZ";a:1:{i:0;s:10:"Mozambique";}s:2:"NA";a:1:{i:0;s:7:"Namibia";}s:2:"NC";a:1:{i:0;s:13:"Ny Caledonien";}s:2:"NE";a:1:{i:0;s:5:"Niger";}s:2:"NF";a:1:{i:0;s:14:"Norfolk Island";}s:2:"NG";a:1:{i:0;s:7:"Nigeria";}s:2:"NI";a:1:{i:0;s:9:"Nicaragua";}s:2:"NL";a:1:{i:0;s:7:"Holland";}s:2:"NO";a:1:{i:0;s:5:"Norge";}s:2:"NP";a:1:{i:0;s:5:"Nepal";}s:2:"NR";a:1:{i:0;s:5:"Nauru";}s:2:"NU";a:1:{i:0;s:4:"Niue";}s:2:"NZ";a:1:{i:0;s:11:"New Zealand";}s:2:"OM";a:1:{i:0;s:4:"Oman";}s:2:"PA";a:1:{i:0;s:6:"Panama";}s:2:"PE";a:1:{i:0;s:4:"Peru";}s:2:"PF";a:1:{i:0;s:17:"Fransk Polynesien";}s:2:"PG";a:1:{i:0;s:15:"Papua Ny Guinea";}s:2:"PH";a:1:{i:0;s:12:"Filippinerne";}s:2:"PK";a:1:{i:0;s:8:"Pakistan";}s:2:"PL";a:1:{i:0;s:5:"Polen";}s:2:"PM";a:1:{i:0;s:24:"Saint Pierre og Miquelon";}s:2:"PN";a:1:{i:0;s:8:"Pitcairn";}s:2:"PR";a:1:{i:0;s:11:"Puerto Rico";}s:2:"PS";a:1:{i:0;s:28:"De palæstinensiske omrÃ¥der";}s:2:"PT";a:1:{i:0;s:8:"Portugal";}s:2:"PW";a:1:{i:0;s:5:"Palau";}s:2:"PY";a:1:{i:0;s:8:"Paraguay";}s:2:"QA";a:1:{i:0;s:5:"Qatar";}s:2:"RE";a:1:{i:0;s:7:"Reunion";}s:2:"RO";a:1:{i:0;s:9:"Rumænien";}s:2:"RU";a:1:{i:0;s:7:"Rusland";}s:2:"RW";a:1:{i:0;s:6:"Rwanda";}s:2:"SA";a:1:{i:0;s:13:"Saudi-Arabien";}s:2:"SB";a:1:{i:0;s:13:"Salomonøerne";}s:2:"SC";a:1:{i:0;s:12:"Seychellerne";}s:2:"SD";a:1:{i:0;s:5:"Sudan";}s:2:"SE";a:1:{i:0;s:7:"Sverige";}s:2:"SG";a:1:{i:0;s:9:"Singapore";}s:2:"SH";a:1:{i:0;s:10:"St. Helena";}s:2:"SI";a:1:{i:0;s:9:"Slovenien";}s:2:"SJ";a:1:{i:0;s:21:"Svalbard og Jan Mayen";}s:2:"SK";a:1:{i:0;s:9:"Slovakiet";}s:2:"SL";a:1:{i:0;s:12:"Sierra Leone";}s:2:"SM";a:1:{i:0;s:10:"San Marino";}s:2:"SN";a:1:{i:0;s:7:"Senegal";}s:2:"SO";a:1:{i:0;s:7:"Somalia";}s:2:"SP";a:1:{i:0;s:7:"Serbien";}s:2:"SR";a:1:{i:0;s:7:"Surinam";}s:2:"ST";a:1:{i:0;s:23:"São Tomé og PrÃncipe";}s:2:"SV";a:1:{i:0;s:11:"El Salvador";}s:2:"SY";a:1:{i:0;s:6:"Syrien";}s:2:"SZ";a:1:{i:0;s:9:"Swaziland";}s:2:"TC";a:1:{i:0;s:22:"Turks- og Caicosøerne";}s:2:"TD";a:1:{i:0;s:5:"Tchad";}s:2:"TF";a:1:{i:0;s:47:"Franske Besiddelser i Det Sydlige Indiske Ocean";}s:2:"TG";a:1:{i:0;s:4:"Togo";}s:2:"TH";a:1:{i:0;s:8:"Thailand";}s:2:"TJ";a:1:{i:0;s:12:"Tadsjikistan";}s:2:"TK";a:1:{i:0;s:7:"Tokelau";}s:2:"TL";a:1:{i:0;s:11:"Timor-Leste";}s:2:"TM";a:1:{i:0;s:12:"Turkmenistan";}s:2:"TN";a:1:{i:0;s:8:"Tunesien";}s:2:"TO";a:1:{i:0;s:5:"Tonga";}s:2:"TR";a:1:{i:0;s:7:"Tyrkiet";}s:2:"TT";a:1:{i:0;s:18:"Trinidad og Tobago";}s:2:"TV";a:1:{i:0;s:6:"Tuvalu";}s:2:"TW";a:1:{i:0;s:6:"Taiwan";}s:2:"TZ";a:1:{i:0;s:8:"Tanzania";}s:2:"UA";a:1:{i:0;s:7:"Ukraine";}s:2:"UG";a:1:{i:0;s:6:"Uganda";}s:2:"UM";a:1:{i:0;s:38:"De Mindre Amerikanske Oversøiske Øer";}s:2:"US";a:1:{i:0;s:3:"USA";}s:2:"UY";a:1:{i:0;s:7:"Uruguay";}s:2:"UZ";a:1:{i:0;s:10:"Usbekistan";}s:2:"VA";a:1:{i:0;s:13:"Vatikanstaten";}s:2:"VC";a:1:{i:0;s:27:"St. Vincent og Grenadinerne";}s:2:"VE";a:1:{i:0;s:9:"Venezuela";}s:2:"VG";a:1:{i:0;s:22:"De britiske jomfruøer";}s:2:"VI";a:1:{i:0;s:25:"De amerikanske jomfruøer";}s:2:"VN";a:1:{i:0;s:7:"Vietnam";}s:2:"VU";a:1:{i:0;s:7:"Vanuatu";}s:2:"WF";a:1:{i:0;s:22:"Wallis og Futunaøerne";}s:2:"WS";a:1:{i:0;s:5:"Samoa";}s:2:"YE";a:1:{i:0;s:5:"Yemen";}s:2:"YT";a:1:{i:0;s:7:"Mayotte";}s:2:"YU";a:1:{i:0;s:11:"Jugoslavien";}s:2:"ZA";a:1:{i:0;s:9:"Sydafrika";}s:2:"ZM";a:1:{i:0;s:6:"Zambia";}s:2:"ZW";a:1:{i:0;s:8:"Zimbabwe";}}s:10:"Currencies";a:346:{s:3:"ADD";a:2:{i:0;s:3:"ADD";i:1;s:16:"Andorransk diner";}s:3:"ADP";a:2:{i:0;s:3:"ADP";i:1;s:17:"Andorransk peseta";}s:3:"AED";a:2:{i:0;s:3:"AED";i:1;s:40:"Dirham fra de Forenede Arabiske Emirater";}s:3:"AIF";a:2:{i:0;s:3:"AIF";i:1;s:21:"Affars og Issas franc";}s:3:"ALK";a:2:{i:0;s:3:"ALK";i:1;s:23:"Albansk lek (1946-1961)";}s:3:"ALL";a:2:{i:0;s:3:"lek";i:1;s:11:"Albansk lek";}s:3:"ALV";a:2:{i:0;s:3:"ALV";i:1;s:11:"Albansk lek";}s:3:"AMD";a:2:{i:0;s:4:"dram";i:1;s:12:"Armensk dram";}s:3:"ANG";a:2:{i:0;s:5:"NA f.";i:1;s:35:"Gylden fra De Nederlandske Antiller";}s:3:"AOA";a:2:{i:0;s:3:"AOA";i:1;s:16:"Angolansk kwanza";}s:3:"AOK";a:2:{i:0;s:3:"AOK";i:1;s:28:"Angolansk kwanza (1977-1990)";}s:3:"AON";a:2:{i:0;s:3:"AON";i:1;s:31:"Ny angolansk kwanza (1990-2000)";}s:3:"AOR";a:2:{i:0;s:3:"AOR";i:1;s:39:"Angolansk kwanza reajustado (1995-1999)";}s:3:"AOS";a:2:{i:0;s:3:"AOS";i:1;s:16:"Angolansk escudo";}s:3:"ARA";a:2:{i:0;s:3:"ARA";i:1;s:18:"Argentinsk austral";}s:3:"ARM";a:2:{i:0;s:3:"ARM";i:1;s:31:"Argentinsk peso moneda nacional";}s:3:"ARP";a:2:{i:0;s:3:"ARP";i:1;s:27:"Argentinsk peso (1983-1985)";}s:3:"ARS";a:2:{i:0;s:4:"Arg$";i:1;s:15:"Argentinsk peso";}s:3:"ATS";a:2:{i:0;s:3:"ATS";i:1;s:19:"Østrigsk schilling";}s:3:"AUD";a:2:{i:0;s:2:"$A";i:1;s:16:"Australsk dollar";}s:3:"AUP";a:2:{i:0;s:3:"AUP";i:1;s:14:"Australsk pund";}s:3:"AWG";a:2:{i:0;s:3:"AWG";i:1;s:15:"Arubansk gylden";}s:3:"AZM";a:2:{i:0;s:3:"AZM";i:1;s:20:"Aserbajdsjansk manat";}s:3:"BAD";a:2:{i:0;s:3:"BAD";i:1;s:26:"Bosnien-Hercegovinsk dinar";}s:3:"BAM";a:2:{i:0;s:2:"KM";i:1;s:37:"Bosnien-Hercegovinsk konvertibel mark";}s:3:"BAN";a:2:{i:0;s:3:"BAN";i:1;s:29:"Ny bosnien-hercegovinsk dinar";}s:3:"BBD";a:2:{i:0;s:4:"BDS$";i:1;s:16:"Barbadisk dollar";}s:3:"BDT";a:2:{i:0;s:2:"Tk";i:1;s:18:"Bangladeshisk taka";}s:3:"BEC";a:2:{i:0;s:3:"BEC";i:1;s:27:"Belgisk franc (konvertibel)";}s:3:"BEF";a:2:{i:0;s:2:"BF";i:1;s:13:"Belgisk franc";}s:3:"BEL";a:2:{i:0;s:3:"BEL";i:1;s:25:"Belgisk franc (financial)";}s:3:"BGL";a:2:{i:0;s:3:"lev";i:1;s:17:"Bulgarsk hard lev";}s:3:"BGM";a:2:{i:0;s:3:"BGM";i:1;s:22:"Bulgarsk socialist lev";}s:3:"BGN";a:2:{i:0;s:3:"BGN";i:1;s:15:"Ny Bulgarsk lev";}s:3:"BGO";a:2:{i:0;s:3:"BGO";i:1;s:24:"Bulgarsk lev (1879-1952)";}s:3:"BHD";a:2:{i:0;s:2:"BD";i:1;s:15:"Bahrainsk dinar";}s:3:"BIF";a:2:{i:0;s:3:"Fbu";i:1;s:15:"Burundisk franc";}s:3:"BMD";a:2:{i:0;s:4:"Ber$";i:1;s:17:"Bermudansk dollar";}s:3:"BMP";a:2:{i:0;s:3:"BMP";i:1;s:15:"Bermudansk pund";}s:3:"BND";a:2:{i:0;s:3:"BND";i:1;s:15:"Bruneisk dollar";}s:3:"BOP";a:2:{i:0;s:3:"BOP";i:1;s:15:"Boliviansk peso";}s:3:"BOV";a:2:{i:0;s:3:"BOV";i:1;s:16:"Boliviansk mvdol";}s:3:"BRB";a:2:{i:0;s:3:"BRB";i:1;s:37:"Brasiliansk cruzeiro novo (1967-1986)";}s:3:"BRC";a:2:{i:0;s:3:"BRC";i:1;s:19:"Brasiliansk cruzado";}s:3:"BRE";a:2:{i:0;s:3:"BRE";i:1;s:32:"Brasiliansk cruzeiro (1990-1993)";}s:3:"BRL";a:2:{i:0;s:2:"R$";i:1;s:16:"Brasiliansk real";}s:3:"BRN";a:2:{i:0;s:3:"BRN";i:1;s:24:"Brasiliansk cruzado novo";}s:3:"BRR";a:2:{i:0;s:3:"BRR";i:1;s:20:"Brasiliansk cruzeiro";}s:3:"BRZ";a:2:{i:0;s:3:"BRZ";i:1;s:32:"Brasiliansk cruzeiro (1942-1967)";}s:3:"BSD";a:2:{i:0;s:3:"BSD";i:1;s:16:"Bahamansk dollar";}s:3:"BSP";a:2:{i:0;s:3:"BSP";i:1;s:14:"Bahamansk pund";}s:3:"BTN";a:2:{i:0;s:2:"Nu";i:1;s:17:"Bhutansk ngultrum";}s:3:"BTR";a:2:{i:0;s:3:"BTR";i:1;s:14:"Bhutansk rupee";}s:3:"BUK";a:2:{i:0;s:3:"BUK";i:1;s:14:"Burmesisk kyat";}s:3:"BUR";a:2:{i:0;s:3:"BUR";i:1;s:15:"Burmesisk rupee";}s:3:"BWP";a:2:{i:0;s:3:"BWP";i:1;s:14:"Botswansk pula";}s:3:"BYB";a:2:{i:0;s:3:"BYB";i:1;s:33:"Ny hviderussisk rubel (1994-1999)";}s:3:"BYL";a:2:{i:0;s:3:"BYL";i:1;s:30:"Hviderussisk rubel (1992-1994)";}s:3:"BYR";a:2:{i:0;s:3:"Rbl";i:1;s:18:"Hviderussisk rubel";}s:3:"BZD";a:2:{i:0;s:3:"BZ$";i:1;s:15:"Belizisk dollar";}s:3:"BZH";a:2:{i:0;s:3:"BZH";i:1;s:23:"Britisk Honduras dollar";}s:3:"CAD";a:2:{i:0;s:4:"Can$";i:1;s:15:"Canadisk dollar";}s:3:"CDF";a:2:{i:0;s:3:"CDF";i:1;s:27:"Congolesisk franc congolais";}s:3:"CDG";a:2:{i:0;s:3:"CDG";i:1;s:17:"Congolesisk franc";}s:3:"CDL";a:2:{i:0;s:3:"CDL";i:1;s:17:"Congolesisk Zaire";}s:3:"CFF";a:2:{i:0;s:3:"CFF";i:1;s:44:"CFA-franc fra den Centralafrikanske republik";}s:3:"CHF";a:2:{i:0;s:3:"SwF";i:1;s:16:"Schweizisk franc";}s:3:"CKD";a:2:{i:0;s:3:"CKD";i:1;s:21:"Dollar fra Cookøerne";}s:3:"CLC";a:2:{i:0;s:3:"CLC";i:1;s:15:"Chilensk condor";}s:3:"CLE";a:2:{i:0;s:3:"CLE";i:1;s:15:"Chilensk escudo";}s:3:"CLF";a:2:{i:0;s:3:"CLF";i:1;s:28:"Chilensk unidades de fomento";}s:3:"CLP";a:2:{i:0;s:3:"Ch$";i:1;s:13:"Chilensk peso";}s:3:"CMF";a:2:{i:0;s:3:"CMF";i:1;s:20:"Camerounsk CFA-franc";}s:3:"CNP";a:2:{i:0;s:3:"CNP";i:1;s:26:"Kinesisk jen min piao yuan";}s:3:"CNY";a:2:{i:0;s:1:"Y";i:1;s:22:"Kinesisk yuan renminbi";}s:3:"COB";a:2:{i:0;s:3:"COB";i:1;s:21:"Colombiansk papirpeso";}s:3:"COF";a:2:{i:0;s:3:"COF";i:1;s:21:"Congolesisk CFA-franc";}s:3:"COP";a:2:{i:0;s:4:"Col$";i:1;s:16:"Colombiansk peso";}s:3:"CRC";a:2:{i:0;s:1:"C";i:1;s:18:"Costaricansk colon";}s:3:"CSC";a:2:{i:0;s:3:"CSC";i:1;s:22:"Tjekkoslovakisk koruna";}s:3:"CSK";a:2:{i:0;s:3:"CSK";i:1;s:27:"Tjekkoslovakisk hard koruna";}s:3:"CUP";a:2:{i:0;s:3:"CUP";i:1;s:12:"Cubansk peso";}s:3:"CVE";a:2:{i:0;s:5:"CVEsc";i:1;s:17:"Kapverdisk escudo";}s:3:"CWG";a:2:{i:0;s:3:"CWG";i:1;s:16:"Curacaosk gylden";}s:3:"CYP";a:2:{i:0;s:3:"£C";i:1;s:15:"Cypriotisk pund";}s:3:"CZK";a:2:{i:0;s:3:"CZK";i:1;s:15:"Tjekkisk koruna";}s:3:"DDM";a:2:{i:0;s:3:"DDM";i:1;s:13:"Østtysk mark";}s:3:"DEM";a:2:{i:0;s:3:"DEM";i:1;s:9:"Tysk mark";}s:3:"DES";a:2:{i:0;s:3:"DES";i:1;s:14:"Tysk sperrmark";}s:3:"DJF";a:2:{i:0;s:2:"DF";i:1;s:16:"Djiboutisk franc";}s:3:"DKK";a:2:{i:0;s:2:"kr";i:1;s:11:"Dansk krone";}s:3:"DOP";a:2:{i:0;s:3:"RD$";i:1;s:16:"Dominikansk peso";}s:3:"DZD";a:2:{i:0;s:2:"DA";i:1;s:14:"Algerisk dinar";}s:3:"DZF";a:2:{i:0;s:3:"DZF";i:1;s:17:"Ny algerisk franc";}s:3:"DZG";a:2:{i:0;s:3:"DZG";i:1;s:23:"Algerisk franc germinal";}s:3:"ECS";a:2:{i:0;s:3:"ECS";i:1;s:18:"Ecuadoriansk sucre";}s:3:"EEK";a:2:{i:0;s:3:"EEK";i:1;s:12:"Estisk kroon";}s:3:"EGP";a:2:{i:0;s:3:"EGP";i:1;s:13:"Egyptisk pund";}s:3:"ERN";a:2:{i:0;s:3:"ERN";i:1;s:15:"Eritreisk nakfa";}s:3:"ESP";a:2:{i:0;s:3:"ESP";i:1;s:13:"Spansk peseta";}s:3:"ETB";a:2:{i:0;s:2:"Br";i:1;s:13:"Etiopisk birr";}s:3:"ETD";a:2:{i:0;s:3:"ETD";i:1;s:15:"Etiopisk dollar";}s:3:"EUR";a:2:{i:0;s:3:"€";i:1;s:4:"Euro";}s:3:"FIM";a:2:{i:0;s:3:"FIM";i:1;s:10:"Finsk mark";}s:3:"FIN";a:2:{i:0;s:3:"FIN";i:1;s:22:"Finsk mark (1860-1962)";}s:3:"FJD";a:2:{i:0;s:2:"F$";i:1;s:15:"Fijiansk dollar";}s:3:"FJP";a:2:{i:0;s:3:"FJP";i:1;s:13:"Fijiansk pund";}s:3:"FKP";a:2:{i:0;s:3:"FKP";i:1;s:24:"Pund fra Falklandsøerne";}s:3:"FOK";a:2:{i:0;s:3:"FOK";i:1;s:14:"Færøsk krone";}s:3:"FRF";a:2:{i:0;s:3:"FRF";i:1;s:12:"Fransk franc";}s:3:"GAF";a:2:{i:0;s:3:"GAF";i:1;s:20:"Gabonesisk CFA-franc";}s:3:"GBP";a:2:{i:0;s:2:"£";i:1;s:12:"Britisk pund";}s:3:"GEK";a:2:{i:0;s:3:"GEK";i:1;s:20:"Georgisk kupon larit";}s:3:"GEL";a:2:{i:0;s:4:"lari";i:1;s:13:"Georgisk lari";}s:3:"GHC";a:2:{i:0;s:3:"GHC";i:1;s:14:"Ghanesisk cedi";}s:3:"GHO";a:2:{i:0;s:3:"GHO";i:1;s:21:"Gammel ghanesisk cedi";}s:3:"GHP";a:2:{i:0;s:3:"GHP";i:1;s:14:"Ghanesisk pund";}s:3:"GHR";a:2:{i:0;s:3:"GHR";i:1;s:25:"Ghanesisk revalueret cedi";}s:3:"GIP";a:2:{i:0;s:3:"GIP";i:1;s:17:"Gibraltarisk pund";}s:3:"GLK";a:2:{i:0;s:3:"GLK";i:1;s:17:"Grønlandsk krone";}s:3:"GMD";a:2:{i:0;s:3:"GMD";i:1;s:14:"Gambisk dalasi";}s:3:"GMP";a:2:{i:0;s:3:"GMP";i:1;s:12:"Gambisk pund";}s:3:"GNF";a:2:{i:0;s:2:"GF";i:1;s:15:"Guineansk franc";}s:3:"GNI";a:2:{i:0;s:3:"GNI";i:1;s:27:"Guineansk franc (1960-1972)";}s:3:"GNS";a:2:{i:0;s:3:"GNS";i:1;s:14:"Guineansk syli";}s:3:"GPF";a:2:{i:0;s:3:"GPF";i:1;s:17:"Guadeloupsk franc";}s:3:"GQE";a:2:{i:0;s:3:"GQE";i:1;s:35:"Ækvatorialguineask ekwele guineana";}s:3:"GQF";a:2:{i:0;s:3:"GQF";i:1;s:26:"Ækvatorialguineask franco";}s:3:"GQP";a:2:{i:0;s:3:"GQP";i:1;s:35:"Ækvatorialguineask peseta guineana";}s:3:"GRD";a:2:{i:0;s:3:"GRD";i:1;s:14:"Græsk drachma";}s:3:"GRN";a:2:{i:0;s:3:"GRN";i:1;s:17:"Ny græsk drachma";}s:3:"GTQ";a:2:{i:0;s:1:"Q";i:1;s:20:"Guatemalansk quetzal";}s:3:"GUF";a:2:{i:0;s:3:"GUF";i:1;s:27:"Fransk-guyansk franc guiana";}s:3:"GWE";a:2:{i:0;s:3:"GWE";i:1;s:25:"Portugisisk guinea escudo";}s:3:"GWM";a:2:{i:0;s:3:"GWM";i:1;s:27:"Portugisisk guinea mil reis";}s:3:"GWP";a:2:{i:0;s:3:"GWP";i:1;s:14:"Guineansk peso";}s:3:"GYD";a:2:{i:0;s:2:"G$";i:1;s:14:"Guyansk dollar";}s:3:"HNL";a:2:{i:0;s:1:"L";i:1;s:18:"Honduransk lempira";}s:3:"HRD";a:2:{i:0;s:3:"HRD";i:1;s:14:"Kroatisk dinar";}s:3:"HRK";a:2:{i:0;s:3:"HRK";i:1;s:13:"Kroatisk kuna";}s:3:"HTG";a:2:{i:0;s:3:"HTG";i:1;s:14:"Haitisk gourde";}s:3:"HUF";a:2:{i:0;s:2:"Ft";i:1;s:14:"Ungarsk forint";}s:3:"IBP";a:2:{i:0;s:3:"IBP";i:1;s:13:"Nordirsk pund";}s:3:"IDG";a:2:{i:0;s:3:"IDG";i:1;s:23:"Indonesisk nica guilder";}s:3:"IDJ";a:2:{i:0;s:3:"IDJ";i:1;s:22:"Indonesisk java rupiah";}s:3:"IDN";a:2:{i:0;s:3:"IDN";i:1;s:20:"Ny indonesisk rupiah";}s:3:"IDR";a:2:{i:0;s:2:"Rp";i:1;s:17:"Indonesisk pupiah";}s:3:"IEP";a:2:{i:0;s:4:"IR£";i:1;s:9:"Irsk pund";}s:3:"ILL";a:2:{i:0;s:3:"ILL";i:1;s:15:"Israelsk shekel";}s:3:"ILP";a:2:{i:0;s:3:"ILP";i:1;s:13:"Israelsk pund";}s:3:"ILS";a:2:{i:0;s:3:"ILS";i:1;s:18:"Ny israelsk shekel";}s:3:"INR";a:2:{i:0;s:18:"=0#Rs.|1#Re.|1
+ * The latest version of PRADO can be obtained from:
+ * {@link http://prado.sourceforge.net/}
+ *
+ * @author Wei Zhuo
+ * @version $Revision: 1.3 $ $Date: 2005/08/27 03:21:12 $
+ * @package System.I18N.core
+ */
+
+
+ /**
+ * For a given DSN (database connection string), return some information
+ * about the DSN. This function comes from PEAR's DB package.
+ * @param string DSN format, similar to PEAR's DB
+ * @return array DSN information.
+ */
+ function parseDSN($dsn)
+ {
+ if (is_array($dsn)) {
+ return $dsn;
+ }
+
+ $parsed = array(
+ 'phptype' => false,
+ 'dbsyntax' => false,
+ 'username' => false,
+ 'password' => false,
+ 'protocol' => false,
+ 'hostspec' => false,
+ 'port' => false,
+ 'socket' => false,
+ 'database' => false
+ );
+
+ // Find phptype and dbsyntax
+ if (($pos = strpos($dsn, '://')) !== false) {
+ $str = substr($dsn, 0, $pos);
+ $dsn = substr($dsn, $pos + 3);
+ } else {
+ $str = $dsn;
+ $dsn = NULL;
+ }
+
+ // Get phptype and dbsyntax
+ // $str => phptype(dbsyntax)
+ if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
+ $parsed['phptype'] = $arr[1];
+ $parsed['dbsyntax'] = (empty($arr[2])) ? $arr[1] : $arr[2];
+ } else {
+ $parsed['phptype'] = $str;
+ $parsed['dbsyntax'] = $str;
+ }
+
+ if (empty($dsn)) {
+ return $parsed;
+ }
+
+ // Get (if found): username and password
+ // $dsn => username:password@protocol+hostspec/database
+ if (($at = strrpos($dsn,'@')) !== false) {
+ $str = substr($dsn, 0, $at);
+ $dsn = substr($dsn, $at + 1);
+ if (($pos = strpos($str, ':')) !== false) {
+ $parsed['username'] = rawurldecode(substr($str, 0, $pos));
+ $parsed['password'] = rawurldecode(substr($str, $pos + 1));
+ } else {
+ $parsed['username'] = rawurldecode($str);
+ }
+ }
+
+ // Find protocol and hostspec
+
+ // $dsn => proto(proto_opts)/database
+ if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
+ $proto = $match[1];
+ $proto_opts = (!empty($match[2])) ? $match[2] : false;
+ $dsn = $match[3];
+
+ // $dsn => protocol+hostspec/database (old format)
+ } else {
+ if (strpos($dsn, '+') !== false) {
+ list($proto, $dsn) = explode('+', $dsn, 2);
+ }
+ if (strpos($dsn, '/') !== false) {
+ list($proto_opts, $dsn) = explode('/', $dsn, 2);
+ } else {
+ $proto_opts = $dsn;
+ $dsn = null;
+ }
+ }
+
+ // process the different protocol options
+ $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
+ $proto_opts = rawurldecode($proto_opts);
+ if ($parsed['protocol'] == 'tcp') {
+ if (strpos($proto_opts, ':') !== false) {
+ list($parsed['hostspec'], $parsed['port']) = explode(':', $proto_opts);
+ } else {
+ $parsed['hostspec'] = $proto_opts;
+ }
+ } elseif ($parsed['protocol'] == 'unix') {
+ $parsed['socket'] = $proto_opts;
+ }
+
+ // Get dabase if any
+ // $dsn => database
+ if (!empty($dsn)) {
+ // /database
+ if (($pos = strpos($dsn, '?')) === false) {
+ $parsed['database'] = $dsn;
+ // /database?param1=value1¶m2=value2
+ } else {
+ $parsed['database'] = substr($dsn, 0, $pos);
+ $dsn = substr($dsn, $pos + 1);
+ if (strpos($dsn, '&') !== false) {
+ $opts = explode('&', $dsn);
+ } else { // database?param1=value1
+ $opts = array($dsn);
+ }
+ foreach ($opts as $opt) {
+ list($key, $value) = explode('=', $opt);
+ if (!isset($parsed[$key])) { // don't allow params overwrite
+ $parsed[$key] = rawurldecode($value);
+ }
+ }
+ }
+ }
+
+ return $parsed;
+ }
+
+
+ /**
+ * Convert strings to UTF-8 via iconv. NB, the result may not by UTF-8
+ * if the conversion failed.
+ * @param string string to convert to UTF-8
+ * @return string UTF-8 encoded string, original string if iconv failed.
+ */
+ function I18N_toUTF8($string, $from)
+ {
+ if($from != 'UTF-8')
+ {
+ $s = iconv($from,'UTF-8',$string); //to UTF-8
+ return $s !== false ? $s : $string; //it could return false
+ }
+ return $string;
+ }
+
+ /**
+ * Convert UTF-8 strings to a different encoding. NB. The result
+ * may not have been encoded if iconv fails.
+ * @param string the UTF-8 string for conversion
+ * @return string encoded string.
+ */
+ function I18N_toEncoding($string, $to)
+ {
+ if($to != 'UTF-8')
+ {
+ $s = iconv('UTF-8', $to, $string);
+ return $s !== false ? $s : $string;
+ }
+ return $string;
+ }
+
+?>
\ No newline at end of file
diff --git a/framework/I18N/schema/mysql.sql b/framework/I18N/schema/mysql.sql
new file mode 100644
index 00000000..55b0fd2b
--- /dev/null
+++ b/framework/I18N/schema/mysql.sql
@@ -0,0 +1,58 @@
+#
+# Database : `messages` for I18N in PRADO
+#
+
+# --------------------------------------------------------
+
+#
+# Table structure for table `catalogue`
+#
+
+CREATE TABLE `catalogue` (
+ `cat_id` int(11) NOT NULL auto_increment,
+ `name` varchar(100) NOT NULL default '',
+ `source_lang` varchar(100) NOT NULL default '',
+ `target_lang` varchar(100) NOT NULL default '',
+ `date_created` int(11) NOT NULL default '0',
+ `date_modified` int(11) NOT NULL default '0',
+ `author` varchar(255) NOT NULL default '',
+ PRIMARY KEY (`cat_id`)
+) TYPE=MyISAM AUTO_INCREMENT=4 ;
+
+#
+# Dumping data for table `catalogue`
+#
+
+INSERT INTO `catalogue` VALUES (1, 'messages', '', '', 0, 0, '');
+INSERT INTO `catalogue` VALUES (2, 'messages.en', '', '', 0, 0, '');
+INSERT INTO `catalogue` VALUES (3, 'messages.en_AU', '', '', 0, 0, '');
+
+# --------------------------------------------------------
+
+#
+# Table structure for table `trans_unit`
+#
+
+CREATE TABLE `trans_unit` (
+ `msg_id` int(11) NOT NULL auto_increment,
+ `cat_id` int(11) NOT NULL default '1',
+ `id` varchar(255) NOT NULL default '',
+ `source` text NOT NULL,
+ `target` text NOT NULL,
+ `comments` text NOT NULL,
+ `date_added` int(11) NOT NULL default '0',
+ `date_modified` int(11) NOT NULL default '0',
+ `author` varchar(255) NOT NULL default '',
+ `translated` tinyint(1) NOT NULL default '0',
+ PRIMARY KEY (`msg_id`)
+) TYPE=MyISAM AUTO_INCREMENT=6 ;
+
+#
+# Dumping data for table `trans_unit`
+#
+
+INSERT INTO `trans_unit` VALUES (1, 1, '1', 'Hello', 'Hello World', '', 0, 0, '', 1);
+INSERT INTO `trans_unit` VALUES (2, 2, '', 'Hello', 'Hello :)', '', 0, 0, '', 0);
+INSERT INTO `trans_unit` VALUES (3, 1, '1', 'Welcome', 'Welcome', '', 0, 0, '', 0);
+INSERT INTO `trans_unit` VALUES (4, 3, '', 'Hello', 'G\'day Mate!', '', 0, 0, '', 0);
+INSERT INTO `trans_unit` VALUES (5, 3, '', 'Welcome', 'Welcome Mate!', '', 0, 0, '', 0);
\ No newline at end of file
diff --git a/framework/I18N/schema/sqlite.sql b/framework/I18N/schema/sqlite.sql
new file mode 100644
index 00000000..68d15d4d
--- /dev/null
+++ b/framework/I18N/schema/sqlite.sql
@@ -0,0 +1,49 @@
+# Database: messages.db for I18N in PRADO
+# --------------------------------------------------------
+
+#
+# Table structure for table: catalogue
+#
+CREATE TABLE catalogue (
+ cat_id INTEGER PRIMARY KEY,
+ name VARCHAR NOT NULL,
+ source_lang VARCHAR ,
+ target_lang VARCHAR ,
+ date_created INT,
+ date_modified INT,
+ author VARCHAR );
+
+#
+# Dumping data for table: catalogue
+#
+INSERT INTO catalogue VALUES ('1', 'messages', '', '', '', '', '');
+INSERT INTO catalogue VALUES ('2', 'messages.en', '', '', '', '', '');
+INSERT INTO catalogue VALUES ('3', 'messages.en_AU', '', '', '', '', '');
+# --------------------------------------------------------
+
+
+#
+# Table structure for table: trans_unit
+#
+CREATE TABLE trans_unit (
+ msg_id INTEGER PRIMARY KEY,
+ cat_id INTEGER NOT NULL DEFAULT '1',
+ id VARCHAR,
+ source TEXT,
+ target TEXT,
+ comments TEXT,
+ date_added INT,
+ date_modified INT,
+ author VARCHAR,
+ translated INT(1) NOT NULL DEFAULT '0' );
+
+#
+# Dumping data for table: trans_unit
+#
+INSERT INTO trans_unit VALUES ('1', '1', '1', 'Hello', 'Hello World', '', '', '', '', '1');
+INSERT INTO trans_unit VALUES ('2', '2', '', 'Hello', 'Hello :)', '', '', '', '', '0');
+INSERT INTO trans_unit VALUES ('3', '1', '1', 'Welcome', 'Welcome', '', '', '', '', '0');
+INSERT INTO trans_unit VALUES ('4', '3', '', 'Hello', 'G''day Mate!', '', '', '', '', '0');
+INSERT INTO trans_unit VALUES ('5', '3', '', 'Welcome', 'Welcome Mate!', '', '', '', '', '0');
+# --------------------------------------------------------
+
diff --git a/framework/TApplication.php b/framework/TApplication.php
index eb53653b..4d773d7b 100644
--- a/framework/TApplication.php
+++ b/framework/TApplication.php
@@ -239,6 +239,12 @@ class TApplication extends TComponent
* @var IUser user instance, could be null
*/
private $_user=null;
+
+ /**
+ * @var TGlobalization module, could be null
+ */
+ private $_globalization=null;
+
/**
* @var TAuthorizationRuleCollection collection of authorization rules
*/
@@ -662,6 +668,16 @@ class TApplication extends TComponent
$this->_user=$user;
}
+ public function getGlobalization()
+ {
+ return $this->_globalization;
+ }
+
+ public function setGlobalization(TGlobalization $handler)
+ {
+ $this->_globalization = $handler;
+ }
+
/**
* @return TAuthorizationRuleCollection list of authorization rules for the current request
*/
diff --git a/framework/Web/UI/TTemplateManager.php b/framework/Web/UI/TTemplateManager.php
index cb44b81d..d5c5f0ba 100644
--- a/framework/Web/UI/TTemplateManager.php
+++ b/framework/Web/UI/TTemplateManager.php
@@ -70,7 +70,7 @@ class TTemplateManager extends TModule
*/
public function getTemplateByFileName($fileName)
{
- if(($fileName=realpath($fileName))!==false && is_file($fileName))
+ if(!is_null($fileName=$this->getLocalizedTemplate($fileName)))
{
if(($cache=$this->getApplication()->getCache())===null)
return new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName);
@@ -91,6 +91,22 @@ class TTemplateManager extends TModule
else
return null;
}
+
+ /**
+ * Finds a localized template file.
+ * @param string template file.
+ * @return string|null a localized template file if found, null otherwise.
+ */
+ protected function getLocalizedTemplate($filename)
+ {
+ $app = $this->getApplication()->getGlobalization();
+ if(is_null($app)) return $filename;
+ foreach($app->getLocalizedResource($filename) as $file)
+ {
+ if(($file=realpath($file))!==false && is_file($file))
+ return $file;
+ }
+ }
}
/**
--
cgit v1.2.3