From 4835704a04cf5aa5ec71a8aef902d54b9c6cae82 Mon Sep 17 00:00:00 2001
From: wei <>
Date: Fri, 6 Jan 2006 04:42:44 +0000
Subject: Adding I18N support.
---
framework/I18N/core/ChoiceFormat.php | 186 +++++++++++++++++++++++++++++++++++
1 file changed, 186 insertions(+)
create mode 100644 framework/I18N/core/ChoiceFormat.php
(limited to 'framework/I18N/core/ChoiceFormat.php')
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
--
cgit v1.2.3