From: konrad Date: Tue, 6 Jul 2010 20:09:34 +0000 (+0000) Subject: add draft of format support to server side X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=c3a765ce9ff77ae1f313aa859b2fff8d6ab02cd6;p=web%2Fkonrad%2Fsmoke.git add draft of format support to server side add draft of timezone support to client side git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@533 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- diff --git a/src/misc/misc.cpp b/src/misc/misc.cpp index f3a3077..65551cc 100644 --- a/src/misc/misc.cpp +++ b/src/misc/misc.cpp @@ -90,9 +90,10 @@ QString unix2dateTime(qint64 tm,bool localize) return mf.formatDateTime(tm); } +//static +MLocalFormat MLocalFormat::defaultformat((int)1); - -MLocalFormat::MLocalFormat() +MLocalFormat::MLocalFormat(int) { m_moneydecimals=2; m_thousanddigits=3; @@ -102,6 +103,35 @@ MLocalFormat::MLocalFormat() setMoneyFormat();setNumberFormat(); } +MLocalFormat::MLocalFormat(const MOServerFormat& s) +{ + //init from current default + operator=(defaultformat); + //overwrite with new settings + QStringList sl; + sl=s.weekdays();if(sl.size())setWeekDays(sl); + sl=s.shortweekdays();if(sl.size())setShortWeekDays(sl); + sl=s.months();if(sl.size())setMonths(sl); + sl=s.shortmonths();if(sl.size())setShortMonths(sl); + setMoneyFormat(s.currencysymbol(),s.moneydecimals(),s.moneynegative()); + setNumberFormat(s.decimaldot().value().at(0),s.thousandseparator().value().at(0),s.thousanddigits().value()); + setAP(s.amtext(),s.pmtext()); +} + + +//static +void MLocalFormat::setDefaultFormat(const MLocalFormat& f) +{ + defaultformat=f; +} + + +MLocalFormat::MLocalFormat() +{ + operator=(defaultformat); +} + + MLocalFormat::MLocalFormat(const MLocalFormat&f) { operator=(f); @@ -586,3 +616,14 @@ QRegExp MLocalFormat::moneyRegExp(bool allownegative,bool allowcurrency)const //return return QRegExp(r); } + +qint64 MLocalFormat::localTime2unix(QDateTime ) const +{ +//TODO!! +} + +void MLocalFormat::setTimeZone(QString olsenname, QList< MOTimeTransition > transitions) +{ +//TODO!! +} + diff --git a/src/misc/misc.h b/src/misc/misc.h index 01706cd..b7a7b41 100644 --- a/src/misc/misc.h +++ b/src/misc/misc.h @@ -18,6 +18,8 @@ #include #include +#include "MOServerFormat.h" + /**converts special HTML characters into harmless &-codes, so the text can be included*/ QString htmlize(QString str); @@ -83,13 +85,18 @@ For example "%w the %d'th of %N in the year of the lord %Y at %a:%I %P" will be class MLocalFormat { public: - /**constructs a formatter object*/ + /**constructs a formatter object that corresponds to the default*/ MLocalFormat(); /**copies a formatter object inheriting its overrides*/ MLocalFormat(const MLocalFormat&); + /**initializes the formatter object from a server format object*/ + MLocalFormat(const MOServerFormat&); /**deletes the formatter object*/ virtual ~MLocalFormat(); + /**sets a new default format*/ + static void setDefaultFormat(const MLocalFormat&); + /**copies a formatter object*/ virtual MLocalFormat& operator=(const MLocalFormat&); @@ -118,11 +125,16 @@ class MLocalFormat /**overrides the formatting of the AM/PM part of time display, resets to the localization if none given*/ virtual void setAP(QString am="--",QString pm="--"); + /**overrides the local time zone + \param olsenname the name of the local timezone in olsen notation, eg. "Europe/Berlin" + \param transitions a list of time transitions, if missing the system attempts to locate the transition DB itself*/ + virtual void setTimeZone(QString olsenname,QList transitions=QList()); + /**overrides the formatting to be non-localized, numbers use decimal dot and no thousand separator, no currency symbol and "-" as negative sign; otherwise things stay the same; this is a helper for the shortcut methods like cent2str*/ virtual void setNonLocalized(); /**formats a date according to the given format, if none is given, the translation default is used - \param date a QDate used as input + \param date a QDate used as input, it is assumed to be local, even if Qt sais it is UTC \param format a format string as specified by QDate::toString */ virtual QString formatDate(const QDate&date,QString format=QString())const; /**formats a date according to the given format, if none is given, the translation default is used @@ -214,6 +226,14 @@ class MLocalFormat /** \internal helper to convert a unix timestamp to local time*/ virtual QDateTime unix2localTime(qint64)const; + + /** \internal helper to convert a local timestamp to unix time*/ + virtual qint64 localTime2unix(QDateTime)const; + + /** \internal constructs the default object from the translation*/ + MLocalFormat(int); + /** \internal default format*/ + static MLocalFormat defaultformat; }; #endif diff --git a/wob/classes/basics.wolf b/wob/classes/basics.wolf index 76b2bfc..35a2826 100644 --- a/wob/classes/basics.wolf +++ b/wob/classes/basics.wolf @@ -13,4 +13,34 @@ + + + Helper class: encapsulates a single transition between UTC-offsets for a timezone. This is based on the Olsen TZ database and used by ServerFormat. + The Unix timestamp (seconds since Epoch) at which the transition occurs. + Offset in seconds from UTC (positive is east). + The abbreviated name of the timezone during this period + true if this is a daylight saving time + + + + Transport class for server formatting settings. This is used by both UIs to format numbers, dates, money, etc. The XML version of it is stored in the template directory, distributed between main and language dependent directory. + + The list of week day names, starting with monday + The list of abbreviated week day names, starting with monday + The list of month names + The list of abbreviated month names + The default format for dates, see the docu of MLocalFormat (Qt side) and LanguageManager (PHP side) for details. + The default format for time. + The default format for date and time. + The text for AM in time stamps + The text for PM in time stamps + The decimal dot for numbers + The thousand separator for numbers, if it is a space the Web UI will actually use &nbsp; to prevent breaking the number. + The amount of digits between thousand separators, 0 for no thousand separator + The amount of decimals for money values - this must be the same for all languages on a server, the default is 2 + The currency used + One or two characters: for negative money values the first one is placed in front of the money value and the second one behind the money value + Olsen database time zone name + list of all precalculated transitions in this timezone, how far into the future calculations go depends on the server, usually at the moment till 2037 + diff --git a/wob/transact/basics.wolf b/wob/transact/basics.wolf index c8eae21..128fe6f 100644 --- a/wob/transact/basics.wolf +++ b/wob/transact/basics.wolf @@ -19,12 +19,13 @@ This transaction returns basic language and formatting settings from the server - it must be used before the client displays any times or monetary values, even if it does not indend to translate any strings. - The language that the client wants to use, use "C" for no translation. + The language that the client wants to use, use "C" for no translation wanted. The translation file format that the client supports: either "ts" for Qt translation XML source files, or "qm" for translated binary Qt translation files. The Qt translation file to translate string from the server. All strings are found in the virtual class "::php". + The formatting as requested by the server. Please note that the names of days and months does not necessarily correspond to the language that has been request but, to the language that the server wants to set for all printouts. diff --git a/www/inc/classes/language_manager.php b/www/inc/classes/language_manager.php index 3474172..7bb12e9 100644 --- a/www/inc/classes/language_manager.php +++ b/www/inc/classes/language_manager.php @@ -44,6 +44,7 @@ class LanguageManager private $lang="C";//fallback for unknown language, constructor overrides it private $config; private $templateFolder; + private $formatcfg; /** private constructor */ private function __construct() @@ -85,6 +86,8 @@ class LanguageManager $this->lang=$l; break; } + //initialize internal formatting + $this->formatcfg=new WOServerFormat($this->lang); //make sure config manager is initialized $this->config = ConfigManager::initialize($this->templateFolder()."lang.po"); } @@ -105,6 +108,12 @@ class LanguageManager return $this->templateFolder.$this->lang."/"; } + /**returns a date in current language formatted to the given format string*/ + public function formatDate($date,$str) + { + $ret=""; + } + /** returns date in current language, default: ISO-date */ public function getDate($date) { @@ -142,6 +151,7 @@ class LanguageManager $d=dir($template); $r=array(); while(false !== ($e=$d->read())){ + if(!is_dir($template."/".$e))continue; if(preg_match('/^[a-z]+$/',$e)>0 && $e!="C") $r[]=$e; } diff --git a/www/inc/machine/translation.php b/www/inc/machine/translation.php index f9b808c..53545bc 100644 --- a/www/inc/machine/translation.php +++ b/www/inc/machine/translation.php @@ -15,13 +15,25 @@ class Translation { static public function getFile($trans) { - $nlst=explode("_",trim($trans->getlanguage())); - $form=$trans->getformat(); - if($form!="ts" && $form!="qm") - $trans->abortWithError(translate("Translation","Format must be either 'ts' or 'qm'.")); + //split language string into components + $nlst=explode("_",trim($trans->getlanguage())); + //set format object + if(count($nlst)>0) + $trans->setformats(new ServerFormat($nlst[0])); + else + $trans->setformats(new ServerFormat(); + //if this is "C", abort parsing and return + if(strtolower(trim($trans->getlanguage()))=="c") + return; + //continue to parse language request + $form=$trans->getformat(); + if($form!="ts" && $form!="qm") + $trans->abortWithError(translate("Translation","Format must be either 'ts' or 'qm'.")); + //does the syntax match? foreach($nlst as $nm) if(!ereg("^[a-zA-Z]{1,3}$",$nm)) $trans->abortWithError(translate("Translation","Language invalid.")); + //find the longest match for language for($i=count($nlst);$i>0;$i--){ $name=implode("_",array_slice($nlst,0,$i)); $fn="translations/_server_".$name.".".$form; @@ -30,6 +42,7 @@ class Translation return; } } + //none found. sadly. $trans->abortWithError(translate("Translation","Language unknown.")); } }; diff --git a/www/inc/rendering/twig_extensions.php b/www/inc/rendering/twig_extensions.php index acfb95f..2c7a352 100644 --- a/www/inc/rendering/twig_extensions.php +++ b/www/inc/rendering/twig_extensions.php @@ -23,6 +23,7 @@ class LangFilterExtension extends Twig_Extension 'asDate' => new Twig_Filter_Method($this, 'getDate'), 'asTime' => new Twig_Filter_Method($this, 'getTime'), 'asDateTime' => new Twig_Filter_Method($this, 'getDateTime'), + 'formatDate' => new Twig_Filter_Method($this, 'formatDate'), ); } diff --git a/www/inc/wext/autoload.php b/www/inc/wext/autoload.php index 06ddfee..78d9250 100644 --- a/www/inc/wext/autoload.php +++ b/www/inc/wext/autoload.php @@ -22,6 +22,7 @@ wob_autoclass("WOOrderInfo","inc/wext/order.php"); wob_autoclass("WOPriceCategory","inc/wext/price.php"); wob_autoclass("WORole","inc/wext/role.php"); wob_autoclass("WORoom","inc/wext/room.php"); +wob_autoclass("WOServerFormat","inc/wext/format.php"); wob_autoclass("WOShipping","inc/wext/shipping.php"); wob_autoclass("WOTemplate","inc/wext/template.php"); wob_autoclass("WOTicket","inc/wext/ticket.php"); diff --git a/www/inc/wext/format.php b/www/inc/wext/format.php new file mode 100644 index 0000000..092cd56 --- /dev/null +++ b/www/inc/wext/format.php @@ -0,0 +1,83 @@ + +// +---------------------------------------------------------------------- +// | +// | Copyright: See COPYING.AGPL file that comes with this distribution +// +---------------------------------------------------------------------- +// + +/**this class extends the definition of the Wob class ServerFormat, to actually do something. +It is used on the other side by the client to configure LocalFormat and by the Web UI to configure LanguageManager.*/ +class WOServerFormat extends WOServerFormatAbstract +{ + /**constructs the format object for a specific language*/ + public function __construct($lang="") + { + parent::__construct(); + global $template; + $this->loadConfig($template."/format.cfg"); + if($lang!="") + $this->loadConfig($template."/".$lang."/format.cfg"); + } + + /**load a configuration file and amend internal state by its definitions*/ + public function loadConfig($file) + { + //ignore if fiel not found + if(!file_exists($file))return; + //read file + $lines=file($file); + foreach($lines as $num=>$ln){ + //trim line and remove comments + $ln=trim($ln); + if($ln=="")continue; + if(substr($ln,0,1)=="#")continue; + //parse + $match=array(); + if(preg_match("/^([a-zA-Z]+) \"(.*)\"$/",$ln,$match)<=0) + die("Syntax error in format config $file line ".($num+1)); + $cmd=strtolower($match[1]); + $val=stripcslashes($match[2]); + switch($cmd){ + case "weekdays":$this->setweekdays(explode(" ",$val));break; + case "shortweekdays":$this->setshortweekdays(explode(" ",$val));break; + case "months":$this->setmonths(explode(" ",$val));break; + case "shortmonths":$this->setshortmonths(explode(" ",$val));break; + case "date":$this->setdateformat($val);break; + case "time":$this->settimeformat($val);break; + case "datetime":$this->setdatetimeformat($val);break; + case "amtext":$this->setamtext($val);break; + case "pmtext":$this->setpmtext($val);break; + case "decimaldot":$this->setdecimaldot($val);break; + case "thousandseparator":$this->setthousandseparator($val);break; + case "thousanddigits":$this->setthousanddigits($val);break; + case "moneydecimals":$this->setmoneydecimals($val);break; + case "currencysymbol":$this->setcurrencysymbol($val);break; + case "moneynegative":$this->setmoneynegative($val);break; + case "timezone":$this->settimezone($val);$this->loadtimezone();break; + default: die("Unknown keyword in format config $file line ".($num+1));break; + } + } + } + + /** \internal helper for loadConfig to initialize timezone transitions*/ + protected function loadtimezone() + { + $dtz=new DateTimeZone($this->prop_timezone); + $tr=array(); + foreach($dtz->getTransitions() as $tran){ + $t=new WOTimeTransition; + $t->setts($tran["ts"]); + $t->setoffset($tran["offset"]); + $t->setabbr($tran["abbr"]); + $t->setisdst($tran["isdst"]); + $tr[]=$t; + } + $this->prop_TZtransitions=$tr; + } +} + +?> \ No newline at end of file diff --git a/www/template/en/format.cfg b/www/template/en/format.cfg new file mode 100644 index 0000000..41bf54d --- /dev/null +++ b/www/template/en/format.cfg @@ -0,0 +1,34 @@ +# This is the local Formatting Configuration for the English language +# it sets new defaults for the properties that are different in English +# +# see ../format.cfg for syntax help + +#Names of the days of the week, long and abbreviated, +# start with monday and must be exactly 7 entries long +WeekDays "Monday Tuesday Wednesday Thursday Friday Saturday Sunday" +ShortWeekDays "Mon Tue Wed Thu Fri Sat Sun" + +#Names of the months, long and abbreviated, the list must be 12 long +Months "January February March April May June July August September October November December" +ShortMonths "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec" + +#The format used for the time of day: +time "%a:%I %P" + +#The format used for expressing a date: +date "%M/%D/%Y" + +#The format used when full date and time display is requested, +datetime "%M/%D/%Y %a:%I %P" + +#the text used for AM and PM in time displays that include them +# use the uppercase version here, lowercase is done automatically +# by translating all latters to lower case +AMtext "AM" +PMtext "PM" + +#The characters used for decimal dot and thousand separator on numbers +#The thousanddigits value tells us how many digits are between separators +decimaldot "." +thousandseparator "," +thousanddigits "3" diff --git a/www/template/format.cfg b/www/template/format.cfg new file mode 100644 index 0000000..fb099f1 --- /dev/null +++ b/www/template/format.cfg @@ -0,0 +1,95 @@ +# This is the global Formatting Configuration +# it sets defaults for all formatting properties +# +# The files in the language folders only override those +# properties which are language specific. +# +# the syntax is rather simple: +# empty lines and lines starting with # are ignored; +# leading and trailing spaces are ignored; +# all other lines have the format 'keyword "value"'; +# the keyword matching is case insensitive, the case of values is preserved; +# you see all allowed keywords below; +# if the parser finds something it cannot interpret it will abort the script and tell you + +#Names of the days of the week, long and abbreviated, +# start with monday and must be exactly 7 entries long +WeekDays "Monday Tuesday Wednesday Thursday Friday Saturday Sunday" +ShortWeekDays "Mon Tue Wed Thu Fri Sat Sun" + +#Names of the months, long and abbreviated, the list must be 12 long +Months "January February March April May June July August September October November December" +ShortMonths "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec" + +#The format used for the time of day: +# %h hour as simple number (eg. 7) in 24-hour format +# %H hour as two digit number (eg. 07) in 24-hour format +# %a hour as simple number (eg. 7) in 12-hour format +# %A hour as two digit number (eg. 07) in 12-hour format +# %i minute as simple number (eg. 7) +# %I minute as two digit number (eg. 07) +# %s second as simple number (eg. 7) +# %S second as two digit number (eg. 07) +# %z milli-seconds as simple number (eg. 7) +# %Z milli-seconds as three digit number (eg. 007) +# %p "am" or "pm" according to current time, this is the one set with setAP +# %P "AM" or "PM" according to current time, this is toUpper executed on the one set with setAP +# %T ISO timezone as +/-hhmm (eg. -0100 or +0100) - does not work reliably on all systems +# %% a single % sign +time "%h:%I" + +#The format used for expressing a date: +# %y two-digit year (eg. 08) +# %Y four-digit year (eg. 1908) +# %m month as simple number (eg. 7) +# %M month as two digit number (eg. 07) +# %n short name of the month (eg. Jul) +# %N long name of the month (eg. July) +# %d day of the month as simple number (eg. 5) +# %D day of the month as two digit number (eg. 05) +# %w day of the week as short name (eg. Wed) +# %W day of the week as long name (eg. Wednesday) +# %% a single % sign +date "%Y-%M-%D" + +#The format used when full date and time display is requested, +# see date and time above for the format codes +datetime "%Y-%M-%D %h:%I" + +#the text used for AM and PM in time displays that include them +# use the uppercase version here, lowercase is done automatically +# by translating all latters to lower case +AMtext "AM" +PMtext "PM" + +#The characters used for decimal dot and thousand separator on numbers +#The thousanddigits value tells us how many digits are between separators +# if it is 0 or less, no separator is used. +decimaldot "." +thousandseparator "," +thousanddigits "0" + +#Currency settings: + +# moneydecimals tells us how many digits of money values are cents +# THIS VALUE MUST NOT BE CHANGED IN SEPARATE LANGUAGES +# money values are stored as integers in cents, if the number of digits +# changes the actual monetary value expressed by a stored int value changes! +moneydecimals "2" + +# currencysymbol: the currency used by this server +# If you change this value in a translation, make sure it still reflects the +# same currency, otherwise your customers might be surprised if the Web UI shows +# amounts in US$, but they are billed in Euro. +currencysymbol "Euro" + +# the negative notation of money, it has one or two characters: +# character 1: the character placed in front of the number, or \n for none +# character 2: the character placed between number and currency symbol +moneynegative "-" + +#Time Zone in Olsen DB notation +# THIS VALUE SHOULD NOT BE CHANGED IN LANGUAGE FOLDERS +# a change of this value directs MagicSmoke to show times for different time zonez +# this value should be set to the zone where the theater is located +timezone "Europe/Berlin"