From b7a883778d4c6df9a300ef0d762aca245dc4a898 Mon Sep 17 00:00:00 2001 From: Stan Ozier Date: Fri, 11 Jun 2010 12:42:24 +0200 Subject: [PATCH] version 0.4 (3) added multi language support added french translation added non apache (mod_rewrite) support (needs testing) improved UI by adding more icons improved user menu (drop down menu) fixed date shortcut on quick task entry fixed changing password bug fixed logging with password bug other minor bug fixes --- .htaccess => DOCS/htaccess | 0 DOCS/readme.txt | 33 ++-- DOCS/release.txt | 17 ++ DOCS/taskfreak_timer.sql | 94 ++--------- DOCS/translation.txt | 46 +++++ README | 4 +- app/config/app.php | 45 +++-- app/config/core.php | 27 +-- app/config/path.php | 5 + app/controller/admin.php | 39 +++-- app/controller/login.php | 2 +- app/controller/task.php | 65 +++++--- app/controller/timer.php | 10 +- app/lang/en/freak.php | 120 +++++++++++++ app/lang/en/help_multi_creation.php | 19 +++ app/lang/en/help_timer_creation.php | 8 + app/lang/fr/freak.php | 120 +++++++++++++ app/lang/fr/help_multi_creation.php | 19 +++ app/lang/fr/help_timer_creation.php | 8 + app/model/member.php | 6 +- app/model/task.php | 17 +- app/view/admin/switch.php | 4 +- app/view/admin/user-edit.php | 28 ++-- app/view/admin/user-list.php | 13 +- app/view/create.php | 24 +-- app/view/edit.php | 18 +- app/view/include/list-compact.php | 33 ++-- app/view/include/list-expand.php | 31 ++-- app/view/include/page-top.php | 16 +- app/view/include/timer-form.php | 25 ++- app/view/include/timer-list.php | 14 +- app/view/include/timer.php | 14 +- app/view/login/login.php | 12 +- app/view/main.php | 24 ++- app/view/view.php | 14 +- asset/js/freak.js | 43 ++++- asset/lang/en/config.php | 10 -- asset/lang/en/core.php | 0 asset/lang/en/freak.php | 0 lib/class/front.php | 5 +- lib/class/model.php | 34 ++-- lib/helper/auth.php | 58 +++---- lib/helper/html_form.php | 27 ++- lib/helper/translator.php | 107 +++++++++--- lib/lang/en/common.php | 250 ++++++++++++++++++++++++++++ lib/lang/en/config.php | 15 ++ lib/lang/fr/common.php | 250 ++++++++++++++++++++++++++++ lib/lang/fr/config.php | 15 ++ lib/model/user.php | 57 ++++--- skin/default/css/freak.css | 75 ++++++--- skin/default/css/tracker.css | 36 +++- skin/default/img/buttons.png | Bin 0 -> 2641 bytes 52 files changed, 1492 insertions(+), 464 deletions(-) rename .htaccess => DOCS/htaccess (100%) create mode 100644 DOCS/translation.txt create mode 100644 app/lang/en/freak.php create mode 100644 app/lang/en/help_multi_creation.php create mode 100644 app/lang/en/help_timer_creation.php create mode 100644 app/lang/fr/freak.php create mode 100644 app/lang/fr/help_multi_creation.php create mode 100644 app/lang/fr/help_timer_creation.php delete mode 100644 asset/lang/en/config.php delete mode 100644 asset/lang/en/core.php delete mode 100644 asset/lang/en/freak.php create mode 100644 lib/lang/en/common.php create mode 100644 lib/lang/en/config.php create mode 100644 lib/lang/fr/common.php create mode 100644 lib/lang/fr/config.php create mode 100644 skin/default/img/buttons.png diff --git a/.htaccess b/DOCS/htaccess similarity index 100% rename from .htaccess rename to DOCS/htaccess diff --git a/DOCS/readme.txt b/DOCS/readme.txt index a93519f..72b76c0 100644 --- a/DOCS/readme.txt +++ b/DOCS/readme.txt @@ -1,29 +1,32 @@ +TaskFreak! Time Tracking +------------------------ +version : 0.4 + + Requirements ------------ -- apache with mod_rewrite +- apache (tested) or any other webserver (not tested) - PHP 5.3.x - mySQL 4.1 or later Setup ----- -1) Set up your virtual host (read further below if using a subfolder instead) -2) create a mySQL database -3) create tables and data with taskfreak_time.sql -4) open app/config/db.php and change database settings +1) create a mySQL database +2) create tables and data with taskfreak_time.sql +3) open app/config/db.php and change database settings You can stop here and have a look. login is "admin" with no password -Subfolder setup ---------------- -If not using a virtual host, you need to change the APP_WWW_URI constant -in app/config/core.php +Enabling clean URLS +------------------- +If using apache with mod_rewrite, you should enable clean URLs -eg. if running under yourdomain.tld/taskfreak -define('APP_WWW_URI', '/taskfreak/'); -don't forget the trailing slash +1) copy the file htaccess from the DOCS folder to the application root folder +2) change its name from htaccess to .htaccess +3) open app/config/core.php, and change APP_URL_REWRITE to true Single user @@ -34,11 +37,15 @@ Search for APP_SETUP_USER_MODEL and set it up to false : define('APP_SETUP_USER_MODEL',false); [/code] +More options +------------ If you feel like playing so more, open app/config/app.php and look into it +To change the application language have a look at DOCS/translation.txt + Known bugs ---------- -- javascript calendar (jdpicker) closes when changing month or year +- some errors might occur on dates depending on your time zone - order by start, stop, or spent doesn't really make sense - very buggy under IE8, and simply unusable with older versions of IE diff --git a/DOCS/release.txt b/DOCS/release.txt index b665d64..35fd667 100644 --- a/DOCS/release.txt +++ b/DOCS/release.txt @@ -1,3 +1,20 @@ +TaskFreak! Time Tracking +------------------------ + +Version 0.4 : 2010-06-11 +------------------------ +Added multi language support +Added french translation +Added non apache (mod_rewrite) support (needs testing) +Improved UI by adding more icons +Improved user menu (drop down menu) +Fixed checkbox bug (checked tasks didn't change status) +Fixed date shortcut on quick task entry +Fixed javascript calendar bug when changing month or year +Fixed changing password bug +Fixed logging with password bug +Other minor bug fixes + Version 0.3 : 2010-05-30 ------------------------ Fixed subfolder installation (virtual host no longer required) diff --git a/DOCS/taskfreak_timer.sql b/DOCS/taskfreak_timer.sql index ec5e916..5869fe2 100644 --- a/DOCS/taskfreak_timer.sql +++ b/DOCS/taskfreak_timer.sql @@ -1,67 +1,23 @@ --- phpMyAdmin SQL Dump --- version 3.3.1 --- http://www.phpmyadmin.net --- --- Host: localhost --- Generation Time: May 30, 2010 at 04:05 PM --- Server version: 5.0.67 --- PHP Version: 5.3.0 - -SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; - --- --- Database: `taskfreak_timer` --- - --- -------------------------------------------------------- - --- --- Table structure for table `acl` --- - -DROP TABLE IF EXISTS `acl`; -CREATE TABLE `acl` ( +CREATE TABLE IF NOT EXISTS `acl` ( `id` mediumint(8) unsigned NOT NULL auto_increment, `name` varchar(127) NOT NULL, `section` varchar(63) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; - --- --- Dumping data for table `acl` --- +) ENGINE=MyISAM DEFAULT CHARSET=utf8; INSERT INTO `acl` VALUES(1, 'task_see_all', 'general'); INSERT INTO `acl` VALUES(2, 'admin_user', 'general'); --- -------------------------------------------------------- - --- --- Table structure for table `acl_user` --- - -DROP TABLE IF EXISTS `acl_user`; -CREATE TABLE `acl_user` ( +CREATE TABLE IF NOT EXISTS `acl_user` ( `user_id` mediumint(8) unsigned NOT NULL, `acl_id` mediumint(8) unsigned NOT NULL, PRIMARY KEY (`user_id`,`acl_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; --- --- Dumping data for table `acl_user` --- - INSERT INTO `acl_user` VALUES(1, 1); INSERT INTO `acl_user` VALUES(1, 2); --- -------------------------------------------------------- - --- --- Table structure for table `member` --- - -DROP TABLE IF EXISTS `member`; -CREATE TABLE `member` ( +CREATE TABLE IF NOT EXISTS `member` ( `id` int(10) unsigned NOT NULL auto_increment, `nickname` varchar(30) NOT NULL, `email` varchar(255) NOT NULL, @@ -81,23 +37,12 @@ CREATE TABLE `member` ( `activation` varchar(16) NOT NULL, `enabled` tinyint(1) unsigned NOT NULL, PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; +) ENGINE=MyISAM DEFAULT CHARSET=utf8; --- --- Dumping data for table `member` --- +INSERT INTO `member` VALUES(1, 'Administrator', '', 'admin', '', '12345678', 0, 'Asia/Bangkok', 0, '2010-06-11 01:30:00', '0000-00-00', '0000-00-00 00:00:00', '127.0.0.1', '0000-00-00 00:00:00', 0, 0, '', 1); +INSERT INTO `member` VALUES(2, 'Emilie', '', 'emilie', '', '12345678', 0, 'Europe/Paris', 0, '2010-06-11 01:31:00', '0000-00-00', '0000-00-00 00:00:00', '127.0.0.1', '0000-00-00 00:00:00', 0, 0, '', 1); -INSERT INTO `member` VALUES(1, 'Administrator', '', 'admin', '', '12345678', 0, 'Asia/Bangkok', 0, '2010-05-21 01:43:21', '0000-00-00', '2010-05-30 13:57:18', '127.0.0.1', '0000-00-00 00:00:00', 1, 0, '', 1); -INSERT INTO `member` VALUES(2, 'Emilie', '', 'emilie', '', '12345678', 0, 'Europe/Paris', 0, '2010-05-21 01:44:17', '0000-00-00', '0000-00-00 00:00:00', '127.0.0.1', '0000-00-00 00:00:00', 0, 0, '', 1); - --- -------------------------------------------------------- - --- --- Table structure for table `task` --- - -DROP TABLE IF EXISTS `task`; -CREATE TABLE `task` ( +CREATE TABLE IF NOT EXISTS `task` ( `id` int(10) unsigned NOT NULL auto_increment, `title` varchar(255) NOT NULL, `note` text NOT NULL, @@ -109,23 +54,12 @@ CREATE TABLE `task` ( `member_id` mediumint(8) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `member_id` (`member_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ; +) ENGINE=MyISAM DEFAULT CHARSET=utf8; --- --- Dumping data for table `task` --- +INSERT INTO `task` VALUES(1, 'taskfreak : README first about this beta version', 'Please keep in mind that this is a beta version. There are quite a few known bugs, a handful of unknown bugs.\r\n\r\nHere''s what you can do so far :\r\n- create, edit and archive tasks\r\n- start and stop task timers\r\n- report time spent on a task\r\n- edit your own profile\r\n- see other''s tasks (task manager only)\r\n- create and edit users (user admin only)\r\n\r\nMake sure you read the README file under the DOCS/ folder. There''s a few setup tips in there.', 5, '9999-00-00', '2010-06-11', 0, 0, 1); +INSERT INTO `task` VALUES(2, 'taskfreak : quick notes about TT 0.4', 'Here''s the list of known bugs at release time :\r\n- some errors might occur on dates depending on your time zone\r\n- order by start, stop, or spent doesn''t really make sense\r\n- very buggy under IE8, and simply unusable with older versions of IE\r\n\r\nPlease report found bugs here :\r\nhttp://forum.taskfreak.com/index.php?board=7.0', 4, '9999-00-00', '9999-00-00', 0, 0, 1); -INSERT INTO `task` VALUES(1, 'taskfreak : README first about this beta version', 'Please keep in mind that this is a beta version. There are quite a few known bugs, a handful of unknown bugs.\r\n\r\nHere''s what you can do so far :\r\n- create, edit and archive tasks\r\n- start and stop task timers\r\n- report time spent on a task\r\n- edit your own profile\r\n- see other''s tasks (task manager only)\r\n- create and edit users (user admin only)\r\n\r\nMake sure you read the README file under the DOCS/ folder. There''s a few setup tips in there.', 5, '9999-00-00', '2010-05-30', 0, 0, 1); -INSERT INTO `task` VALUES(2, 'taskfreak : quick notes about TT 0.3', 'Here''s the list of known bugs at release time :\r\n- javascript calendar (jdpicker) closes when changing month or year\r\n- order by start, stop, or spent doesn''t really make sense\r\n- very buggy under IE8, and simply unusable with older versions of IE\r\n\r\nPlease report found bugs here :\r\nhttp://forum.taskfreak.com/index.php?board=7.0', 4, '9999-00-00', '9999-00-00', 0, 0, 1); - --- -------------------------------------------------------- - --- --- Table structure for table `timer` --- - -DROP TABLE IF EXISTS `timer`; -CREATE TABLE `timer` ( +CREATE TABLE IF NOT EXISTS `timer` ( `task_id` int(10) unsigned NOT NULL, `start` datetime NOT NULL, `stop` datetime NOT NULL, @@ -134,7 +68,3 @@ CREATE TABLE `timer` ( KEY `task_id` (`task_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; --- --- Dumping data for table `timer` --- - diff --git a/DOCS/translation.txt b/DOCS/translation.txt new file mode 100644 index 0000000..361a0b7 --- /dev/null +++ b/DOCS/translation.txt @@ -0,0 +1,46 @@ +TaskFreak! Time Tracking +------------------------ + +How to change the default language ? +------------------------------------ + +In app/config/app.php, go to the end of the file and modify its settings : + +For english : +[code] +$GLOBALS['config']['lang'] = array( + 'default' => 'en', + 'user' => 'en', + 'specialchars' => 2 +); +[/code] + +For french : +[code] +$GLOBALS['config']['lang'] = array( + 'default' => 'fr', + 'user' => 'fr', + 'specialchars' => 2 +); +[/code] + +Note : don't bother modifying the specialchars setting + + +How can I translate this app to my language ? +--------------------------------------------- + +There's 5 files you need to look : +- lib/lang/en/config.php +- lib/lang/en/common.php +- app/lang/en/freak.php +- app/lang/en/help_multi_creation.php +- app/lang/en/help_timer_creation.php + +1) Copy folder lib/lang/en to lib/lang/XX where XX is your language code +2) Copy folder app/lang/en to app/lang/XX where XX is your language code +3) Open all copied files and start translating +4) Change the application settings (read instructions above) and test it all + +Then, please send them to taskfreak@gmail.com so your translation can be +included in the next TaskFreak! release \ No newline at end of file diff --git a/README b/README index d1f4ffa..c6d883a 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ TaskFreak! Time Tracking ------------------------ -version : 0.3 -released : 2010-05-30 +version : 0.4 +released : 2010-06-11 status : beta ------------------------ diff --git a/app/config/app.php b/app/config/app.php index c8c1b55..83e0fff 100644 --- a/app/config/app.php +++ b/app/config/app.php @@ -3,8 +3,8 @@ // ---- LOG and DEBUGGING ----------------------------------------------------- $GLOBALS['config']['log_front'] = 0; -$GLOBALS['config']['log_debug'] = 1; -$GLOBALS['config']['log_message'] = 1; +$GLOBALS['config']['log_debug'] = 0; +$GLOBALS['config']['log_message'] = 0; $GLOBALS['config']['log_warn'] = 0; $GLOBALS['config']['log_error'] = 1; $GLOBALS['config']['log_core'] = 0; @@ -26,14 +26,6 @@ $GLOBALS['config']['pages'] = array( 'Archives' => 'task/archives' ); -// ---- LANGUAGE DEFAULTS ----------------------------------------------------- - -$GLOBALS['config']['lang'] = array( - 'default' => 'en', - 'user' => 'en', - 'specialchars' => 2 -); - // ---- DATE / TIME FORMATS --------------------------------------------------- // date/time timezone and formats defaults @@ -58,20 +50,20 @@ $GLOBALS['config']['task'] = array( $GLOBALS['config']['task']['priority'] = array( 'options' => array( - 1 => '1) urgent', - 2 => '2) important', - 3 => '3) quickly', - 4 => '4) pretty soon', - 5 => '5) normal', - 6 => '6) after', - 7 => '7) later', - 8 => '8) anytime', - 9 => '9) whatever' + 1 => 'urgent', + 2 => 'important', + 3 => 'quickly', + 4 => 'soon', + 5 => 'normal', + 6 => 'after', + 7 => 'later', + 8 => 'anytime', + 9 => 'whenever' ), 'default' => 5 ); -$GLOBALS['config']['task']['pagination'] = array('15'=>15,'25'=>25,'50'=>50,'all'=>0); +$GLOBALS['config']['task']['pagination'] = array(15=>15,30=>30,50=>50,'all'=>0); $GLOBALS['config']['task']['pagination_default'] = 15; // ---- DEFAULT Javascript ---------------------------------------------------- @@ -88,6 +80,13 @@ $GLOBALS['config']['skin'] = 'default'; // ---- LANGUAGE -------------------------------------------------------------- -$GLOBALS['config']['lang']['default'] = 'en'; -$GLOBALS['config']['lang']['user'] = 'en'; -$GLOBALS['config']['lang']['specialchars'] = 2; +$GLOBALS['config']['lang'] = array( + 'default' => 'en', + 'user' => 'en', + 'specialchars' => 2 +); + +$GLOBALS['config']['lang']['files'] = array( + 'common.php' => APP_INCLUDE_PATH.'lib/lang/', + 'freak.php' => APP_INCLUDE_PATH.'app/lang/' +); diff --git a/app/config/core.php b/app/config/core.php index 414b8e2..dbad8da 100644 --- a/app/config/core.php +++ b/app/config/core.php @@ -3,8 +3,6 @@ error_reporting(E_ALL); // --- APPLICATION SETUP ------------------------------------------------------ -$GLOBALS['config'] = array(); - // connect to database (see /app/config/db.php for settings) define('APP_SETUP_DATABASE', true); @@ -15,7 +13,7 @@ define('APP_SETUP_GLOBAL_SETTINGS', false); define('APP_SETUP_USER_SETTINGS', false); // use translation helper -define('APP_SETUP_TRANSLATOR', false); +define('APP_SETUP_TRANSLATOR', true); // use (trans-sessions) messaging helper define('APP_SETUP_MESSAGING', true); @@ -23,6 +21,8 @@ define('APP_SETUP_MESSAGING', true); // use navi helper define('APP_SETUP_NAVI', true); +$GLOBALS['config'] = array(); + // --- USER AUTHENTICATION SETUP ---------------------------------------------- // model class used for app users @@ -45,7 +45,7 @@ $GLOBALS['config']['auth'] = array( // allow auto login (true or false) 'password_recover' => true, // allow password recovery (true or false) - 'register' => 2 + 'register' => 0 // register mode // 0: no registration, 1: account created directly (no validation) // 2: user validation (from email), 3: admin validate account @@ -62,23 +62,30 @@ define('APP_CONFIG_PATH',APP_CORE_PATH.'config/'); define('APP_MODEL_PATH',APP_CORE_PATH.'model/'); define('APP_CONTROLLER_PATH',APP_CORE_PATH.'controller/'); define('APP_VIEW_PATH',APP_CORE_PATH.'view/'); +define('APP_CACHE_PATH',APP_ROOT_PATH.'cache/'); define('APP_INCLUDE_PATH', APP_ROOT_PATH); -define('APP_CACHE_PATH',APP_INCLUDE_PATH.'cache/'); define('APP_LIB_PATH',APP_INCLUDE_PATH.'lib/'); define('APP_CLASS_PATH',APP_LIB_PATH.'class/'); define('APP_HELPER_PATH',APP_LIB_PATH.'helper/'); +define('APP_LANGUAGE_PATH',APP_LIB_PATH.'lang/'); define('APP_ASSET_PATH',APP_ROOT_PATH.'asset/'); -define('APP_LANGUAGE_PATH',APP_ASSET_PATH.'lang/'); define('APP_PLUGIN_PATH',APP_ROOT_PATH.'plugin/'); define('APP_SKIN_PATH',APP_ROOT_PATH.'skin/'); // ---- APPLICATION URLs ------------------------------------------------------ -define('APP_URL_REWRITE', true); -define('APP_WWW_URI', '/'); -// define('APP_WWW_URI', '/taskfreak/'); +define('APP_URL_REWRITE', false); + +$uri = trim(substr(APP_WWW_PATH,strlen($_SERVER['DOCUMENT_ROOT'])),'/'); +if (empty($uri)) { + $uri = '/'; +} else { + $uri = '/'.$uri.'/'; +} +define('APP_WWW_URI', $uri); +unset($uri); define('APP_WWW_URL','http://'.$_SERVER['SERVER_NAME'].APP_WWW_URI); @@ -87,7 +94,7 @@ define('APP_WWW_URL','http://'.$_SERVER['SERVER_NAME'].APP_WWW_URI); define('APP_USER_ID_LENGTH',8); // length of user ID define('APP_USER_SANITIZE','/^[a-z0-9_-]+$/i'); define('APP_USER_NAME_MIN',4); // minimum length for username -define('APP_USER_NAME_MAX',15); // maximum length for username +define('APP_USER_NAME_MAX',16); // maximum length for username define('APP_USER_PASS_MIN',4); // minimum length for password define('APP_USER_PASS_MAX',16); // maximum length for password define('APP_PASSWORD_SANITIZE','/^[a-z0-9%!@#&*+:;,<>\.\?\|\{\}\(\)\[\]\$_-]+$/i'); diff --git a/app/config/path.php b/app/config/path.php index 4528da3..8b896da 100644 --- a/app/config/path.php +++ b/app/config/path.php @@ -33,4 +33,9 @@ $GLOBALS['config']['path']['css'] = array( $GLOBALS['config']['path']['js'] = array( $GLOBALS['config']['skin'].'/js/', 'asset/js/' +); + +$GLOBALS['config']['path']['lang'] = array( + 'lib/lang/', + 'app/lang/' ); \ No newline at end of file diff --git a/app/controller/admin.php b/app/controller/admin.php index c4e4621..4566173 100644 --- a/app/controller/admin.php +++ b/app/controller/admin.php @@ -4,7 +4,7 @@ * * @package taskfreak_tt * @author Stan Ozier - * @version 0.3 + * @version 0.4 * @copyright GNU General Public License (GPL) version 3 */ @@ -26,7 +26,7 @@ class Admin extends AppController { $this->page->clean('js'); } else { $this->page->add('css',array('form.css','freak.css','list.css','tracker.css','colorbox.css')); - // $this->page->add('js',array('jquery.form.min.js','jquery.colorbox-min.js')); + $this->_addJsSettings(); $this->page->add('js','freak.js'); } } @@ -42,17 +42,17 @@ class Admin extends AppController { $this->limit = $this->fc->sessionVariable('userlimit'); $this->search = $this->fc->sessionVariable('search'); - $title = 'All users'; + $title = TR::get('ui','all_users'); $filter = ''; switch ($this->filter) { case '1': - $title = 'Task managers'; + $title = TR::get('ui','task_managers'); $filter = "actags LIKE '%task_see_all%'"; $this->limit = 0; break; case '2': - $title = 'User managers'; + $title = TR::get('ui','user_admins'); $filter = "actags LIKE '%admin_user%'"; $this->limit = 0; break; @@ -101,9 +101,11 @@ class Admin extends AppController { if ($this->fc->chkReqVar('pass1') && $this->fc->chkReqVar('pass2')) { if ($this->data->setPassword($this->fc->getReqVar('pass1'), $this->fc->getReqVar('pass2'))) { // save it all + error_log('setting new password : '.$this->fc->getReqVar('pass1')); $this->data->ignore(); } else { // do not save password + error_log('can not save password'); $this->data->ignore('password,salt'); } } @@ -113,10 +115,11 @@ class Admin extends AppController { $myself = ($this->data->getUid() == $this->fc->user->getUid()); if ($this->data->save(!$myself)) { if ($myself) { - // editing own profile need to relogin + // editing own profile need to reset session + error_log('updating session'); $this->data->updateSessionVariables(); } - $this->fc->autoRedirect('user saved'); + $this->fc->autoRedirect('saved'); } } return true; @@ -133,18 +136,18 @@ class Admin extends AppController { $db->query('DELETE FROM '.$this->data->dbTable('acl_user').' WHERE user_id='.$this->data->getUid()); // delete this user's tasks $db->query('DELETE FROM '.$this->data->dbTable('task').' WHERE member_id='.$this->data->getUid()); - $this->fc->redirect(APP_WWW_URI.'admin','user deleted'); + $this->fc->redirect($this->fc->getUrl('admin'),'deleted'); } } - $this->fc->redirect(APP_WWW_URI.'admin','user deleted'); + $this->fc->redirect($this->fc->getUrl('admin'),'deleted'); } public function switchAction() { if (!$this->fc->user->checkAcl('task_see_all')) { - $this->fc->redirect(APP_WWW_URI,'access_denied'); + $this->fc->redirect(APP_WWW_URI,'[error]access_denied'); } if ($id = $this->fc->getReqVar('id')) { @@ -156,7 +159,7 @@ class Admin extends AppController { $this->fc->setSessionVariable('switch_id', $id); $this->fc->setSessionVariable('switch_name', $obj->get('nickname')); } - $this->fc->redirect(APP_WWW_URI,'switched to '.$obj->get('nickname')); + $this->fc->redirect(APP_WWW_URI,'[ui]switched'); } $this->switch_id = $this->fc->getSessionVariable('switch_id'); @@ -202,4 +205,18 @@ class Admin extends AppController { return true; } + protected function _addJsSettings() { + $js = "var RELOAD_URI='".APP_WWW_URI."task/main/ajax/1'; var URLMODREWRITE=true; "; + + if (!APP_URL_REWRITE) { + $js = "var RELOAD_URI='".APP_WWW_URI."?c=task&a=main&ajax=1'; var URLMODREWRITE=false; "; + } + + // translations + $js .= "var LANGRUNNING='".TR::html('task','running')."'; "; + $js .= "var LANGCONFIRM='".TR::html('data','delete_confirm')."'; "; + + $this->page->add('jsCode', $js); + } + } diff --git a/app/controller/login.php b/app/controller/login.php index e3cb402..cb0c8be 100644 --- a/app/controller/login.php +++ b/app/controller/login.php @@ -25,7 +25,7 @@ class Login extends AppController { */ public function mainAction() { $this->fc->user->addHelper('html_form'); - $this->page->set('title','TaskFreak! Login'); + $this->page->set('title','TaskFreak! '.TR::get('security','login')); $this->page->add('css',array('form.css','freak.css','login.css')); $this->page->add('js','form.js'); $this->setView('login/login'); diff --git a/app/controller/task.php b/app/controller/task.php index 8569692..ed674b7 100644 --- a/app/controller/task.php +++ b/app/controller/task.php @@ -4,7 +4,7 @@ * * @package taskfreak_tt * @author Stan Ozier - * @version 0.3 + * @version 0.4 * @copyright GNU General Public License (GPL) version 3 */ @@ -38,45 +38,46 @@ class Task extends AppController { } else { $this->page->add('css',array('form.css','freak.css','list.css','tracker.css','colorbox.css')); // $this->page->add('js',array('jquery.form.min.js','jquery.colorbox-min.js')); + $this->_addJsSettings(); $this->page->add('js','freak.js'); } } public function mainAction() { $this->filter = $this->fc->sessionVariable('filter'); - $title = 'Todo'; + $title = 'todo'; $filter = 'status=0 AND archived=0'; $this->actions = array(); switch ($this->filter) { case '1': - $title = 'Completed'; + $title = 'done'; $filter = 'status=1 AND archived=0'; - $this->actions['open'] = 'Re-open'; - $this->actions['valid'] = 'Validate'; - $this->actions['archive'] = 'Archive'; + $this->actions['open'] = 'reopen'; + $this->actions['valid'] = 'validate'; + $this->actions['archive'] = 'archive'; break; case '2': - $title = 'Valid'; // -TODO- check english term + $title = 'valid'; $filter = 'status=2 AND archived=0'; - $this->actions['open'] = 'Re-open'; - $this->actions['archive'] = 'Archive'; + $this->actions['open'] = 'reopen'; + $this->actions['archive'] = 'archive'; break; case '3': - $title = 'Archives'; + $title = 'archives'; $filter = 'archived=1'; - $this->actions['unarchive'] = 'Unarchive'; + $this->actions['unarchive'] = 'unarchive'; break; default: - $this->actions['report'] = 'Report 1 day'; - $this->actions['close'] = 'Mark as done'; - $this->actions['valid'] = 'Validate'; - $this->actions['archive'] = 'Archive'; + $this->actions['report'] = 'postpone_1_day'; + $this->actions['close'] = 'mark_done'; + $this->actions['valid'] = 'validate'; + $this->actions['archive'] = 'archive'; break; } $this->_taskList($filter); - $this->page->set('title',$title.' | TaskFreak! Time Tracker'); + $this->page->set('title',TR::get('pages',$title).' | TaskFreak! Time Tracker'); if ($this->fc->getReqVar('ajax')) { $this->setView('include/list-'.($this->expand?'expand':'compact')); @@ -91,14 +92,14 @@ class Task extends AppController { // drop if no checkbox have been checked if (!$this->fc->chkReqVar('chk')) { // -TODO- show error - $this->fc->redirect(APP_WWW_URI.'task/main/','please mark at least one task'); + $this->fc->redirect($this->fc->getUrl('task','main'),'[error]none_checked'); } // check action request $action = $this->fc->chkReqVar('report,open,close,valid,archive,unarchive'); // do it then TaskModel::updateManyAtOnce($action, $_POST['chk']); // reload entire page - $this->fc->redirect(APP_WWW_URI.'task/main/'); + $this->fc->redirect($this->fc->getUrl('task','main')); } /** @@ -123,7 +124,7 @@ class Task extends AppController { // now start selected task TimerModel::start($id); $this->current = TaskSummary::loadCurrent(); - $this->jsCode .= "clockstart('$id')"; + $this->jsCode .= "clockstart('$id');$('#drun button').wTip();"; } $this->setView('include/timer'); $this->view(); @@ -159,7 +160,7 @@ class Task extends AppController { $this->jsCode .= "clockreport('$cid');clockstatus('paused');"; } else { // nope, requested task is not running, show error - $this->jsCode = "alert('error trying to pause')"; + $this->jsCode = "alert('".TR::get('error','action_failed')."')"; FC::log_debug('error trying to pause non running task'); } break; @@ -173,7 +174,7 @@ class Task extends AppController { if (TimerModel::stop($id)) { $this->jsCode = "clockstatus();"; } else { - $this->jsCode = "alert('task already stopped');"; + $this->jsCode = "alert('".TR::get('error','action_failed')."');"; } $this->current = false; break; @@ -273,7 +274,7 @@ class Task extends AppController { $this->timer = new TimerModel(); $this->timer->addHelper('html_form'); - $this->page->set('title','Todo details | TaskFreak! Time Tracker'); + $this->page->set('title',TR::get('pages','view_task').' | TaskFreak! Time Tracker'); // $this->page->add('js',array('jquery.dateentry.pack.js','jquery.timeentry.pack.js')); $this->setView('view'); $this->view(); @@ -282,7 +283,7 @@ class Task extends AppController { public function createAction() { $this->_loadTask(); $this->data->addHelper('html_form'); - $this->page->set('title','Create Multiple Todos | TaskFreak! Time Tracker'); + $this->page->set('title',TR::get('pages','create_tasks').' | TaskFreak! Time Tracker'); $this->setView('create'); $this->view(); } @@ -305,14 +306,14 @@ class Task extends AppController { } } } - $this->fc->redirect(APP_WWW_URI.'task/main',$i.' task(s) created !'); + $this->fc->redirect($this->fc->getUrl('task','main'),'created'); // -TODO- show $i } public function editAction() { $this->_loadTask(); $this->data->addHelper('html_form'); - $this->page->set('title',($this->data->getUid()?'Edit':'Create').' Todo | TaskFreak! Time Tracker'); + $this->page->set('title',TR::get('pages',($this->data->getUid()?'edit':'create').'_task').' | TaskFreak! Time Tracker'); $this->setView('edit'); $this->view(); } @@ -342,4 +343,18 @@ class Task extends AppController { return $this->data->getUid(); } + protected function _addJsSettings() { + $js = "var RELOAD_URI='".APP_WWW_URI."task/main/ajax/1'; var URLMODREWRITE=true; "; + + if (!APP_URL_REWRITE) { + $js = "var RELOAD_URI='".APP_WWW_URI."?c=task&a=main&ajax=1'; var URLMODREWRITE=false; "; + } + + // translations + $js .= "var LANGRUNNING='".TR::html('task','running')."'; "; + $js .= "var LANGCONFIRM='".TR::html('data','delete_confirm')."'; "; + + $this->page->add('jsCode', $js); + } + } \ No newline at end of file diff --git a/app/controller/timer.php b/app/controller/timer.php index 414eb3c..74af503 100644 --- a/app/controller/timer.php +++ b/app/controller/timer.php @@ -4,7 +4,7 @@ * * @package taskfreak_tt * @author Stan Ozier - * @version 0.3 + * @version 0.4 * @copyright GNU General Public License (GPL) version 3 */ @@ -79,7 +79,7 @@ class Timer extends AppController { echo ''; - echo '

time added

'; + echo '

'.TR::html('message','time_added').'

'; return false; } @@ -89,7 +89,7 @@ class Timer extends AppController { $start = $this->fc->getReqVar('start'); if (empty($id) || empty($start)) { - $this->fc->redirect(APP_WWW_URI,'ERROR:missing parameters'); + $this->fc->redirect(APP_WWW_URI,'[error]action_failed'); } // delete timer @@ -115,7 +115,7 @@ class Timer extends AppController { echo "reloadList();"; echo ''; } else { - $this->fc->redirect(APP_WWW_URI,'Timer deleted'); + $this->fc->redirect(APP_WWW_URI,'deleted'); } } else { // error deleting @@ -124,7 +124,7 @@ class Timer extends AppController { echo 'alert("can not delete timer");'; echo ''; } else { - $this->fc->redirect(APP_WWW_URI,'Timer NOT deleted'); + $this->fc->redirect(APP_WWW_URI,'[error]action_deleted'); } } diff --git a/app/lang/en/freak.php b/app/lang/en/freak.php new file mode 100644 index 0000000..b928252 --- /dev/null +++ b/app/lang/en/freak.php @@ -0,0 +1,120 @@ + + * @version 0.4 + * @copyright GNU General Public License (GPL) version 3 + */ + +$GLOBALS['lang']['task'] = array( + 'priority' => 'priority', + 'spent' => 'spent', + 'note' => 'note', + 'todo' => 'todo', + 'done' => 'done', + 'valid' => 'valid', + 'archived' => 'archived', + 'running' => 'running', + 'paused' => 'paused' +); + +$GLOBALS['lang']['priority'] = array( + 'urgent' => 'urgent', + 'important' => 'important', + 'high' => 'high', + 'quickly' => 'quickly', + 'pretty_soon' => 'pretty soon', + 'soon' => 'soon', + 'normal' => 'normal', + 'after' => 'after', + 'later' => 'later', + 'low' => 'low', + 'anytime' => 'anytime', + 'whenever' => 'whenever' +); + +$GLOBALS['lang']['ui'] = array( + 'reload' => 'reload', + 'reload_list' => 'reload list', + 'task' => 'task', + 'tasks' => 'tasks', + 'create_single' => 'create single task', + 'create_multi' => 'create multiple task', + 'edit_task' => 'edit task', + 'delete_task' => 'delete task', + 'start_task' => 'start task', + 'mark_archived' => 'mark task as archived', + 'done_confirm' => 'really mark this task as completed ?', + 'compact' => 'compact', + 'expand' => 'expand', + 'select_all' => 'select all', + 'info' => 'info', + 'history' => 'history', + 'history_empty' => 'no time reports yet', + 'report_spent' => 'report time spent', + 'total' => 'total', + 'user_menu' => 'show user menu', + 'admin' => 'admin', + 'settings' => 'settings', + 'all_users' => 'all users', + 'switch' => 'switch', + 'switch_user' => 'see other user\'s tasks', + 'select_user' => 'select user whose tasks you want to see', + 'switched' => 'switched to another user', + 'task_manager' => 'task manager', + 'task_managers' => 'task managers', + 'user_admin' => 'user admin', + 'user_admins' => 'user admins', + 'last_visit' => 'last visit', + 'preferences' => 'my preferences', + 'create_user' => 'create user', + 'edit_user' => 'edit user', + 'delete_user' => 'delete user' +); + +$GLOBALS['lang']['pages'] = array( + 'todo' => 'todo', + 'done' => 'done', + 'valid' => 'valid', + 'archives' => 'archives', + 'edit_task' => 'edit task', + 'create_task' => 'create task', + 'create_tasks' => 'create multiple tasks', + 'view_task' => 'task details' +); + +$arrMess = array( + 'task_created' => 'task created', + 'task_updated' => 'task updated', + '%_task_created' => '% task(s) created', + 'task_deleted' => 'task deleted', + 'time_added' => 'work time reported' +); +// we're adding these translations to the standard messages translations +$GLOBALS['lang']['message'] = $GLOBALS['lang']['message']+$arrMess; + +$arrButton = array( + 'pause' => 'pause', + 'resume' => 'resume', + 'done' => 'done', + 'reopen' => 're-open', + 'postpone_1_day' => 'postpone 1 day', + 'postpone_2_days' => 'postpone 2 days', + 'postpone_1_week' => 'postpone 1 week', + 'postpone_2_weeks' => 'postpone 2 weeks', + 'postpone_1_month' => 'postpone 1 month', + 'postpone_2_months' => 'postpone 2 months', + 'postpone_1_year' => 'postpone 1 year', + 'postpone_2_years' => 'postpone 2 years', + 'mark_done' => 'mark as done', + 'validate' => 'validate', + 'archive' => 'archive', + 'unarchive' => 'unarchive', + 'save_report' => 'save_report', + 'save_task' => 'save task', + 'save_and_start' => 'save and start' +); +// we're adding these translations to the standard button translations +$GLOBALS['lang']['button'] = $GLOBALS['lang']['button']+$arrButton; \ No newline at end of file diff --git a/app/lang/en/help_multi_creation.php b/app/lang/en/help_multi_creation.php new file mode 100644 index 0000000..e612581 --- /dev/null +++ b/app/lang/en/help_multi_creation.php @@ -0,0 +1,19 @@ +

Enter one task per line.

+

Task format

+

Task format : [date] [priority] [label :] task title
+fields within brackets are optional

+

date can be :

+
    +
  • a date in format dd/mm[/yy]
  • +
  • a + followed by number of days in the future
  • +
  • a - means no deadline
  • +
  • nothing means deadline is today
  • +
+

priority is a number between 1 and 9, followed by a )
+« 1) » for urgent tasks, « 5) » for normal priority

+

label is optional

+

Defaults for multiple tasks

+

a line starting by a * sets up defaults

+

Format is : * [date] [label]
+« * +1 taskfreak » or « * 12/04 »

+

reset defaults with a line with « ** »

\ No newline at end of file diff --git a/app/lang/en/help_timer_creation.php b/app/lang/en/help_timer_creation.php new file mode 100644 index 0000000..88a1302 --- /dev/null +++ b/app/lang/en/help_timer_creation.php @@ -0,0 +1,8 @@ +

Enter either :

+
    +
  • A start time only (will calculate time from then until now)
  • +
  • A time spent only (will consider you've just finished the task)
  • +
  • A start time and an stop time
  • +
  • A start time and a time spent
  • +
  • A stop time and a time spent
  • +
\ No newline at end of file diff --git a/app/lang/fr/freak.php b/app/lang/fr/freak.php new file mode 100644 index 0000000..3ba9487 --- /dev/null +++ b/app/lang/fr/freak.php @@ -0,0 +1,120 @@ + + * @version 0.4 + * @copyright GNU General Public License (GPL) version 3 + */ + +$GLOBALS['lang']['task'] = array( + 'priority' => 'priorité', + 'spent' => 'durée', + 'note' => 'note', + 'todo' => 'à faire', + 'done' => 'effectué', + 'valid' => 'validé', + 'archived' => 'archivé', + 'running' => 'en cours', + 'paused' => 'en pause`' +); + +$GLOBALS['lang']['priority'] = array( + 'urgent' => 'urgent', + 'important' => 'important', + 'high' => 'haute', + 'quickly' => 'dès que possible', + 'pretty_soon' => 'rapidement', + 'soon' => 'bientôt', + 'normal' => 'normal', + 'after' => 'après', + 'later' => 'plus tard', + 'low' => 'faible', + 'anytime' => 'bien plus tard', + 'whenever' => 'peu importe' +); + +$GLOBALS['lang']['ui'] = array( + 'reload' => 'recharger', + 'reload_list' => 'recharger la liste', + 'task' => 'tâche', + 'tasks' => 'tâches', + 'create_single' => 'créer une tâche', + 'create_multi' => 'créer plusieurs tâches', + 'edit_task' => 'modifier tâche', + 'delete_task' => 'supprimer tâche', + 'start_task' => 'démarrer la tâche', + 'mark_archived' => 'marquer comme archivé', + 'done_confirm' => 'vraiment marquer comme effectuée?', + 'compact' => 'compacte', + 'expand' => 'étendue', + 'select_all' => 'tout sélectionner', + 'info' => 'info', + 'history' => 'historique', + 'history_empty' => 'aucune durée rapportée', + 'report_spent' => 'rapporter une durée passée', + 'total' => 'total', + 'user_menu' => 'menu utilisateur', + 'admin' => 'administration', + 'settings' => 'paramètres', + 'all_users' => 'tous utilisateurs', + 'switch' => 'changer', + 'switch_user' => 'changer d\'utilisateur', + 'select_user' => 'choisir un utiisateur pour en voir les tâches', + 'switched' => 'changement effectué', + 'task_manager' => 'chef de projet', + 'task_managers' => 'chefs de projet', + 'user_admin' => 'administrateur', + 'user_admins' => 'administrateurs', + 'last_visit' => 'dernière visite', + 'preferences' => 'mes préférences', + 'create_user' => 'créer utilisateur', + 'edit_user' => 'moditier utilisateur', + 'delete_user' => 'supprimer utilisateur' +); + +$GLOBALS['lang']['pages'] = array( + 'todo' => 'tâches à faire', + 'done' => 'tâches effectuées', + 'valid' => 'tâches validées', + 'archives' => 'archives', + 'edit_task' => 'modifier une tâche', + 'create_task' => 'créer une tâche', + 'create_tasks' => 'créer plusieurs tâches', + 'view_task' => 'détails de la tâche' +); + +$arrMess = array( + 'task_created' => 'tâche créée', + 'task_updated' => 'tâche mise à jour', + '%_task_created' => '% tâche(s) crées', + 'task_deleted' => 'tâche supprimée', + 'time_added' => 'temps passé enregistré' +); +// we're adding these translations to the standard messages translations +$GLOBALS['lang']['message'] = $GLOBALS['lang']['message']+$arrMess; + +$arrButton = array( + 'pause' => 'pause', + 'resume' => 'reprendre', + 'done' => 'effectuée', + 'reopen' => 'réouvrir', + 'postpone_1_day' => 'repousser d\'un jour', + 'postpone_2_days' => 'repousser de 2 jours', + 'postpone_1_week' => 'repousser d\'une semaine', + 'postpone_2_weeks' => 'repousser de 2 semaines', + 'postpone_1_month' => 'repousser d\'un mois', + 'postpone_2_months' => 'repousser de 2 mois', + 'postpone_1_year' => 'repousser d\'une année', + 'postpone_2_years' => 'repousser de 2 ans', + 'mark_done' => 'marquer effectuée', + 'validate' => 'valider', + 'archive' => 'archiver', + 'unarchive' => 'réactiver', + 'save_report' => 'rapporter', + 'save_task' => 'enregistrer la tâche', + 'save_and_start' => 'enregistrer et démarrer' +); +// we're adding these translations to the standard button translations +$GLOBALS['lang']['button'] = $GLOBALS['lang']['button']+$arrButton; \ No newline at end of file diff --git a/app/lang/fr/help_multi_creation.php b/app/lang/fr/help_multi_creation.php new file mode 100644 index 0000000..b8cc2a7 --- /dev/null +++ b/app/lang/fr/help_multi_creation.php @@ -0,0 +1,19 @@ +

Saisir une tâche par ligne.

+

Format de la saisie :

+

[date] [priorité] [mot-clé :] titre de la tâche
+les champs entre crochets sont facultatifs

+

date peut être :

+
    +
  • une date au format jj/mm[/aa]
  • +
  • un + suivi du nombre de jours dans le futur
  • +
  • un - signifie pas de date
  • +
  • pas de date signifie aujourd'hui
  • +
+

priorité: un chiffre entre 1 et 9 suivi de )
+« 1) » pour urgent, « 5) » pour normal

+

mot-clé est facultatif

+

Valeurs par défaut pour plusieurs tâches

+

commençer par * indique les valeurs par défaut

+

Le format est : * [date] [mot-clé]
+« * +1 taskfreak » ou « * 12/04 »

+

annuler les valeurs par défaut : « ** » sur une ligne

\ No newline at end of file diff --git a/app/lang/fr/help_timer_creation.php b/app/lang/fr/help_timer_creation.php new file mode 100644 index 0000000..1ad2c10 --- /dev/null +++ b/app/lang/fr/help_timer_creation.php @@ -0,0 +1,8 @@ +

Saisir soit :

+
    +
  • Une heure de début (calcule le temps passé jusqu'à maintenant)
  • +
  • Un temps passé (considère que vous venez juste de terminer)
  • +
  • Une heure de départ et une heure de fin
  • +
  • Une heure de départ et un temps passé
  • +
  • Une heure de fin et un temps passé
  • +
\ No newline at end of file diff --git a/app/model/member.php b/app/model/member.php index 1eb5f8c..7ae2450 100644 --- a/app/model/member.php +++ b/app/model/member.php @@ -4,7 +4,7 @@ * * @package taskfreak_tt * @author Stan Ozier - * @version 0.2 + * @version 0.4 * @copyright GNU General Public License (GPL) version 3 */ @@ -29,10 +29,10 @@ class MemberModel extends UserAclModel { $arr = explode(',', $this->get('actags')); $arrTrans = array(); if (in_array('task_see_all', $arr)) { - $arrTrans[] = 'task manager'; + $arrTrans[] = TR::html('ui','task_manager'); } if (in_array('admin_user', $arr)) { - $arrTrans[] = 'user admin'; + $arrTrans[] = TR::html('ui','user_admin'); } return implode(', ',$arrTrans); } diff --git a/app/model/task.php b/app/model/task.php index fde9d01..c4d800f 100644 --- a/app/model/task.php +++ b/app/model/task.php @@ -4,7 +4,7 @@ * * @package taskfreak_tt * @author Stan Ozier - * @version 0.2 + * @version 0.4 * @copyright GNU General Public License (GPL) version 3 */ @@ -183,15 +183,15 @@ class TaskSummary extends TaskModel { public function htmlPriority() { $arr = $this->getPropertyOptions('priority'); $st = $this->get('priority'); - return $arr['options'][$st]; + return $st.') '.TR::html('priority',$arr['options'][$st]); } public function htmlStatus() { $arr = $this->getPropertyOptions('status'); $str = $this->get('status'); - $str = $arr['options'][$str]; // -TODO- TRANSLATE + $str = TR::html('task',$arr['options'][$str]); if ($this->get('archived')) { - $str .= ' (archived)'; + $str .= ' ('.TR::html('task','archived').')'; } return $str; } @@ -201,7 +201,6 @@ class TaskSummary extends TaskModel { if ($this->isEmpty('begin')) { return '-'; } else { - // -TODO- show in grey return $this->html('begin',APP_DATE); } } else { @@ -237,11 +236,11 @@ class TaskSummary extends TaskModel { case 9999: return '-'; case -1: - return 'yesterday'; + return TR::html('date','yesterday'); case 0: - return 'today'; + return TR::html('date','today'); case 1: - return 'tomorrow'; + return TR::html('date','tomorrow'); default: return $this->html('deadline',APP_DATE); } @@ -313,7 +312,7 @@ class TaskSummary extends TaskModel { if ($stopped) { return '--:--'; } else { - return 'running'; + return TR::html('task','running'); } } $h = floor($spent / 60); diff --git a/app/view/admin/switch.php b/app/view/admin/switch.php index f09c934..bed378c 100644 --- a/app/view/admin/switch.php +++ b/app/view/admin/switch.php @@ -2,7 +2,7 @@ $this->incView('include/page-top', false); ?> -

Select user whose tasks you want to see

+

    data->next()) { @@ -10,7 +10,7 @@ while ($this->data->next()) { if ($this->data->getUid() == $this->switch_id) { echo $this->data->html('nickname'); } else { - echo ''.$this->data->html('nickname').''; + echo ''.$this->data->html('nickname').''; } echo ''; } diff --git a/app/view/admin/user-edit.php b/app/view/admin/user-edit.php index 35c66d0..bd57ade 100644 --- a/app/view/admin/user-edit.php +++ b/app/view/admin/user-edit.php @@ -5,12 +5,12 @@ $this->incView('include/page-top', false); echo '

    '; if ($id = $this->data->getUid()) { if ($id == $this->fc->user->getUid()) { - echo 'My preferences'; + TR::phtml('security','my_account'); } else { - echo 'Edit a user'; + TR::phtml('ui','edit_user'); } } else { - echo 'Create new user'; + TR::phtml('ui','create_user'); } echo '

    '; @@ -20,22 +20,22 @@ echo $this->data->iHidden('id'); ?>
      data->iFieldLabelled('nickname','','','li class="compulsory"'); - echo $this->data->iFieldLabelled('email'); + echo $this->data->iFieldLabelled('nickname',TR::html('form','nick_name'),'','li class="compulsory"'); + echo $this->data->iFieldLabelled('email',TR::html('form','email')); ?>
    1. - + data->iTimeZone('time_zone'); ?>
    2. data->iFieldLabelled('username','','','li class="compulsory"'); + echo $this->data->iFieldLabelled('username',TR::html('form','username'),'','li class="compulsory"'); ?>
    3. - + data->iPass('pass1', false); ?>
    4. - + data->iPass('pass2', false); ?>
    5. data->iHidden('id'); // can only change rights for other users ?>
    6. - +
      • data->checkAcl('task_see_all')) echo ' checked="checked"'; - ?> />
      • + ?> />
      • data->checkAcl('admin_user')) echo ' checked="checked"'; - ?> />
      • + ?> />
    7. - + canDeleteThisUser) { ?> Delete + onclick="return confirm('');" class="button marge delete"> diff --git a/app/view/admin/user-list.php b/app/view/admin/user-list.php index 069f0d7..dd7f556 100644 --- a/app/view/admin/user-list.php +++ b/app/view/admin/user-list.php @@ -5,7 +5,7 @@ $this->incView('include/page-top', false);
      - Create user + @@ -40,7 +40,7 @@ $this->incView('include/page-top', false); if ($this->limit == $val) { echo ' class="active"'; } - echo '>$val)).'>'.$lbl.'
    8. '; + echo '>$val)).'>'.(is_int($lbl)?$lbl:TR::html('data',$lbl)).''; } ?>
@@ -48,9 +48,17 @@ $this->incView('include/page-top', false); if ($this->search) { echo ' class="filled"'; } ?>>

+ + + + - - + +

diff --git a/app/view/view.php b/app/view/view.php index aed85fa..c54a2b0 100644 --- a/app/view/view.php +++ b/app/view/view.php @@ -4,30 +4,30 @@ $this->incView('include/page-top', false);

data->html('title'); ?>

- + - + - + data->isEmpty('note')) { ?> - + - * @since 0.1 - * @copyright GNU Lesser General Public License (LGPL) version 3 - */ - -$GLOBALS['config']['lang']['specialchars'] = 2; \ No newline at end of file diff --git a/asset/lang/en/core.php b/asset/lang/en/core.php deleted file mode 100644 index e69de29..0000000 diff --git a/asset/lang/en/freak.php b/asset/lang/en/freak.php deleted file mode 100644 index e69de29..0000000 diff --git a/lib/class/front.php b/lib/class/front.php index 9fbbd76..231fb03 100644 --- a/lib/class/front.php +++ b/lib/class/front.php @@ -4,7 +4,7 @@ * * @package tzn_core_classes * @author Stan Ozier - * @version 0.3 + * @version 0.4 * @copyright GNU Lesser General Public License (LGPL) version 3 */ @@ -154,6 +154,7 @@ class FrontController extends HelpableSingleton { */ public function loadUserSettings() { // might overload default controller and action + // and language // -TODO- if ($this->user->isLoggedIn()) { $this->setSessionDefault('usertask', $this->user->getUid()); @@ -179,6 +180,8 @@ class FrontController extends HelpableSingleton { */ public function initTranslator() { $this->addHelper('translator'); + $this->loadLangConfig(); + $this->loadLangFilesFromConfig(); } /** diff --git a/lib/class/model.php b/lib/class/model.php index 09d6188..6cbb250 100644 --- a/lib/class/model.php +++ b/lib/class/model.php @@ -4,7 +4,7 @@ * * @package tzn_core_classes * @author Stan Ozier - * @version 0.3 + * @version 0.4 * @copyright GNU Lesser General Public License (LGPL) version 3 */ @@ -692,7 +692,7 @@ class VarDte extends VarAbstract if ($t = self::strToUnix($val)) { return strftime(APP_DATE_SQL, $t); } - $info['error'] = 'model_date_invalid'; + $info['error'] = 'invalid_date'; return false; } @@ -763,7 +763,7 @@ class VarDur extends VarAbstract } return $t; } else { - $info['error'] = 'model_time_invalid'; + $info['error'] = 'invalid_duration'; return false; } } @@ -830,7 +830,7 @@ class VarTim extends VarDur // now make GMT return $t - self::getUserTimeZoneOffset(); } - $info['error'] = 'model_time_invalid'; + $info['error'] = 'invalid_time'; return false; } @@ -886,7 +886,7 @@ class VarDtm extends VarAbstract // return datetime in SQL format return $d.' '.VarDur::workout($t); } - $info['error'] = 'model_datetime_invalid'; + $info['error'] = 'invalid_datetime'; return false; } @@ -983,7 +983,7 @@ class VarStr extends VarAbstract } switch ($GLOBALS['config']['lang']['specialchars']) { case 3: - $val = htmlentities($val); + $val = htmlentities(utf8_decode($val)); break; case 2: $val = htmlspecialchars($val); @@ -1007,20 +1007,19 @@ class VarUsr extends VarAbstract { public static function sanitize($val, &$info) { if (!$val && in_array('compulsory', $info)) { - $info['error'] = 'user_name_invalid'; + $info['error'] = 'username_invalid'; return false; } if ((strlen($val) < APP_USER_NAME_MIN) || (strlen($val) > APP_USER_NAME_MAX)) { - $info['error'] = 'user_name_length'; + $info['error'] = 'username_length'; return false; } else if (preg_match(APP_USER_SANITIZE, $val)) { return $val; } else { - $info['error'] = 'user_name_invalid'; + $info['error'] = 'username_invalid'; return false; } - return $val; } public static function value($val) { @@ -1043,15 +1042,21 @@ class VarPss extends VarAbstract return true; } } - if (preg_match(APP_PASSWORD_SANITIZE, $val)) { + return $val; + } + + public static function checkValid($val, &$info) { + if ((strlen($val) < APP_USER_PASS_MIN) + || (strlen($val) > APP_USER_PASS_MAX)) { + $info['error'] = 'password_length'; + return false; + } else if (preg_match(APP_PASSWORD_SANITIZE, $val)) { return $val; } else { $info['error'] = 'password_invalid'; return false; } - return $val; } - } /** @@ -1144,6 +1149,7 @@ class VarXml extends VarAbstract /** * URL Variable - URL Address * @since 0.1 + * @todo check if URL is valid */ class VarUrl extends VarAbstract { @@ -1176,7 +1182,7 @@ class VarEml extends VarAbstract if (empty($val) || preg_match("/^[a-z0-9]([a-z0-9_\-\.\+]*)@([a-z0-9_\-\.]*)\.([a-z]{2,4})$/i",$val)) { return $val; } else { - $info['error'] = 'model_email_invalid'; // -TODO-TRANSLATE- + $info['error'] = 'invalid_email'; return ''; } } diff --git a/lib/helper/auth.php b/lib/helper/auth.php index bef4511..d031433 100644 --- a/lib/helper/auth.php +++ b/lib/helper/auth.php @@ -4,7 +4,7 @@ * * @package tzn_helpers * @author Stan Ozier - * @version 0.2 + * @version 0.4 * @since 0.1 * @copyright GNU Lesser General Public License (LGPL) version 3 */ @@ -40,7 +40,7 @@ class AuthHelper extends Helper { } if (crypt($password, $salt) != $pass) { // password invalid - $this->error = 'user_pass_invalid'; + $this->error = 'password_invalid'; $this->badAccess(); return false; } @@ -49,7 +49,7 @@ class AuthHelper extends Helper { $sql = "ENCRYPT('$password','$salt')"; if (!self::checkDbPass($sql, $pass)) { // password not OK - $this->error = 'user_pass_invalid'; + $this->error = 'password_invalid'; $this->badAccess(); return false; // error or password mismatch } @@ -58,7 +58,7 @@ class AuthHelper extends Helper { $sql = "ENCODE('$password','$pass')"; if (!self::checkDbPass($sql, $pass)) { // password not OK - $this->error = 'user_pass_invalid'; + $this->error = 'password_invalid'; $this->badAccess(); return false; // error or password mismatch } @@ -70,7 +70,7 @@ class AuthHelper extends Helper { $sql = "MD5('$password')"; if (!self::checkDbPass($sql, $pass)) { // password not OK - $this->error = 'user_pass_invalid'; + $this->error = 'password_invalid'; $this->badAccess(); return false; // error or password mismatch } @@ -86,7 +86,7 @@ class AuthHelper extends Helper { break; } } - $this->error = 'user_pass_invalid'; + $this->error = 'password_invalid'; $this->badAccess(); return false; break; @@ -101,7 +101,7 @@ class AuthHelper extends Helper { { break; } - $this->error = 'user_pass_invalid'; + $this->error = 'password_invalid'; $this->badAccess(); return false; break; @@ -212,7 +212,7 @@ class AuthHelper extends Helper { public function login($username, $password, $activation=false) { $this->error = ''; if ($username == '') { - $this->error = 'user_name_empty'; + $this->error = 'username_required'; return false; } if (APP_AUTH_FIELD == 'username' && (!VarUsr::sanitize($username, $error))) { @@ -225,11 +225,13 @@ class AuthHelper extends Helper { if (!$this->obj->get('enabled')) { if (!$activation || $activation != $activ) { //Account Disabled - $this->error = 'user_disabled'; + $this->error = 'account_disabled'; + } else { + $this->error = 'account_not_active'; } } if (!$this->checkPassword($password)) { - $this->error = 'user_password_invalid'; + $this->error = 'password_invalid'; } else if ($activation && $activation == $activ) { // activate account $this->activateAccount(true); @@ -239,7 +241,7 @@ class AuthHelper extends Helper { return false; } } else { - $this->error = 'user_name_not_found'; + $this->error = 'username_not_found'; return false; } @@ -435,22 +437,20 @@ class AuthHelper extends Helper { if ($this->obj->get('salt') == "") { if (!$this->obj->loadByKey($key,$value)) { // user not found - $this->_error['forgot'] = $key." not found"; + $this->error = $key."_not_found"; return false; } } switch (APP_AUTH_PASSWORD_MODE) { case 1: - $this->generateNewSalt(); - $newpass = StringHelper::genRandom(6,"123456789"); - $this->obj->set('password', crypt($pass1 , $this->obj->get('salt'))); - $this->updatePassword(); - break; case 2: + case 4: + case 5: $this->generateNewSalt(); - $newpass = StringHelper::genRandom(6,"123456789"); - $this->obj->set('password', self::getDbPass("ENCRYPT(\"".$pass1."\",\"".$this->obj->get('salt')."\")")); - $this->updatePassword(); + $newpass = StringHelper::genRandom(6,"123456789"); + $this->obj->setRawPassword($newpass, $this->obj->get('salt')); + $this->updatePassword(); + return $newpass; break; case 3: $strSql = "SELECT DECODE(password, '".$this->obj->get('salt') @@ -458,29 +458,19 @@ class AuthHelper extends Helper { ." WHERE ".$this->obj->dbUid()."='".$this->obj->getUid()."'"; if ($rows = DbConnnector::query($strSql)) { if (!empty($rows[0])) { - $this->obj->password = $rows[0]->pass; - return $this->obj->password; + return $rows[0]->pass; } } - $this->_error['forgot'] = "can not decode?"; - return false; - break; - case 4: - case 5: - $this->generateNewSalt(); - $newpass = StringHelper::genRandom(6,"123456789"); - $this->password = "MD5('$newpass')"; - $this->updatePassword(); break; default: $iv = mcrypt_create_iv (mcrypt_get_iv_size (MCRYPT_3DES, MCRYPT_MODE_ECB), MCRYPT_RAND); - $this->password = mcrypt_decrypt (MCRYPT_3DES, $this->obj->get('salt'), + return mcrypt_decrypt (MCRYPT_3DES, $this->obj->get('salt'), $passBin, MCRYPT_MODE_ECB, $iv); - return $this->password; break; } - return $newpass; + $this->error = 'password_recover'; + return false; } public function getLoginCountry() { diff --git a/lib/helper/html_form.php b/lib/helper/html_form.php index 70144ca..7e1417c 100644 --- a/lib/helper/html_form.php +++ b/lib/helper/html_form.php @@ -94,7 +94,6 @@ class HtmlFormHelper extends Helper { /** * returns a field along with LABEL, all wrapped in a LI - * @todo make the wrapper optional * @todo missing types */ public function iFieldLabelled($key, $label='', $type='', $wrap='li') { @@ -144,7 +143,7 @@ class HtmlFormHelper extends Helper { return false; } if (empty($label)) { - $label = str_replace('_',' ',$key); // -TODO- translate + $label = str_replace('_',' ',$key); } return $this->_htmlWrapBegin($wrap) .'' @@ -314,6 +313,30 @@ class HtmlFormHelper extends Helper { return $str.''; } + /** + * generates a select (drop down) + */ + public function iSelectTranslate($key, $section, $options='') { + if (isset($this->obj)) { + $options = $this->obj->getPropertyOptions($key); + } + if (empty($options['options'])) { + FC::log_warn("iRadio $key does not provide options"); + return $key.' (no option)'; + } + $str = ''; + } + /** * generates a time zone drop down list */ diff --git a/lib/helper/translator.php b/lib/helper/translator.php index 743c7d7..bd04bf8 100644 --- a/lib/helper/translator.php +++ b/lib/helper/translator.php @@ -4,7 +4,7 @@ * * @package tzn_helpers * @author Stan Ozier - * @since 0.3 + * @version 0.4 * @copyright GNU Lesser General Public License (LGPL) version 3 */ @@ -12,6 +12,7 @@ * Translator Helper * * translates everything + * @since 0.3 * @todo test it all */ class TranslatorHelper { @@ -22,40 +23,98 @@ class TranslatorHelper { public function __construct() { $this->langDefault = $GLOBALS['config']['lang']['default']; $this->langUser = $GLOBALS['config']['lang']['user']; + $GLOBALS['lang'] = array(); } public function loadLangConfig() { - include_once(APP_LANGUAGE_PATH.$this->langDefault.'/config.php'); - include_once(APP_LANGUAGE_PATH.$this->langUser.'/config.php'); + if (file_exists(APP_LANGUAGE_PATH.$this->langUser.'/config.php')) { + include_once(APP_LANGUAGE_PATH.$this->langUser.'/config.php'); + } else { + include_once(APP_LANGUAGE_PATH.$this->langDefault.'/config.php'); + } + } + + public function loadLangFilesFromConfig() { + foreach($GLOBALS['config']['lang']['files'] as $file => $path) { + $full = $path.$this->langUser.'/'.$file; + if (file_exists($full)) { + include_once($full); + } else { + $full = $path.$this->langDefault.'/'.$file; + if (file_exists($full)) { + include_once($full); + } + } + } } public function loadLangFile($file) { - if (file_exists(APP_LANGUAGE_PATH.$this->langUser.'/'.$file.'.php')) { - include_once(APP_LANGUAGE_PATH.$this->langUser.'/'.$file.'.php'); + // try user language + foreach ($GLOBALS['config']['path']['lang'] as $path) { + if (file_exists(APP_INCLUDE_PATH.$path.$this->langUser.'/'.$file)) { + include_once(APP_INCLUDE_PATH.$path.$this->langUser.'/'.$file); + return true; + } } - if (file_exists(APP_LANGUAGE_PATH.$this->langDefault.'/'.$file.'.php')) { - include_once(APP_LANGUAGE_PATH.$this->langDefault.'/'.$file.'.php'); + // not found ? try default language + foreach ($GLOBALS['config']['path']['lang'] as $path) { + if (file_exists(APP_INCLUDE_PATH.$path.$this->langDefault.'/'.$file)) { + include_once(APP_INCLUDE_PATH.$path.$this->langDefault.'/'.$file); + return true; + } + } + return false; + } + + public static function getRawTranslation($section, $label, $field='') { + if (!array_key_exists($section, $GLOBALS['lang'])) { + FC::log_debug('can not find section '.$section); + return str_replace('_',' ',$label); + } + if (array_key_exists($label, $GLOBALS['lang'][$section])) { + if (is_array($GLOBALS['lang'][$section][$label])) { + return $GLOBALS['lang'][$section][$label][$field]; + } else { + return $GLOBALS['lang'][$section][$label]; + } + } else if (array_key_exists($label, $GLOBALS['lang'][$section])) { + if (is_array($GLOBALS['lang'][$section][$label])) { + return $GLOBALS['lang'][$section][$label][$field]; + } else { + return $GLOBALS['lang'][$section][$label]; + } + } else { + FC::log_debug('really can not find section '.$section); + return str_replace('_',' ',$label); } } - public function getTranslation($label, $section, $field='') { - if (!array_key_exists($section, $GLOBALS['lang'][$this->langDefault])) { - return $label; + public static function getTranslation($section, $label='', $field='') { + if (preg_match('/^\[([a-z_]+)\](.*)$/',$section, $matches)) { + $section = $matches[1]; + $label = $matches[2]; } - if (array_key_exists($label, $GLOBALS['lang'][$this->langUser][$section])) { - if (is_array($GLOBALS['lang'][$this->langUser][$section][$label])) { - return $GLOBALS['lang'][$this->langUser][$section][$label][$field]; - } else { - return $GLOBALS['lang'][$this->langUser][$section][$label]; - } - } else if (array_key_exists($label, $GLOBALS['lang'][$this->langDefault][$section])) { - if (is_array($GLOBALS['lang'][$this->langDefault][$section][$label])) { - return $GLOBALS['lang'][$this->langDefault][$section][$label][$field]; - } else { - return $GLOBALS['lang'][$this->langDefault][$section][$label]; - } - } else { - return $label; + $str = self::getRawTranslation($section, $label, $field); + if ($GLOBALS['config']['lang']['ucfirst']) { + return ucfirst($str); } + return $str; } + +} + +class TR extends TranslatorHelper { + + public static function get($section, $label, $field='') { + return self::getTranslation($section, $label, $field); + } + + public static function html($section, $label, $field='') { + return VarStr::html(self::getTranslation($section, $label, $field)); + } + + public static function phtml($section, $label, $field='') { + echo self::html($section, $label, $field); + } + } \ No newline at end of file diff --git a/lib/lang/en/common.php b/lib/lang/en/common.php new file mode 100644 index 0000000..cc34949 --- /dev/null +++ b/lib/lang/en/common.php @@ -0,0 +1,250 @@ + + * @version 0.4 + * @copyright GNU Lesser General Public License (LGPL) version 3 + */ + +$GLOBALS['lang']['data'] = array( + 'new' => 'new item', + 'read' => 'read this item', + 'view' => 'view details', + 'modify' => 'modify item', + 'delete' => 'delete this item', + 'delete_confirm' => 'really delete this item ?', + 'remove' => 'remove this item', + 'remove_confirm' => 'really remove from the list ?', + 'search' => 'search', + 'next' => 'next', + 'previous' => 'previous', + 'next_page' => 'next page', + 'previous_page' => 'previous page', + 'all' => 'all', + 'more' => 'more', + 'less' => 'less', + 'item_found' => 'item found', + 'items_found' => 'items found', + 'empty' => 'no data available' +); + +$GLOBALS['lang']['message'] = array( + 'saved' => 'data successfully saved', + 'created' => 'data successfully created', + 'updated' => 'data successfully updated', + 'deleted' => 'data successfully deleted', + 'removed' => 'data successfully removed' +); + +$GLOBALS['lang']['error'] = array( + 'db_no_connection' => 'can not connect to database', + 'db_no_database' => 'database not found', + 'db_sql_error' => 'database query error', + 'sql_injection' => 'possible SQL injection intended', + 'search_empty' => 'sorry, no item could be found', + 'not_found' => 'data not found', + 'login_failed' => 'login failed', + 'access_denied' => 'access denied', + 'data_denied' => 'access to data denied', + 'not_found_denied' => 'data not found or access denied', + 'action_failed' => 'requested action could not be performed', + 'form_error' => 'form contains error(s)', + 'compulsory_field' => 'information required', + 'account_disabled' => 'account is disabled', + 'account_expired' => 'account has expired', + 'account_not_found' => 'account does not exist', + 'username_required' => 'please enter your username', + 'username_not_found'=> 'username does not exists', + 'username_invalid' => 'not a valid username (avoid special characters or spaces)', + 'username_length' => 'username must have between '.APP_USER_NAME_MIN.' and '.APP_USER_NAME_MAX.' characters', + 'email_not_found' => 'email does not exists', + 'password_required' => 'password required', + 'password_invalid' => 'invalid password', + 'password_length' => 'password must have between '.APP_USER_PASS_MIN.' and '.APP_USER_PASS_MAX.' characters', + 'password_mismatch' => 'password and verification do not match', + 'password_recover' => 'password can not be recovered', + 'field_length' => 'too short or too long', + 'field_exists' => 'this entry already exists', + 'field_invalid' => 'entry is not valid', + 'field_mismatch' => 'entries do not match', + 'invalid_date' => 'not a valid date', + 'invalid_time' => 'not a valid time', + 'invalid_email' => 'e-mail address is not valid', + 'invalid_duration' => 'not a valid duration', + 'file_wrong_type' => 'wrong file type', + 'file_empty' => 'please select a file', + 'none_checked' => 'please check at least one item' +); + +$GLOBALS['lang']['security'] = array( + 'login' => 'login', + 'logout' => 'logout', + 'sign_in' => 'not a member? Sign in now', + 'my_account' => 'my account', + 'account' => 'account', + 'account_active' => 'account is activated', + 'account_not_active'=> 'account is not activated', + 'account_enabled' => 'account is enabled', + 'visit_count' => 'visits', + 'visit_fail_count' => 'failed login attempts', + 'access_denied' => 'access denied', + 'permission_denied' => 'permission denied', + 'session_expired' => 'your session has expired', + 'login_last_date' => 'Last login date', + 'login_last_address'=> 'Last login address' +); + +$GLOBALS['lang']['form'] = array( + 'compulsory' => 'compulsory', + 'username' => 'username', + 'password' => 'password', + 'password_confirm' => '(verification)', + 'auto_login' => 'remember me on this computer', + 'password_legend' => 'enter a password (and confirm) only if you want to change it.', + 'name' => 'name', + 'category' => 'category', + 'title' => 'title', + 'last_name' => 'last name', + 'middle_name' => 'middle name', + 'first_name' => 'first name', + 'nick_name' => 'nick name', + 'address' => 'address', + 'location' => 'location', + 'city' => 'city', + 'state' => 'state', + 'state_us_only' => 'for US members only', + 'country' => 'country', + 'time_zone' => 'time zone', + 'user_rights' => 'permissions', + 'email' => 'email', + 'subject' => 'subject', + 'body' => 'body', + 'comment' => 'comment', + 'in' => 'in', + 'out' => 'out', + 'from' => 'from', + 'to' => 'to', + 'cc' => 'cc', + 'url' => 'URL', + 'website' => 'website', + 'description' => 'description', + 'user' => 'user', + 'member' => 'member', + 'author' => 'author', + 'status' => 'status', + 'file' => 'file', + 'image' => 'image', + 'thumbnail' => 'thumbnail', + 'document' => 'document', + 'file_legend' => 'please select a file by clicking the \'Browse..\' button', + 'file_name' => 'filename', + 'file_size' => 'file size', + 'file_type' => 'file type', + 'date' => 'date', + 'deadline' => 'deadline', + 'start' => 'start', + 'stop' => 'stop', + 'publish_date' => 'publish', + 'post_date' => 'post', + 'creation_date' => 'date of creation', + 'last_change_date' => 'last update', + 'last_visit_date' => 'last visit', + 'last_visit_addr' => 'from', + 'posted_on' => 'posted on', + 'published on' => 'published on', + 'by' => 'by', + 'action' => 'action' +); + +// buttons +$GLOBALS['lang']['button'] = array( + 'add' => 'add', + 'create' => 'create', + 'edit' => 'edit', + 'submit' => 'submit', + 'login' => 'login', + 'save' => 'save', + 'save_changes' => 'save changes', + 'save_and_add' => 'save and add more', + 'save_and_close' => 'save and close', + 'update' => 'update', + 'cancel' => 'cancel changes', + 'close' => 'close', + 'reset' => 'reset form', + 'delete' => 'delete', + 'remove' => 'remove', + 'start' => 'start', + 'stop' => 'stop', + 'enable' => 'enable', + 'disable' => 'disable', + 'activate' => 'activate', + 'deactivate' => 'deactivate', + 'next_step' => 'next step', + 'previous_step' => 'previous step', + 'back' => 'go back', + 'back_to_list' => 'back to list' +); + +$GLOBALS['lang']['date'] = array( + 'future_pre' => 'in', // eg. "in" 2 days + 'future_app' => '', // ie. when keyword needs to be appended to the date + 'past_pre' => '', // eg. "il y a" 2 jours (french) + 'past_app' => 'ago', // eg. 2 days "ago" + 'yesterday' => 'yesterday', + 'today' => 'today', + 'tomorrow' => 'tomorrow', + 'days' => 'days', + 'day' => 'day', + 'weeks' => 'weeks', + 'week' => 'week', + 'months' => 'months', + 'month' => 'month', + 'years' => 'years', + 'year' => 'year', + 'hour' => 'hour', + 'hours' => 'hours', + 'minute' => 'minute', + 'minutes' => 'minutes', + 'second' => 'second', + 'seconds' => 'seconds', + 'january' => 'january', + 'february' => 'february', + 'march' => 'march', + 'april' => 'april', + 'may' => 'may', + 'june' => 'june', + 'july' => 'july', + 'august' => 'august', + 'september' => 'september', + 'october' => 'october', + 'november' => 'november', + 'december' => 'december', + 'jan' => 'jan', + 'feb' => 'feb', + 'mar' => 'mar', + 'apr' => 'apr', + 'may' => 'may', + 'jun' => 'jun', + 'jul' => 'jul', + 'aug' => 'aug', + 'sep' => 'sep', + 'oct' => 'oct', + 'nov' => 'nov', + 'dec' => 'dec', + 'monday' => 'monday', + 'tuesday' => 'tuesday', + 'wednesday' => 'wednesday', + 'thursday' => 'thursday', + 'friday' => 'friday', + 'saturday' => 'saturday', + 'sunday' => 'sunday', + 'mon' => 'mon', + 'tue' => 'tue', + 'wed' => 'wed', + 'thu' => 'thu', + 'fri' => 'fri', + 'sat' => 'sat', + 'sun' => 'sun' +); \ No newline at end of file diff --git a/lib/lang/en/config.php b/lib/lang/en/config.php new file mode 100644 index 0000000..ce81ec3 --- /dev/null +++ b/lib/lang/en/config.php @@ -0,0 +1,15 @@ + + * @version 0.4 + * @copyright GNU Lesser General Public License (LGPL) version 3 + */ + + +$GLOBALS['config']['lang']['specialchars'] = 2; +$GLOBALS['config']['lang']['ucfirst'] = false; + +setLocale(LC_ALL, 'en_EN.UTF-8', 'en_GB.utf8', 'en_US.utf8', 'en_EN', 'en'); \ No newline at end of file diff --git a/lib/lang/fr/common.php b/lib/lang/fr/common.php new file mode 100644 index 0000000..d2858a4 --- /dev/null +++ b/lib/lang/fr/common.php @@ -0,0 +1,250 @@ + + * @version 0.4 + * @copyright GNU Lesser General Public License (LGPL) version 3 + */ + +$GLOBALS['lang']['data'] = array( + 'new' => 'nouvel élément', + 'read' => 'lire la suite', + 'view' => 'voire les détails', + 'modify' => 'modifier', + 'delete' => 'supprimer', + 'delete_confirm' => 'réellemment supprimer cet élément ?', + 'remove' => 'retirer cet élément', + 'remove_confirm' => 'réellemment retirer cet élément ?', + 'search' => 'chercher', + 'next' => 'suivant', + 'previous' => 'précédent', + 'next_page' => 'page suivante', + 'previous_page' => 'page précédente', + 'all' => 'tous', + 'more' => 'plus', + 'less' => 'moins', + 'item_found' => 'élément trouvé', + 'items_found' => 'éléments trouvés', + 'empty' => 'aucune donnée trouvée' +); + +$GLOBALS['lang']['message'] = array( + 'saved' => 'données enregistrées avec succès', + 'created' => 'données créées avec succès', + 'updated' => 'données mises à jour', + 'deleted' => 'données supprimées avec succès', + 'removed' => 'éléments retirés' +); + +$GLOBALS['lang']['error'] = array( + 'db_no_connection' => 'impossible de se connecter à la base de données', + 'db_no_database' => 'base de données introuvable', + 'db_sql_error' => 'échec de la requete SQL', + 'sql_injection' => 'possibilité SQL injection intended', + 'search_empty' => 'aucun élément trouvé', + 'not_found' => 'données introuvable', + 'login_failed' => 'echec de l\'identification', + 'access_denied' => 'accès interdit', + 'data_denied' => 'accès refusé', + 'not_found_denied' => 'données non trouvées ou accès refusé', + 'action_failed' => 'echec de la commande', + 'form_error' => 'le formulaire content des erreurs', + 'compulsory_field' => 'donnée obilgatoire', + 'account_disabled' => 'compte désactivé', + 'account_expired' => 'le compte a expiré', + 'account_not_found' => 'compte introuvable', + 'username_required' => 'veuillez saisir un nom d\'utilisateur', + 'username_not_found'=> 'nom utilisateur introuvable', + 'username_invalid' => 'nom utilisateur non valide (éviter espaces et caractères spéciaux)', + 'username_length' => 'le nom doit avoir entre '.APP_USER_NAME_MIN.' et '.APP_USER_NAME_MAX.' caractères', + 'email_not_found' => 'courriel introuvable', + 'password_required' => 'mot de passe requis', + 'password_invalid' => 'mauvais mot de passe', + 'password_length' => 'le mot de passe doit avoir entre '.APP_USER_PASS_MIN.' et '.APP_USER_PASS_MAX.' caractères', + 'password_mismatch' => 'le mot de passe ne correspond pas', + 'password_recover' => 'impossible de récuperer le mot de passe', + 'field_length' => 'trop court ou trop long', + 'field_exists' => 'un entrée identique existe déjà', + 'field_invalid' => 'donnée non valide', + 'field_mismatch' => 'les données ne correspondent pas', + 'invalid_date' => 'date non valide', + 'invalid_time' => 'heure non valide', + 'invalid_email' => 'adresse non valide', + 'invalid_duration' => 'durée non valide', + 'file_wrong_type' => 'mauvais type de fichier', + 'file_empty' => 'veuillez sélectionner un fichier', + 'none_checked' => 'veuillez sélectionner au moins un élément' +); + +$GLOBALS['lang']['security'] = array( + 'login' => 'connexion', + 'logout' => 'déconnexion', + 'sign_in' => 'pas encore membre? cliquez ici', + 'my_account' => 'mon compte', + 'account' => 'compte', + 'account_active' => 'compte activé', + 'account_not_active'=> 'compte désactivé', + 'account_enabled' => 'compte activé', + 'visit_count' => 'visites', + 'visit_fail_count' => 'echecs de connexion', + 'access_denied' => 'accès refusé', + 'permission_denied' => 'permission refusée', + 'session_expired' => 'votre session a expiré', + 'login_last_date' => 'date dernière connexion', + 'login_last_address'=> 'adresse dernière connexion' +); + +$GLOBALS['lang']['form'] = array( + 'compulsory' => 'requis', + 'username' => 'utilisateur', + 'password' => 'mot de passe', + 'password_confirm' => '(vérification)', + 'auto_login' => 'm\'identifier automatiquement depuis cet ordinateur', + 'password_legend' => 'saisir un mot de passe uniquement pour en changer.', + 'name' => 'nom', + 'category' => 'catégorie', + 'title' => 'titre', + 'last_name' => 'nom de famille', + 'middle_name' => '', + 'first_name' => 'prénom', + 'nick_name' => 'surnom', + 'address' => 'adresse', + 'location' => 'lieu', + 'city' => 'ville', + 'state' => 'état', + 'state_us_only' => 'pour les USA uniquement', + 'country' => 'pays', + 'time_zone' => 'fuseau horaire', + 'user_rights' => 'permissions', + 'email' => 'courriel', + 'subject' => 'sujet', + 'body' => 'message', + 'comment' => 'commentaire', + 'in' => 'entrant', + 'out' => 'sortant', + 'from' => 'expéditeur', + 'to' => 'destinatire', + 'cc' => 'copie à', + 'url' => 'URL', + 'website' => 'site internet', + 'description' => 'description', + 'user' => 'utilisateur', + 'member' => 'membre', + 'author' => 'auteur', + 'status' => 'état', + 'file' => 'fichier', + 'image' => 'image', + 'thumbnail' => 'aperçu', + 'document' => 'document', + 'file_legend' => 'veuillez choisir un fichier en cliquant sur \'Parcourir...\'', + 'file_name' => 'nom du fichier', + 'file_size' => 'taille du fichier', + 'file_type' => 'type du fichier', + 'date' => 'date', + 'deadline' => 'échéance', + 'start' => 'début', + 'stop' => 'fin', + 'publish_date' => 'publication', + 'post_date' => 'envoi', + 'creation_date' => 'date de création', + 'last_change_date' => 'dernière mise à jour', + 'last_visit_date' => 'dernière visite', + 'last_visit_addr' => 'depuis', + 'posted_on' => 'envoyée le', + 'published on' => 'publiée le', + 'by' => 'par', + 'action' => 'action' +); + +// buttons +$GLOBALS['lang']['button'] = array( + 'add' => 'ajouter', + 'create' => 'créer', + 'edit' => 'modifier', + 'submit' => 'soumettre', + 'login' => 'indentifier', + 'save' => 'enregistrer', + 'save_changes' => 'enregistrer les modifications', + 'save_and_add' => 'enregistrer et créer à nouveau', + 'save_and_close' => 'enregistrer et fermer', + 'update' => 'mettre à jour', + 'cancel' => 'annuler', + 'close' => 'fermer', + 'reset' => 'réinitialiser', + 'delete' => 'supprimer', + 'remove' => 'retirer', + 'start' => 'démarrer', + 'stop' => 'arrêter', + 'enable' => 'activer', + 'disable' => 'désactiver', + 'activate' => 'activer', + 'deactivate' => 'désactiver', + 'next_step' => 'étape suivante', + 'previous_step' => 'étape précédente', + 'back' => 'revenir', + 'back_to_list' => 'revenir en arrière' +); + +$GLOBALS['lang']['date'] = array( + 'future_pre' => 'dans', // eg. "in" 2 days + 'future_app' => '', // ie. when keyword needs to be appended to the date + 'past_pre' => 'il y a', // eg. "il y a" 2 jours (french) + 'past_app' => '', // eg. 2 days "ago" + 'yesterday' => 'hier', + 'today' => 'aujourd\'hui', + 'tomorrow' => 'demain', + 'days' => 'jours', + 'day' => 'jour', + 'weeks' => 'semaines', + 'week' => 'semaine', + 'months' => 'mois', + 'month' => 'mois', + 'years' => 'années', + 'year' => 'année', + 'hour' => 'heure', + 'hours' => 'heures', + 'minute' => 'minute', + 'minutes' => 'minutes', + 'second' => 'seconde', + 'seconds' => 'secondes', + 'january' => 'janvier', + 'february' => 'février', + 'march' => 'mars', + 'april' => 'avril', + 'may' => 'mai', + 'june' => 'juin', + 'july' => 'juillet', + 'august' => 'août', + 'september' => 'septembre', + 'october' => 'octobre', + 'november' => 'novembre', + 'december' => 'décembre', + 'jan' => 'jan', + 'feb' => 'fev', + 'mar' => 'mar', + 'apr' => 'avr', + 'may' => 'mai', + 'jun' => 'juin', + 'jul' => 'juil', + 'aug' => 'aout', + 'sep' => 'sep', + 'oct' => 'oct', + 'nov' => 'nov', + 'dec' => 'dec', + 'monday' => 'lundi', + 'tuesday' => 'mardi', + 'wednesday' => 'mercredi', + 'thursday' => 'jeudi', + 'friday' => 'vendredi', + 'saturday' => 'samedi', + 'sunday' => 'dimanche', + 'mon' => 'lun', + 'tue' => 'mar', + 'wed' => 'mer', + 'thu' => 'jeu', + 'fri' => 'ven', + 'sat' => 'sam', + 'sun' => 'dim' +); \ No newline at end of file diff --git a/lib/lang/fr/config.php b/lib/lang/fr/config.php new file mode 100644 index 0000000..93514c9 --- /dev/null +++ b/lib/lang/fr/config.php @@ -0,0 +1,15 @@ + + * @version 0.4 + * @copyright GNU Lesser General Public License (LGPL) version 3 + */ + + +$GLOBALS['config']['lang']['specialchars'] = 3; +$GLOBALS['config']['lang']['ucfirst'] = false; + +setLocale(LC_ALL, 'fr_FR.UTF-8', 'fr_FR', 'fr'); \ No newline at end of file diff --git a/lib/model/user.php b/lib/model/user.php index d31cf72..97e3924 100644 --- a/lib/model/user.php +++ b/lib/model/user.php @@ -4,7 +4,7 @@ * * @package tzn_models * @author Stan Ozier - * @version 0.2 + * @version 0.4 * @since 0.1 * @copyright GNU Lesser General Public License (LGPL) version 3 */ @@ -86,38 +86,18 @@ abstract class UserModel extends Model { 'abcdefghijklmnopqrstuvwxyz' .'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')); if ($pass1) { - if ((strlen($pass1) >= APP_USER_PASS_MIN) - && (strlen($pass1) <= APP_USER_PASS_MAX)) + $arr = explode(',',$this->_properties[$key]); + $class = array_shift($arr); + if (VarPss::checkValid($pass1, $arr)) { - $salt = $this->get('salt'); + $this->setRawPassword($pass1, $this->get('salt')); - switch (APP_AUTH_PASSWORD_MODE) { - case 1: - $this->set('password',crypt($pass1 , $salt)); - break; - case 2: - $this->set('password',AuthHelper::getDbPass("ENCRYPT('$pass1','$salt')")); - break; - case 3: - $this->set('password',AuthHelper::getDbPass("ENCODE('$pass1','$salt')")); - break; - case 4: - case 5: - $this->set('password',AuthHelper::getDbPass("MD5('$pass1')")); - break; - default: - $iv = mcrypt_create_iv (mcrypt_get_iv_size(MCRYPT_3DES - , MCRYPT_MODE_ECB), MCRYPT_RAND); - $crypttext = mcrypt_encrypt(APP_AUTH_PASSWORD_MODE, $salt - , $pass1, MCRYPT_MODE_ECB, $iv); - $this->set('password',bin2hex($crypttext)); - } } else { $this->_error['password'] = 'user_pass_length'; return false; } } else { - $this->set('password',''); + $this->data['password'] = ''; } return true; } else { @@ -129,6 +109,31 @@ abstract class UserModel extends Model { } } + public function setRawPassword($pass, $salt) { + switch (APP_AUTH_PASSWORD_MODE) { + case 1: + $this->data['password'] = crypt($pass , $salt); + break; + case 2: + $this->data['password'] = AuthHelper::getDbPass("ENCRYPT('$pass','$salt')"); + break; + case 3: + $this->data['password'] = AuthHelper::getDbPass("ENCODE('$pass','$salt')"); + break; + case 4: + case 5: + $this->data['password'] = AuthHelper::getDbPass("MD5('$pass')"); + break; + default: + $iv = mcrypt_create_iv (mcrypt_get_iv_size(MCRYPT_3DES + , MCRYPT_MODE_ECB), MCRYPT_RAND); + $crypttext = mcrypt_encrypt(APP_AUTH_PASSWORD_MODE, $salt + , $pass, MCRYPT_MODE_ECB, $iv); + $this->data['password'] = bin2hex($crypttext); + break; + } + } + public function setupTimeZone() { if (!$this->isEmpty('time_zone')) { try { diff --git a/skin/default/css/freak.css b/skin/default/css/freak.css index 1a2538f..094ed76 100644 --- a/skin/default/css/freak.css +++ b/skin/default/css/freak.css @@ -113,31 +113,64 @@ img.frgt { text-align: right; width: 150px; } -#dtop ul { - padding: 12px 0 0 0; - height: 28px; -} -#dtop ul li { - float: left; - list-style: none; - margin-right: 8px; - padding: 0 0 8px 10px; - height: 20px; -} -#dtop ul li.active { - background: url(../img/top-tab.png) no-repeat left 0; -} -#dtop ul li a { - display: block; - color: #fff; +#dtop #duser p a { text-decoration: none; - padding: 6px 10px 0 0; } -#dtop ul li a:hover { +#dtop #duser p a:hover { + color: #fff; } -#dtop ul li.active a { +#dtop #duser p a small { + color: #9cf; +} +#dtop #duser p a:hover small { + color: #cce3ff; +} +#dtop #duser ul { + top: 20px; + background-color: #ccc; + border: 1px solid #999; + margin: 0; + padding: 0; + position: absolute; + right: 5px; + min-width: 150px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-border-top-right-radius: 0; + -moz-border-radius-topright: 0; + border-radius: 5px 0 5px 5px; +} +#dtop #duser ul#dmenu { + display: none; +} +#dtop #duser ul li { + font-size: 11px; + list-style: none; + padding: 0; + text-align: left; +} +#dtop #duser ul li a { + color: #333; + display: block; + text-decoration: none; + padding: 2px 4px; +} +#dtop #duser ul li:first-child a { + -webkit-border-top-left-radius: 5px; + -moz-border-radius-topleft: 5px; + border-radius: 5px 0 0 0; +} +#dtop #duser ul li:last-child a { + -webkit-border-bottom-left-radius: 5px; + -webkit-border-bottom-right-radius: 5px; + -moz-border-radius-bottomleft: 5px; + -moz-border-radius-bottomright: 5px; + border-radius: 0 0 5px 5px; +} +#dtop #duser ul li a:hover { + background-color: #fff; color: #000; - background: url(../img/top-tab.png) no-repeat right 0; } /* search form */ form#search p { diff --git a/skin/default/css/tracker.css b/skin/default/css/tracker.css index a0ec4a9..b50c7de 100644 --- a/skin/default/css/tracker.css +++ b/skin/default/css/tracker.css @@ -3,9 +3,9 @@ position: absolute; top: 0; left: 50%; - margin-left: -250px; + margin-left: -220px; padding: 6px 10px; - width: 500px; + width: 440px; color: #036; background-color: transparent; z-index: 10; @@ -40,7 +40,7 @@ } #drun p input { color: #036; - width: 300px; + width: 340px; border: 0; padding: 2px 5px 3px; background-color: #39c; @@ -66,9 +66,15 @@ float: right; } #drun button { - opacity: 0.5; - -moz-opacity: 0.5; - filter: alpha(opacity=50); + opacity: 0.85; + -moz-opacity: 0.85; + filter: alpha(opacity=85); + background: url(../img/buttons.png) no-repeat 0 0; + width: 34px; + height: 22px; + text-indent: -9999px; + overflow: hidden; + border: 0 none; } #drun button:hover, #drun button:focus { opacity: 1; @@ -76,6 +82,24 @@ filter: alpha(opacity=100); outline: 0 none; } +#drun button#b_save { + +} +#drun button#b_start { + background-position: -40px 0; +} +#drun button#b_resume { + background-position: -80px 0; +} +#drun button#b_pause { + background-position: -120px 0; +} +#drun button#b_stop { + background-position: -160px 0; +} +#drun button#b_close { + background-position: -200px 0; +} #timerstatus.loading { background: url(../img/barloader.gif) no-repeat center center; } diff --git a/skin/default/img/buttons.png b/skin/default/img/buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..091dbdf6834e40049bf1fe7848505616dc0184eb GIT binary patch literal 2641 zcmd^>`#;l*AICqATuPkdL=-7Uq8t&;C6@@Bdy1Jj?w2(&WvgwLogJ6d+)kLe&vjxg zml=k+MQcH+;|R$34+rtEh3TV;+!!PWX5yzU0htM5)^+i_ z4C~%bclUrG(>lw#k--S)Tt73TmD=4GnOr5gEydv^cqA1mtt$Hr?%d&fM0g^CG5F|; z*7}|*pR_ax>ZUPUE;u{8fXzl!pzWKcq&`aRjS8R`iA%ckI*0+-P z$n=2$%RS3HKEHfy%$Y<+CM3ipCgKVT9FWMEy_ocdhD=72zpsD9lL)otQ^Ijp8H*)9 zC7)KuY};#t-h}!@Ue75mwv5kW>@hU9HO#%eUGH1D!C*80&NPYkyt_<(bTDf(Jc%T? zw!XHE$B#Yy{fi3nP41eM#2dyA2b7j(-+lX|zO#5>fKF~B?@bT#`FUew<*fI4ELIs3 z=@1a$Ar!utXl_nOKqe-}6cpgJ)4O#PHvs|MLLuU!*hvK;o@~t+fY! zvM1-@?IUpDLDRT~a>S64y5Nkii_4KdstZ%kIl1?zXvK2HvoNlFm-jCTWGmBA8QW!D z3cRdV?bIpVKG{QYa}El2UE+$vL-G<)wojtI@M5Fb)1kj2RofjV7wAzLq)3L~ym0Cd z`g81Hf}kqO^A{$b5U36A0SI?*zAR^SKF=F30Iq-t?o%CldHT$Y@6RbpbP&Te?7w%8Ku z`W5pBX9>`snoU}tr|A{Q6mt^P^$tvYj=t9_2Gp!|W)ajMLx_l^sH^QdCDr(l{ zlBNw@?`=wq%%y8zZE7+zBnn`y3UhE)_)bQ zX|7JI9Iogfgv|NXmutNcg?8AQ#9mVF`;Vw{qEe9I!u!sYMh-~Y?C!dxA_W511rhtUsr(l)RIC;_($Sa+0}jBA6%D zd4GFfWzjBeI5>whd3Bcj?VoT?S~kM(U2vfmh2k9(nlmwM<_<0P6K6oSev^es%sy!t z0%7uKqwz;(a<|V}$T?0K^DKXq7IJ8P^J~vl17~Y$E==skm#4nasacVDCY#hh zYbWxJLv@2V=%bT^jy#y`*5E{M(!i#6u*BXYh0_R=!28 zstj`x4gAYwlO0EgOd-`^cpsMj7QBmG_DA(=w56j@ea(c zTH_s+OIG4EE%n|^$yw_)OMaphuJ{^jodbr;wIBJ7FJlU4Y97V?a-(oetWKE)-^A-f zYc8&A%lr*L-h?2nNN6MQ7-^lwC+ceE;K|38{nGD0ks|z9k)KbrM0l#v`OBhqXWF!5 zO;F-_#Z7#NX;M`<8&fA~hVwi-AnaL=tPPDkRwBrLy7XDEF6Mm_=hn|O7$NulV|Bfo v`ln0RbN1%%`!co(Z0D_APV&qTolYR`F8n41Z8y6ABLWU~uC~vv1jPLppZ3MB literal 0 HcmV?d00001
deadline data->htmlDeadline(); ?>
priority data->htmlPriority(); ?>
status data->htmlStatus(); ?>
note data->html('note'); ?>