├── .gitignore ├── locales ├── ar_DZ.mo ├── ar_MA.mo ├── ca_ES.mo ├── de_DE.mo ├── el_GR.mo ├── en_GB.mo ├── es_AR.mo ├── es_CO.mo ├── es_EC.mo ├── es_ES.mo ├── et_EE.mo ├── fr_FR.mo ├── gl_ES.mo ├── he_IL.mo ├── hi_IN.mo ├── hu_HU.mo ├── it_IT.mo ├── ja_JP.mo ├── pl_PL.mo ├── pt_BR.mo ├── pt_PT.mo ├── ru_RU.mo ├── sr_RS.mo ├── tr_TR.mo ├── vi_VN.mo ├── localazy.json ├── actualtime.pot ├── ja_JP.po ├── he_IL.po ├── ca_ES.po ├── el_GR.po ├── en_GB.po ├── hu_HU.po ├── pt_PT.po ├── ar_MA.po ├── hi_IN.po ├── pl_PL.po ├── ar_DZ.po ├── sr_RS.po ├── vi_VN.po ├── es_AR.po ├── et_EE.po └── pt_BR.po ├── tools ├── phpstan │ ├── phpstan.phar │ ├── autoload.php │ ├── phpstan.neon │ ├── rules │ │ ├── PermissionControlRule.php │ │ ├── InputValidationRule.php │ │ ├── SensitiveInfoExposureRule.php │ │ ├── UnsafeFunctionsRule.php │ │ ├── SqlInjectionRule.php │ │ └── HardcodedPasswordRule.php │ └── stubs │ │ └── glpi_constants.php ├── php-cs-fixer.sh ├── generate_locales.sh ├── updatetranslations.sh ├── phpstan.sh ├── TICGAL_HEADER ├── extract_template.sh ├── modify_headers.pl └── make_release.sh ├── .twig_cs.dist.php ├── .php-cs-fixer.php ├── .phpcs.xml ├── composer.json ├── tests ├── bootstrap.php └── units │ ├── PluginActualtimeTask.php │ └── PluginActualtimeConfig.php ├── README.md ├── .github └── workflows │ └── continuous-integration.yml ├── report ├── actualtimeuser │ ├── actualtimeuser.en_GB.php │ └── actualtimeuser.php └── actualtimetotal │ ├── actualtimetotal.en_GB.php │ └── actualtimetotal.php ├── phpstan.neon ├── ajax ├── running.php └── changetimer.php ├── .travis.yml ├── front ├── running.php ├── config.form.php └── sourcetimer.form.php ├── CHANGELOG.md ├── templates └── forms │ ├── config.html.twig │ └── modify_timers.html.twig ├── inc ├── dashboard.class.php └── profile.class.php └── setup.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | vendor -------------------------------------------------------------------------------- /locales/ar_DZ.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/ar_DZ.mo -------------------------------------------------------------------------------- /locales/ar_MA.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/ar_MA.mo -------------------------------------------------------------------------------- /locales/ca_ES.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/ca_ES.mo -------------------------------------------------------------------------------- /locales/de_DE.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/de_DE.mo -------------------------------------------------------------------------------- /locales/el_GR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/el_GR.mo -------------------------------------------------------------------------------- /locales/en_GB.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/en_GB.mo -------------------------------------------------------------------------------- /locales/es_AR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/es_AR.mo -------------------------------------------------------------------------------- /locales/es_CO.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/es_CO.mo -------------------------------------------------------------------------------- /locales/es_EC.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/es_EC.mo -------------------------------------------------------------------------------- /locales/es_ES.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/es_ES.mo -------------------------------------------------------------------------------- /locales/et_EE.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/et_EE.mo -------------------------------------------------------------------------------- /locales/fr_FR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/fr_FR.mo -------------------------------------------------------------------------------- /locales/gl_ES.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/gl_ES.mo -------------------------------------------------------------------------------- /locales/he_IL.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/he_IL.mo -------------------------------------------------------------------------------- /locales/hi_IN.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/hi_IN.mo -------------------------------------------------------------------------------- /locales/hu_HU.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/hu_HU.mo -------------------------------------------------------------------------------- /locales/it_IT.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/it_IT.mo -------------------------------------------------------------------------------- /locales/ja_JP.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/ja_JP.mo -------------------------------------------------------------------------------- /locales/pl_PL.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/pl_PL.mo -------------------------------------------------------------------------------- /locales/pt_BR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/pt_BR.mo -------------------------------------------------------------------------------- /locales/pt_PT.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/pt_PT.mo -------------------------------------------------------------------------------- /locales/ru_RU.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/ru_RU.mo -------------------------------------------------------------------------------- /locales/sr_RS.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/sr_RS.mo -------------------------------------------------------------------------------- /locales/tr_TR.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/tr_TR.mo -------------------------------------------------------------------------------- /locales/vi_VN.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/locales/vi_VN.mo -------------------------------------------------------------------------------- /tools/phpstan/phpstan.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ticgal/actualtime/HEAD/tools/phpstan/phpstan.phar -------------------------------------------------------------------------------- /.twig_cs.dist.php: -------------------------------------------------------------------------------- 1 | in(__DIR__ . '/templates/') 9 | ->name('*.html.twig') 10 | ->ignoreVCSIgnored(true); 11 | 12 | return Twigcs\Config\Config::create() 13 | ->setFinder($finder) 14 | ->setRuleSet(\Glpi\Tools\GlpiTwigRuleset::class) 15 | ; -------------------------------------------------------------------------------- /locales/localazy.json: -------------------------------------------------------------------------------- 1 | { 2 | "upload": { 3 | "type": "pot", 4 | "deprecate": "project", 5 | "files": [ 6 | { 7 | "pattern": "actualtime.pot" 8 | }, 9 | { 10 | "group": "existing", 11 | "file": "actualtime.pot", 12 | "pattern": "./*.po", 13 | "type": "po", 14 | "lang": "${autodetectLang}" 15 | } 16 | ] 17 | }, 18 | "download": { 19 | "files": "${languageCode}_${regionCode}.po", 20 | "includeSourceLang": true 21 | } 22 | } -------------------------------------------------------------------------------- /.php-cs-fixer.php: -------------------------------------------------------------------------------- 1 | in(__DIR__) 8 | ->name('*.php') 9 | ->ignoreVCSIgnored(true); 10 | 11 | $config = new Config(); 12 | 13 | $rules = [ 14 | '@PER-CS2.0' => true, 15 | 'trailing_comma_in_multiline' => ['elements' => ['arguments', 'array_destructuring', 'arrays']], // For PHP 7.4 compatibility 16 | ]; 17 | 18 | return $config 19 | ->setRules($rules) 20 | ->setFinder($finder) 21 | ->setUsingCache(false); -------------------------------------------------------------------------------- /tools/php-cs-fixer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TOOL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" 4 | cd "$TOOL_DIR/.." 5 | 6 | if [ ! -f ".php-cs-fixer.php" ]; then 7 | echo "Error: The configuration file doesn't exist in .php-cs-fixer.php" 8 | exit 1 9 | fi 10 | 11 | if [ ! -f "vendor/bin/php-cs-fixer" ]; then 12 | echo "Error: PHP CS Fixer not found in vendor/bin/php-cs-fixer" 13 | exit 1 14 | fi 15 | 16 | # vendor/bin/php-cs-fixer check --config=.php-cs-fixer.php to check problems 17 | PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --no-interaction -------------------------------------------------------------------------------- /.phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | . 4 | /.git/ 5 | ^node_modules/ 6 | ^vendor/ 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tools/phpstan/autoload.php: -------------------------------------------------------------------------------- 1 | , YEAR./TICGAL, $(date +%Y)/" actualtime.pot 13 | sed -i "s/YEAR/$(date +%Y)/" actualtime.pot 14 | 15 | localazy upload 16 | localazy download 17 | 18 | for a in $(ls *.po); do 19 | msgmerge -U $a actualtime.pot 20 | msgfmt $a -o "${a%.*}.mo" 21 | done 22 | rm -f *.po~ -------------------------------------------------------------------------------- /tools/updatetranslations.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CUR_PATH="`dirname \"$0\"`" 4 | 5 | cd "$CUR_PATH/.." 6 | 7 | xgettext *.php */*.php -o locales/actualtime.pot -L PHP --add-comments=TRANS --from-code=UTF-8 --force-po -k --keyword=__:1,2t --keyword=_x:1,2,3t --keyword=__s:1,2t --keyword=_sx:1,2,3t --keyword=_n:1,2,3,4t --keyword=_sn:1,2t --keyword=_nx:1,2,3t --copyright-holder "TICGAL" --package-name "Actualtime Plugin" --package-version "1.1.0" --msgid-bugs-address=https://github.com/ticgal/actualtime/issues 8 | 9 | cd locales 10 | 11 | sed -i "s/SOME DESCRIPTIVE TITLE/ActualTime Glpi Plugin/" actualtime.pot 12 | sed -i "s/FIRST AUTHOR , YEAR./TICGAL, $(date +%Y)/" actualtime.pot 13 | sed -i "s/YEAR/$(date +%Y)/" actualtime.pot 14 | 15 | for a in $(ls *.po); do 16 | msgmerge -U $a actualtime.pot 17 | msgfmt $a -o "${a%.*}.mo" 18 | done 19 | rm -f *.po~ 20 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | }, 4 | "require-dev": { 5 | "friendsofphp/php-cs-fixer": "^3.75", 6 | "friendsoftwig/twigcs": "^6.1", 7 | "glpi-project/tools": "^0.7.5", 8 | "php-parallel-lint/php-parallel-lint": "^1.4", 9 | "phpstan/extension-installer": "^1.4", 10 | "phpstan/phpstan": "^2.1", 11 | "phpstan/phpstan-deprecation-rules": "^2.0" 12 | }, 13 | "config": { 14 | "optimize-autoloader": true, 15 | "platform": { 16 | "php": "8.1.0" 17 | }, 18 | "sort-packages": true, 19 | "allow-plugins": { 20 | "phpstan/extension-installer": true 21 | } 22 | }, 23 | "autoload": { 24 | "psr-4": { 25 | "CustomPHPStanRules\\": "tools/phpstan/rules/" 26 | } 27 | }, 28 | "autoload-dev": { 29 | "psr-4": { 30 | "Glpi\\Tools\\": "../../tools/src/" 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /tools/phpstan.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TOOL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" 4 | PHPSTAN_DIR="$TOOL_DIR/phpstan/phpstan.phar" 5 | CONFIG_FILE="$TOOL_DIR/phpstan/phpstan.neon" 6 | AUTOLOAD_FILE="$TOOL_DIR/phpstan/autoload.php" 7 | 8 | # if exist vendor/bin/phpstan, use it 9 | if [ -f "$TOOL_DIR/../vendor/bin/phpstan" ]; then 10 | cd "$TOOL_DIR/.." 11 | vendor/bin/phpstan analyze --ansi --memory-limit=2G --no-interaction 12 | exit 0 13 | fi 14 | 15 | # Verify folder 16 | if [ ! -f "$PHPSTAN_DIR" ]; then 17 | echo "Error: PHPStan not finded in $PHPSTAN_DIR" 18 | exit 1 19 | fi 20 | 21 | # Verify file 22 | if [ ! -f "$CONFIG_FILE" ]; then 23 | echo "Error: The configuration file doesn't exist in $CONFIG_FILE" 24 | exit 1 25 | fi 26 | 27 | # Clear cache 28 | #./tools/phpstan/phpstan.phar clear-result-cache 29 | 30 | # Execute PHPStan 31 | $PHPSTAN_DIR analyse -c "$CONFIG_FILE" -a "$AUTOLOAD_FILE" $TOOL_DIR/.. 32 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | checkStates(true); 22 | $plugin->getFromDBbyDir('actualtime'); 23 | 24 | //check from prerequisites as Plugin::install() does not! 25 | if (!plugin_actualtime_check_prerequisites()) { 26 | echo "\nPrerequisites are not met!"; 27 | die(1); 28 | } 29 | 30 | if (!$plugin->isInstalled('actualtime')) { 31 | call_user_func([$plugin, 'install'], $plugin->getID()); 32 | } 33 | 34 | if (!$plugin->isActivated('actualtime')) { 35 | call_user_func([$plugin, 'activate'], $plugin->getID()); 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ActualTime 2 | 3 | ActualTime Logo 4 | 5 | [![License](https://img.shields.io/badge/License-GNU%20AGPLv3-blue.svg?style=flat-square)](https://github.com/ticgal/actualtime/blob/master/LICENSE) 6 | [![Twitter](https://img.shields.io/badge/Twitter-TICGAL-blue.svg?style=flat-square)](https://twitter.com/ticgalcom) 7 | [![Web](https://img.shields.io/badge/Web-TICGAL-blue.svg?style=flat-square)](https://tic.gal/) 8 | [![Web](https://img.shields.io/badge/Web-ActualTime-blue.svg?style=flat-square)](https://tic.gal/glpi/glpi-plugins/actualtime-the-time-tracking-plugin-for-glpi/) 9 | [![Localazy](https://img.shields.io/badge/Translate-Localazy-cyan)](https://localazy.com/p/actualtime#translations) 10 | 11 | 12 | Adds actual time tracking for GLPI tasks. 13 | ### Setup 14 | Install it like any other GLPI plugin from Marketplace, or download and install it in the plugin folder. 15 | ### How to use 16 | When a standard user has a **To Do** task in a **ticket, change or project**, (new on ActualTime 3), he/she must click the start button to begin time tracking. 17 | Click on the stop button to end it. 18 | ### Additional features 19 | - Running timers 20 | - Planning view 21 | - New dashboard widgets 22 | - Searchable fields 23 | - Additional ticket stats on the GLPI ticket statistics tab 24 | -------------------------------------------------------------------------------- /tools/TICGAL_HEADER: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------- 2 | ActualTime plugin for GLPI 3 | Copyright (C) 2018-2025 by the TICGAL Team. 4 | https://www.tic.gal/ 5 | ------------------------------------------------------------------------- 6 | LICENSE 7 | This file is part of the ActualTime plugin. 8 | ActualTime plugin is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; either version 3 of the License, or 11 | (at your option) any later version. 12 | ActualTime plugin is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | You should have received a copy of the GNU General Public License 17 | along withOneTimeSecret. If not, see . 18 | ------------------------------------------------------------------------- 19 | @package ActualTime 20 | @author the TICGAL team 21 | @copyright Copyright (c) 2018-2025 TICGAL team 22 | @license AGPL License 3.0 or (at your option) any later version 23 | http://www.gnu.org/licenses/agpl-3.0-standalone.html 24 | @link https://www.tic.gal/ 25 | @since 2018 26 | ------------------------------------------------------------------------- 27 | -------------------------------------------------------------------------------- /.github/workflows/continuous-integration.yml: -------------------------------------------------------------------------------- 1 | name: "Continuous integration" 2 | 3 | on: 4 | push: 5 | branches: 6 | - "feature/**" 7 | - "bugfix/**" 8 | tags: 9 | - "*" 10 | workflow_dispatch: 11 | 12 | concurrency: 13 | group: "${{ github.workflow }}-${{ github.ref }}" 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | generate-ci-matrix: 18 | name: "Generate CI matrix" 19 | runs-on: "ubuntu-latest" 20 | outputs: 21 | matrix: ${{ steps.generate-ci-matrix.outputs.matrix }} 22 | steps: 23 | - name: "Generate CI matrix" 24 | id: "generate-ci-matrix" 25 | run: | 26 | MATRIX=' 27 | { 28 | "include": [ 29 | {"glpi-version": "10.0.x", "php-version": "8.4", "db-image": "mariadb:11.4"} 30 | ] 31 | } 32 | ' 33 | echo "matrix=$(echo $MATRIX | jq -c .)" >> $GITHUB_OUTPUT 34 | ci: 35 | name: "GLPI ${{ matrix.glpi-version }} - php:${{ matrix.php-version }} - ${{ matrix.db-image }}" 36 | needs: "generate-ci-matrix" 37 | strategy: 38 | fail-fast: false 39 | matrix: ${{ fromJson(needs.generate-ci-matrix.outputs.matrix) }} 40 | uses: "glpi-project/plugin-ci-workflows/.github/workflows/continuous-integration.yml@v1" 41 | with: 42 | plugin-key: "actualtime" 43 | glpi-version: "${{ matrix.glpi-version }}" 44 | php-version: "${{ matrix.php-version }}" 45 | db-image: "${{ matrix.db-image }}" 46 | -------------------------------------------------------------------------------- /tools/phpstan/phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | parallel: 3 | maximumNumberOfProcesses: 2 4 | level: 5 5 | bootstrapFiles: 6 | - '../../../../inc/based_config.php' 7 | - '../../../../inc/db.function.php' 8 | excludePaths: 9 | - '**/vendor/*' 10 | - '**/tests/*' 11 | - '**/tools/*' 12 | paths: 13 | - .. 14 | - tools/phpstan/rules 15 | stubFiles: 16 | - './stubs/glpi_constants.php' 17 | ignoreErrors: 18 | - '/Property CommonDBTM::\$input \(array\\) does not accept false/' 19 | - '/Access to property \$fields on an unknown class Plugin\w+/' 20 | - '/Access to constant \w+ on an unknown class Plugin\w+/' 21 | - '/Call to static method \w+\(\) on an unknown class Plugin\w+/' 22 | reportUnmatchedIgnoredErrors: false 23 | services: 24 | - 25 | class: CustomPHPStanRules\HardcodedPasswordRule 26 | tags: [phpstan.rules.rule] 27 | - 28 | class: CustomPHPStanRules\UnsafeFunctionsRule 29 | tags: [phpstan.rules.rule] 30 | - 31 | class: CustomPHPStanRules\InputValidationRule 32 | tags: [phpstan.rules.rule] 33 | - 34 | class: CustomPHPStanRules\SensitiveInfoExposureRule 35 | tags: [phpstan.rules.rule] 36 | - 37 | class: CustomPHPStanRules\SqlInjectionRule 38 | tags: [phpstan.rules.rule] 39 | - 40 | class: CustomPHPStanRules\PermissionControlRule 41 | tags: [phpstan.rules.rule] -------------------------------------------------------------------------------- /report/actualtimeuser/actualtimeuser.en_GB.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | $LANG['plugin_actualtime']['actualtimeuser'] = "ActualTime Users"; 33 | -------------------------------------------------------------------------------- /report/actualtimetotal/actualtimetotal.en_GB.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | $LANG['plugin_actualtime']['actualtimetotal'] = "ActualTime Total"; 33 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | parallel: 3 | maximumNumberOfProcesses: 2 4 | level: 5 5 | bootstrapFiles: 6 | - ../../inc/based_config.php 7 | paths: 8 | - ajax 9 | - front 10 | - inc 11 | - hook.php 12 | - setup.php 13 | - tools/phpstan/rules 14 | excludePaths: 15 | - '**/vendor/*' 16 | - '**/tests/*' 17 | - '**/tools/*' 18 | scanDirectories: 19 | - ../../inc 20 | - ../../src 21 | - tools/phpstan/rules 22 | stubFiles: 23 | - ../../stubs/glpi_constants.php 24 | ignoreErrors: 25 | - '/(Instantiated class|Class) (GlpiPlugin(\\\w+)+|Plugin\w+) not found/' 26 | - '/Call to (static )?method \w+\(\) on an unknown class (GlpiPlugin(\\\w+)+|Plugin\w+)/' 27 | - '/Access to (property \$\w+|constant \w+) on an unknown class (GlpiPlugin(\\\w+)+|Plugin\w+)/' 28 | - '/PHPDoc tag \@var for variable \$\w+ contains unknown class (GlpiPlugin(\\\w+)+|Plugin\w+)/' 29 | reportUnmatchedIgnoredErrors: false 30 | rules: 31 | - GlpiProject\Tools\PHPStan\Rules\GlobalVarTypeRule 32 | services: 33 | - 34 | class: CustomPHPStanRules\HardcodedPasswordRule 35 | tags: [phpstan.rules.rule] 36 | - 37 | class: CustomPHPStanRules\UnsafeFunctionsRule 38 | tags: [phpstan.rules.rule] 39 | - 40 | class: CustomPHPStanRules\InputValidationRule 41 | tags: [phpstan.rules.rule] 42 | - 43 | class: CustomPHPStanRules\SensitiveInfoExposureRule 44 | tags: [phpstan.rules.rule] 45 | - 46 | class: CustomPHPStanRules\SqlInjectionRule 47 | tags: [phpstan.rules.rule] 48 | - 49 | class: CustomPHPStanRules\PermissionControlRule 50 | tags: [phpstan.rules.rule] -------------------------------------------------------------------------------- /ajax/running.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | include("../../../inc/includes.php"); 33 | 34 | header("Content-Type: text/html; charset=UTF-8"); 35 | Html::header_nocache(); 36 | 37 | Session::checkLoginUser(); 38 | 39 | if (isset($_POST["action"])) { 40 | echo PluginActualtimeRunning::listRunning(); 41 | } 42 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | # - 5.6 4 | - 7.0 5 | - 7.1 6 | - 7.2 7 | - 7.3 8 | - nightly 9 | 10 | env: 11 | global: 12 | - DB=mysql 13 | matrix: 14 | - GLPIVER=9.5/bugfixes 15 | - GLPIVER=9.4/bugfixes 16 | - GLPIVER=9.3/bugfixes 17 | # - GLPIVER=master 18 | 19 | before_script: 20 | - composer self-update 21 | - composer require --dev atoum/atoum 22 | - git clone --depth=1 https://github.com/glpi-project/glpi -b $GLPIVER ../glpi && cd ../glpi 23 | - sed -e '/"php":/d' -i composer.json 24 | - sed -i 's/CssMin/cssmin/;s/Faker/Faker/;s/vfsStream/vfsstream/' composer.json 25 | - composer install --optimize-autoloader --no-dev 26 | - rm -f composer.lock 27 | - mysql -u root -e 'create database glpitest;' 28 | # Both 9.3 and 9.4: 29 | - if [[ -f "scripts/cliinstall.php" ]]; then php scripts/cliinstall.php --db=glpitest --user=root --tests; else bin/console glpi:database:install --config-dir=./tests --no-interaction --db-name=glpitest --db-user=root; fi 30 | - mv ../actualtime plugins/actualtime 31 | - cd plugins/actualtime 32 | - composer install -o 33 | 34 | 35 | script: 36 | - vendor/bin/robo --no-interaction code:cs 37 | - mysql -u root -e 'select version();' 38 | - ./vendor/bin/atoum --debug -bf tests/bootstrap.php -d tests/units/ 39 | 40 | 41 | # Permit failure on PHP nightly until Travis fix missing gd extension 42 | matrix: 43 | exclude: 44 | # - php: 5.6 45 | # env: GLPIVER=master 46 | # - php: 5.6 47 | # env: GLPIVER=9.4/bugfixes 48 | allow_failures: 49 | - php: nightly 50 | 51 | cache: 52 | directories: 53 | - $HOME/.composer/cache 54 | 55 | #notifications: 56 | # irc: 57 | # channels: 58 | # - "irc.freenode.org#channel" 59 | # on_success: change 60 | # on_failure: always 61 | # use_notice: true 62 | # skip_join: true 63 | -------------------------------------------------------------------------------- /front/running.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | include('../../../inc/includes.php'); 33 | 34 | $plugin = new Plugin(); 35 | if (!$plugin->isInstalled('actualtime') || !$plugin->isActivated('actualtime')) { 36 | Html::displayNotFoundError(); 37 | } 38 | Session::checkRight('plugin_actualtime_running', READ); 39 | 40 | Html::header( 41 | PluginActualtimeRunning::getTypeName(Session::getPluralNumber()), 42 | '', 43 | "admin", 44 | "pluginactualtimerunning", 45 | ); 46 | 47 | PluginActualtimeRunning::show(); 48 | 49 | Html::footer(); 50 | -------------------------------------------------------------------------------- /front/config.form.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | include('../../../inc/includes.php'); 33 | 34 | // Check if plugin is activated... 35 | $plugin = new Plugin(); 36 | if (!$plugin->isInstalled('actualtime') || !$plugin->isActivated('actualtime')) { 37 | Html::displayNotFoundError(); 38 | } 39 | 40 | Session::checkRight('config', UPDATE); 41 | 42 | $config = new PluginActualtimeConfig(); 43 | 44 | if (isset($_POST["update"])) { 45 | $config->check($_POST['id'], UPDATE); 46 | $config->update($_POST); 47 | Html::back(); 48 | } 49 | 50 | /** @var array $CFG_GLPI */ 51 | global $CFG_GLPI; 52 | 53 | $redirect = $CFG_GLPI["root_doc"] . "/front/config.form.php"; 54 | $redirect .= "?forcetab=" . urlencode('PluginActualtimeConfig$1'); 55 | Html::redirect($redirect); 56 | -------------------------------------------------------------------------------- /ajax/changetimer.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | include("../../../inc/includes.php"); 33 | 34 | header("Content-Type: text/html; charset=UTF-8"); 35 | Html::header_nocache(); 36 | 37 | Session::checkLoginUser(); 38 | 39 | if (isset($_REQUEST["itemtype"]) && isset($_REQUEST["task_id"])) { 40 | if (PluginActualtimeSourcetimer::checkItemtypeRight($_REQUEST["itemtype"])) { 41 | Html::popHeader( 42 | PluginActualtimeSourcetimer::getTypeName(1), 43 | $_SERVER['PHP_SELF'], 44 | true, 45 | 'actualtime', 46 | 'sourcetimer', 47 | ); 48 | $source = new PluginActualtimeSourcetimer(); 49 | $source->modalForm($_REQUEST["itemtype"], (int) $_REQUEST["task_id"]); 50 | Html::popFooter(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tools/phpstan/rules/PermissionControlRule.php: -------------------------------------------------------------------------------- 1 | getFile(); 35 | 36 | // Apply the rule only to Config.php or config.class.php 37 | if (!preg_match('/(\/|\\\\)(Config\.php|config\.class\.php)$/i', $filePath)) { 38 | return []; // Skip files that don't match 39 | } 40 | 41 | // Check if the class has a property named $rightname 42 | foreach ($node->getProperties() as $property) { 43 | if ($property instanceof Property && $property->props[0]->name->toString() === 'rightname') { 44 | $default = $property->props[0]->default; 45 | 46 | // Check if the default value of $rightname is 'config' 47 | if ($default instanceof String_ && $default->value === 'config') { 48 | return []; // No error if $rightname is correctly set to 'config' 49 | } 50 | 51 | return [ 52 | RuleErrorBuilder::message( 53 | 'The class in Config.php or config.class.php must have the $rightname attribute set to "config".', 54 | )->build(), 55 | ]; 56 | } 57 | } 58 | 59 | // If $rightname is not defined, report an error 60 | return [ 61 | RuleErrorBuilder::message( 62 | 'The class in Config.php or config.class.php must define the $rightname attribute with the value "config".', 63 | )->build(), 64 | ]; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Actualtime 2 | 3 | ## [3.2.2] - 2025/08/20 4 | ### Fixed 5 | - Limit and better control for timer modification 6 | 7 | ## [3.2.1] - 2025/06/10 8 | ### Fixed 9 | - ProjectTask parent key to start the timer 10 | 11 | ## [3.2.0] - 2025/02/27 12 | ### Added 13 | - Actualtimes for Problem tasks, contributed by Gambware 14 | 15 | ### Fixed 16 | - Task in progress message redirecting to the correct ticket 17 | 18 | ## [3.1.3] - 2025/01/27 19 | ### Fixed 20 | - Conflict with pending reasons with glpi solutions 21 | - Fix ChangeTasks foreign key and integration 22 | - Better control over null values 23 | 24 | ## 3.1.2 - 06/11/2024 25 | ### Bugfixes 26 | - Fix active task alert showing and redirecting to the correct page 27 | 28 | ## 3.1.1 - 10/10/2024 29 | ### Bugfixes 30 | - Fix change tech 31 | - Fix warning 32 | - Fix solution check 33 | - Fix tam check 34 | 35 | ## 3.1.0 - 30/04/2024 36 | ### Features 37 | - Modify the end date of timers 38 | ### Bugfixes 39 | - Fix permissions check of the timers running 40 | 41 | ## 3.0.1 - 15/04/2024 42 | ### Features 43 | - Use global functions 44 | ### Bugfixes 45 | - Fix field update 46 | 47 | ## 3.0.0 - 16/02/2024 48 | ### Features 49 | - Add compatibility with project task 50 | - Add compatibility with change task 51 | ### Bugfixes 52 | - Fix autostart css 53 | - Fix disabled button 54 | 55 | ## 2.2.0 -15/09/2023 56 | ### Features 57 | - Add block timer on different day 58 | - Add block timer on planned task 59 | - Permission to view activated timers 60 | - Filter activated timers by entities 61 | - Show location and assets in activated timers 62 | ### Bugfixes 63 | - Fix warning string 64 | - Fix update actiontime 65 | 66 | ## 2.1.2 - Internal - 05/09/2023 67 | ### Features 68 | - Add block timer on different day 69 | - Add block timer on planned task 70 | ### Bugfixes 71 | - Fix warning string 72 | 73 | ## 2.1.1 - Internal - 12/07/2023 74 | ### Features 75 | - Permission to view activated timers 76 | - Filter activated timers by entities 77 | - Show location and assets in activated timers 78 | ### Bugfixes 79 | - Fix update actiontime 80 | 81 | ## 2.1.0 - 15/03/2023 82 | ### Features 83 | - Show ticket and task id in planning 84 | - Stop timer when ticket delete 85 | - Change pop-up 86 | - Add button with task closed 87 | ### Bugfixes 88 | - Fix delete timer when purge task 89 | - Check user login 90 | - Fix widget sql 91 | 92 | ## 2.0.0 - 12/08/2022 93 | ### Features 94 | - Update the time of the task by marking it as done 95 | - UI enhancements 96 | - Drop auto open new task option 97 | ### Bugfixes 98 | - Fix sql ticket statistics 99 | -------------------------------------------------------------------------------- /templates/forms/config.html.twig: -------------------------------------------------------------------------------- 1 | {# 2 | #} 3 | 4 | {% import 'components/form/fields_macros.html.twig' as fields %} 5 | 6 | {% if options is not defined %} 7 | {% set options = {} %} 8 | {% endif %} 9 | 10 | {{ include('components/form/header.html.twig', {'in_twig': true, 'no_header': true}) }} 11 | 12 |
13 |
14 | 15 | {{ fields.dropdownArrayField( 16 | 'displayinfofor', 17 | item.fields['displayinfofor'], 18 | displayvalues, 19 | __('Enable timer on tasks', 'actualtime'), 20 | options|merge({'width': 'auto'}) 21 | ) }} 22 | 23 | {{ fields.dropdownYesNo( 24 | 'showtimerpopup', 25 | item.fields['showtimerpopup'], 26 | __('Display pop-up window with current running timer', 'actualtime'), 27 | options 28 | ) }} 29 | 30 | {{ fields.dropdownYesNo( 31 | 'showtimerinbox', 32 | item.fields['showtimerinbox'], 33 | __('Display actual time in closed task box (\'Processing ticket\' list)', 'actualtime'), 34 | options 35 | ) }} 36 | 37 | {{ fields.dropdownYesNo( 38 | 'autoopenrunning', 39 | item.fields['autoopenrunning'], 40 | __('Automatically open task with timer running', 'actualtime'), 41 | options 42 | ) }} 43 | 44 | {{ fields.dropdownYesNo( 45 | 'autoupdate_duration', 46 | item.fields['autoupdate_duration'], 47 | __('Automatically update the duration', 'actualtime'), 48 | options 49 | ) }} 50 | 51 | {{ fields.dropdownYesNo( 52 | 'planned_task', 53 | item.fields['planned_task'], 54 | __('Enable Timer Only on Scheduled Task Day', 'actualtime'), 55 | options 56 | ) }} 57 | 58 | {{ fields.dropdownYesNo( 59 | 'multiple_day', 60 | item.fields['multiple_day'], 61 | __('Enable Timer Only on Task\'s Start Day', 'actualtime'), 62 | options 63 | ) }} 64 | 65 | {{ fields.numberField( 66 | 'task_limit', 67 | item.fields['task_limit'], 68 | __('Task limit in hours for ActualTime', 'actualtime'), 69 | options|merge({ 70 | 'input_addclass': 'w-auto', 71 | 'min': 0, 72 | 'max': 24, 73 | 'step': 1 74 | }) 75 | ) }} 76 | 77 |
78 |
79 | 80 | {{ include('components/form/buttons.html.twig') }} -------------------------------------------------------------------------------- /tools/phpstan/rules/InputValidationRule.php: -------------------------------------------------------------------------------- 1 | getFile(); 42 | 43 | // Skip files in "ajax" or "front" directories 44 | if (strpos($filePath, '/ajax/') !== false || strpos($filePath, '/front/') !== false) { 45 | return []; // Do not apply the rule to these files 46 | } 47 | 48 | // If file is apirest.class.php, skip the rule 49 | if (strpos($filePath, '/apirest.class.php') !== false) { 50 | return []; // Do not apply the rule to this file 51 | } 52 | 53 | // Get the function name 54 | $functionName = $scope->getFunctionName(); 55 | 56 | // Allowed functions 57 | if (in_array($functionName, ['prepareInputForAdd', 'prepareInputForUpdate'], true)) { 58 | return []; // Do not apply the rule to these functions 59 | } 60 | 61 | if (is_string($node->name) && in_array($node->name, self::SUPERGLOBALS, true)) { 62 | // Check if the superglobal is being accessed with a specific key 63 | // If not, allow assignment Ex. $get = $_GET; 64 | if ($node->getAttribute('key') === null) { 65 | return []; 66 | } 67 | 68 | return [ 69 | RuleErrorBuilder::message( 70 | sprintf( 71 | 'The use of the superglobal "%s" without validation is discouraged out of ajax and front files.', 72 | print_r($node->name, true), 73 | ), 74 | )->build(), 75 | ]; 76 | } 77 | 78 | return []; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tools/phpstan/rules/SensitiveInfoExposureRule.php: -------------------------------------------------------------------------------- 1 | name instanceof Node\Name) { 37 | $functionName = (string) $node->name; 38 | if (in_array($functionName, self::SENSITIVE_FUNCTIONS, true)) { 39 | // Special handling for print_r 40 | if ($functionName === 'print_r') { 41 | // Check if the second argument is set and is `true` 42 | if (isset($node->args[1])) { 43 | $secondArg = $node->args[1]->value; 44 | 45 | // Allow only if the second argument is a literal `true` 46 | if ($secondArg->name->toLowerString() === 'true') { 47 | return []; // No error if print_r($var, true) 48 | } 49 | } 50 | 51 | // If no second argument or it's not `true`, report an error 52 | return [ 53 | RuleErrorBuilder::message( 54 | 'The use of "print_r" without the second argument as `true` may expose sensitive information and should be avoided in production environments.', 55 | ) 56 | ->tip('Use "print_r($var, true)" to avoid direct output or consider removing this call.') 57 | ->build(), 58 | ]; 59 | } 60 | 61 | return [ 62 | RuleErrorBuilder::message( 63 | sprintf( 64 | 'The use of the function "%s" may expose sensitive information and should be avoided in production environments.', 65 | $functionName, 66 | ), 67 | )->build(), 68 | ]; 69 | } 70 | } 71 | 72 | return []; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tools/phpstan/rules/UnsafeFunctionsRule.php: -------------------------------------------------------------------------------- 1 | build(), 55 | ]; 56 | } 57 | 58 | // Handle other unsafe functions 59 | if ($node instanceof Node\Expr\FuncCall && $node->name instanceof Node\Name) { 60 | $functionName = (string) $node->name; 61 | 62 | if (in_array($functionName, self::UNSAFE_FUNCTIONS, true)) { 63 | return [ 64 | RuleErrorBuilder::message( 65 | sprintf( 66 | 'The use of the unsafe function "%s" is prohibited for security reasons.', 67 | $functionName, 68 | ), 69 | )->build(), 70 | ]; 71 | } 72 | 73 | // Check for unsafe cryptographic functions 74 | if (in_array($functionName, self::UNSAFE_CRYPTO_FUNCTIONS, true)) { 75 | return [ 76 | RuleErrorBuilder::message( 77 | sprintf( 78 | 'The use of the insecure cryptographic function "%s" is discouraged. Use modern alternatives like "password_hash()" or "hash(\'sha256\', ...)" instead.', 79 | $functionName, 80 | ), 81 | )->build(), 82 | ]; 83 | } 84 | } 85 | 86 | return []; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tools/phpstan/rules/SqlInjectionRule.php: -------------------------------------------------------------------------------- 1 | expr instanceof Concat) { 34 | $left = $node->expr->left; 35 | $right = $node->expr->right; 36 | 37 | // Skip if neither side is a string literal 38 | if (!($left instanceof String_) && !($right instanceof String_)) { 39 | return []; 40 | } 41 | 42 | $variableName = $node->var->name ?? null; 43 | $sqlKeywords = ['sql', 'query', 'statement', 'db']; 44 | if ( 45 | is_string($variableName) 46 | && preg_match('/(' . implode('|', $sqlKeywords) . ')/i', $variableName) === 0 47 | ) { 48 | return []; // Skip if the variable name doesn't suggest SQL 49 | } 50 | 51 | // Check if the left or right side of the concatenation is a string containing SQL keywords 52 | if ( 53 | ($left instanceof String_ && $this->containsSqlKeywords($left->value)) || 54 | ($right instanceof String_ && $this->containsSqlKeywords($right->value)) 55 | ) { 56 | return [ 57 | RuleErrorBuilder::message( 58 | 'Detected a SQL query constructed with string concatenation, which may lead to SQL injection vulnerabilities. Use prepared statements instead.', 59 | )->build(), 60 | ]; 61 | } 62 | } 63 | 64 | return []; 65 | } 66 | 67 | /** 68 | * Checks if a string contains common SQL keywords. 69 | * 70 | * @param string $value 71 | * @return bool 72 | */ 73 | private function containsSqlKeywords(string $value): bool 74 | { 75 | $keywords = ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'WHERE', 'FROM', 'JOIN', 'DROP', 'ALTER']; 76 | foreach ($keywords as $keyword) { 77 | if (stripos($value, $keyword) !== false) { 78 | return true; 79 | } 80 | } 81 | return false; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tools/extract_template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_DIR=$(dirname "$(readlink -f "$0")") 4 | PARENT_FOLDER_PATH=$(dirname "$SCRIPT_DIR") 5 | PLUGINNAME=$(basename "$PARENT_FOLDER_PATH") 6 | 7 | POTFILE=$PLUGINNAME.pot 8 | LOCALES=$PARENT_FOLDER_PATH/locales 9 | 10 | # check if xgettext is installed 11 | if ! command -v xgettext &>/dev/null; then 12 | echo "Error: xgettext is not installed" 13 | exit 1 14 | fi 15 | 16 | # if no exist locales folder, create it 17 | if [ ! -d "$LOCALES" ]; then 18 | mkdir $LOCALES 19 | fi 20 | 21 | INIT_PWD=$PWD 22 | if [ ! "$PARENT_FOLDER_PATH" = "$INIT_PWD" ]; then 23 | cd $PARENT_FOLDER_PATH 24 | fi 25 | 26 | # Clean existing file 27 | rm -f $LOCALES/$POTFILE && touch $LOCALES/$POTFILE >/dev/null 28 | 29 | echo Searching PHP files... 30 | # Append locales from PHP 31 | xgettext $(find -type f -name "*.php") -o $LOCALES/$POTFILE -L PHP --add-comments=TRANS --from-code=UTF-8 --force-po --join-existing \ 32 | --keyword=__:1,2t -d $PLUGINNAME --copyright-holder "TICgal" >/dev/null 2>&1 33 | 34 | echo Searching JS files... 35 | # Append locales from JavaScript 36 | xgettext $(find -type f -name "*.js") -o $LOCALES/$POTFILE -L JavaScript --add-comments=TRANS --from-code=UTF-8 --force-po --join-existing \ 37 | --keyword=__:1,2t -d $PLUGINNAME --copyright-holder "TICgal" >/dev/null 2>&1 38 | 39 | echo Searching TWIG files... 40 | # Append locales from Twig templates 41 | for file in $(find ./templates -type f -name "*.twig"); do 42 | # 1. Convert file content to replace "{{ function(.*) }}" by "" and extract strings via std input 43 | # 2. Replace "standard input:line_no" by file location in po file comments 44 | contents=$(cat $file | sed -r "s|\{\{\s*([a-z0-9_]+\(.*\))\s*\}\}||gi") 45 | cat $file | perl -0pe "s/\{\{(.*?)\}\}//gism" | xgettext - -o $LOCALES/$POTFILE -L PHP --add-comments=TRANS --from-code=UTF-8 --force-po --join-existing \ 46 | --keyword=__:1,2t -d $PLUGINNAME --copyright-holder "TICgal" 47 | sed -i -r "s|standard input:([0-9]+)|$(echo $file | sed "s|./||"):\1|g" $LOCALES/$POTFILE 48 | done 49 | 50 | #Update main language 51 | LANG=C msginit --no-translator -i $LOCALES/$POTFILE -l en_GB -o $LOCALES/en_GB.po 52 | 53 | ### for using tx : 54 | ##tx set --execute --auto-local -r GLPI.glpipot 'locales/.po' --source-lang en_GB --source-file locales/glpi.pot 55 | ## tx push -s 56 | ## tx pull -a 57 | 58 | cd $LOCALES 59 | 60 | sed -i "s/SOME DESCRIPTIVE TITLE/$PLUGINNAME Glpi Plugin/" $POTFILE 61 | sed -i "s/FIRST AUTHOR , YEAR./TICgal, $(date +%Y)/" $POTFILE 62 | sed -i "s/YEAR/$(date +%Y)/" $POTFILE 63 | 64 | #Update all languages with localazy 65 | if command -v localazy &>/dev/null; then 66 | if [ -f "localazy.keys.json" ] && [ -f "localazy.json" ]; then 67 | localazy upload 68 | localazy download 69 | else 70 | echo "Missing credentials to update translations" 71 | fi 72 | fi 73 | 74 | #Compile all languages 75 | for a in $(ls *.po); do 76 | msgmerge -U $a $POTFILE 77 | msgfmt $a -o "${a%.*}.mo" 78 | done 79 | rm -f *.po~ 80 | 81 | cd $INIT_PWD -------------------------------------------------------------------------------- /tests/units/PluginActualtimeTask.php: -------------------------------------------------------------------------------- 1 | . 21 | -------------------------------------------------------------------------- 22 | @package ActualTime 23 | @author the TICGAL team 24 | @copyright Copyright (c) 2018-2022 TICGAL team 25 | @license AGPL License 3.0 or (at your option) any later version 26 | http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | @link https://www.tic.gal/ 28 | @since 2018-2022 29 | ---------------------------------------------------------------------- 30 | */ 31 | 32 | namespace tests\units; 33 | 34 | use atoum; 35 | 36 | class PluginActualtimeTask extends atoum 37 | { 38 | public function testRightname() 39 | { 40 | $this 41 | ->given($conf = $this->getTestedClassName()) 42 | ->string($conf::$rightname) 43 | ->isEqualTo('task'); 44 | } 45 | 46 | public function testGetTypeName() 47 | { 48 | $this 49 | ->if($class = $this->testedClass->getClass()) 50 | ->then 51 | ->string($class::getTypeName()) 52 | ->isNotEmpty(); 53 | } 54 | 55 | /* 56 | * Actually is not easy to test the class, as it depends on already created 57 | * ticket with already created task to start timer. In future we should 58 | * probably emulate those tests. Now, just testing some results methods 59 | * should return if there is no tasks at all. 60 | */ 61 | 62 | public function testCheckTech() 63 | { 64 | $this 65 | ->if($class = $this->testedClass->getClass()) 66 | ->then 67 | ->boolean($class::checkTech(1)) 68 | ->isFalse(); 69 | } 70 | 71 | public function testCheckTimerActive() 72 | { 73 | $this 74 | ->if($class = $this->testedClass->getClass()) 75 | ->then 76 | ->boolean($class::checkTimerActive(1)) 77 | ->isFalse(); 78 | } 79 | 80 | public function testTotalEndTime() 81 | { 82 | $this 83 | ->if($class = $this->testedClass->getClass()) 84 | ->then 85 | ->integer($class::totalEndTime(1)) 86 | ->isIdenticalTo(0); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tools/phpstan/rules/HardcodedPasswordRule.php: -------------------------------------------------------------------------------- 1 | var instanceof Node\Expr\Variable && $node->expr instanceof Node\Scalar\String_) { 30 | $variableName = $node->var->name; 31 | $value = $node->expr->value; 32 | 33 | // Ignore empty variable or initialization. 34 | if ($value === '') { 35 | return []; 36 | } 37 | 38 | // Detect variables with suspicious names. 39 | if (preg_match('/password|passwd|pwd|secret|api[_-]?key|token/i', $variableName)) { 40 | return [ 41 | RuleErrorBuilder::message( 42 | sprintf( 43 | 'A possible hardcoded password or API key was detected in the variable $%s.', 44 | $variableName, 45 | ), 46 | )->build(), 47 | ]; 48 | } 49 | 50 | // Detect suspicious values (e.g., long strings that look like API keys or tokens). 51 | if (is_string($value) && $this->isSuspiciousValue($value)) { 52 | return [ 53 | RuleErrorBuilder::message( 54 | sprintf( 55 | 'A possible hardcoded API key or token was detected in the value assigned to $%s.', 56 | $variableName, 57 | ), 58 | )->build(), 59 | ]; 60 | } 61 | } 62 | 63 | return []; 64 | } 65 | 66 | /** 67 | * Checks if a string value looks like a hardcoded API key or token. 68 | * 69 | * @param string $value 70 | * @return bool 71 | */ 72 | private function isSuspiciousValue(string $value): bool 73 | { 74 | $suspicious = false; 75 | $commonPatterns = [ 76 | // 20+ characters with uppercase, lowercase, digits, and special symbols 77 | '/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[-_!@#$%^&*])[A-Za-z\d-_!@#$%^&*]{20,}$/', 78 | '/^[A-Za-z0-9]{32}$/', // 32-character alphanumeric string (e.g., MD5 hash) 79 | '/^[A-Za-z0-9_-]{40}$/', // 40-character alphanumeric string (e.g., SHA1 hash) 80 | '/^[A-Za-z0-9_-]{64}$/', // 64-character alphanumeric string (e.g., SHA256 hash) 81 | ]; 82 | 83 | foreach ($commonPatterns as $pattern) { 84 | if (preg_match($pattern, $value)) { 85 | $suspicious = true; 86 | break; 87 | } 88 | } 89 | 90 | return $suspicious; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /tools/phpstan/stubs/glpi_constants.php: -------------------------------------------------------------------------------- 1 | . 32 | * 33 | * --------------------------------------------------------------------- 34 | */ 35 | 36 | // This file contains stubs for GLPI constants. 37 | // Please try to keep them alphabetically ordered. 38 | 39 | // Directories constants 40 | define('GLPI_CACHE_DIR', null); 41 | define('GLPI_CRON_DIR', null); 42 | define('GLPI_DOC_DIR', null); 43 | define('GLPI_DUMP_DIR', null); 44 | define('GLPI_GRAPH_DIR', null); 45 | define('GLPI_INVENTORY_DIR', null); 46 | define('GLPI_LOCAL_I18N_DIR', null); 47 | define('GLPI_LOCK_DIR', null); 48 | define('GLPI_LOG_DIR', null); 49 | define('GLPI_MARKETPLACE_DIR', null); 50 | define('GLPI_PICTURE_DIR', null); 51 | define('GLPI_PLUGIN_DOC_DIR', null); 52 | define('GLPI_RSS_DIR', null); 53 | define('GLPI_SESSION_DIR', null); 54 | define('GLPI_TMP_DIR', null); 55 | define('GLPI_UPLOAD_DIR', null); 56 | define('GLPI_VAR_DIR', null); 57 | 58 | // Optionnal constants 59 | define('GLPI_FORCE_MAIL', null); 60 | define('GLPI_LOG_LVL', null); 61 | define('GLPI_SQL_DEBUG', null); 62 | define('GLPI_STRICT_DEPRECATED', null); 63 | 64 | // Other constants 65 | define('GLPI_AJAX_DASHBOARD', null); 66 | define('GLPI_ALLOW_IFRAME_IN_RICH_TEXT', null); 67 | define('GLPI_CALDAV_IMPORT_STATE', null); 68 | define('GLPI_CSRF_EXPIRES', null); 69 | define('GLPI_CSRF_MAX_TOKENS', null); 70 | define('GLPI_DEMO_MODE', null); 71 | define('GLPI_DISABLE_ONLY_FULL_GROUP_BY_SQL_MODE', null); 72 | define('GLPI_IDOR_EXPIRES', null); 73 | define('GLPI_INSTALL_MODE', null); 74 | define('GLPI_MARKETPLACE_ALLOW_OVERRIDE', null); 75 | define('GLPI_MARKETPLACE_ENABLE', null); 76 | define('GLPI_MARKETPLACE_MANUAL_DOWNLOADS', null); 77 | define('GLPI_MARKETPLACE_PLUGINS_API_URI', null); 78 | define('GLPI_MARKETPLACE_PRERELEASES', null); 79 | define('GLPI_NETWORK_REGISTRATION_API_URL', null); 80 | define('GLPI_NETWORK_MAIL', null); 81 | define('GLPI_NETWORK_SERVICES', null); 82 | define('GLPI_SERVERSIDE_URL_ALLOWLIST', null); 83 | define('GLPI_TELEMETRY_URI', null); 84 | define('GLPI_USE_CSRF_CHECK', null); 85 | define('GLPI_USE_IDOR_CHECK', null); 86 | define('GLPI_USER_AGENT_EXTRA_COMMENTS', null); 87 | define('GLPI_CENTRAL_WARNINGS', null); 88 | define('GLPI_TEXT_MAXSIZE', null); 89 | -------------------------------------------------------------------------------- /report/actualtimetotal/actualtimetotal.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | $USEDBREPLICATE = 1; 33 | $DBCONNECTION_REQUIRED = 0; 34 | 35 | include("../../../../inc/includes.php"); 36 | 37 | $report = new PluginReportsAutoReport(__('ActualTimeTotal')); 38 | //Filtro fecha 39 | new PluginReportsDateIntervalCriteria( 40 | $report, 41 | 'glpi_tickets.closedate', 42 | __("Close date"), 43 | ); 44 | //Filtro usuario 45 | new PluginReportsDropdownCriteria( 46 | $report, 47 | "glpi_tickets_users.users_id", 48 | "glpi_users", 49 | __("Requester"), 50 | ); 51 | 52 | $report->displayCriteriasForm(); 53 | $report->setColumns([ 54 | new PluginReportsColumnLink( 55 | 'tickets_id', 56 | __('Ticket'), 57 | 'Ticket', 58 | [ 59 | 'with_navigate' => true, 60 | ], 61 | ), 62 | new PluginReportsColumnTimestamp( 63 | 'duration', 64 | __("Total duration"), 65 | ), 66 | new PluginReportsColumnTimestamp( 67 | 'totalduration', 68 | "ActualTime - " . __("Total duration"), 69 | ), 70 | new PluginReportsColumnTimestamp( 71 | 'diff', 72 | __("Duration Diff", "actiontime"), 73 | ), 74 | new PluginReportsColumn( 75 | 'diffpercent', 76 | __("Duration Diff", "actiontime") . " (%)", 77 | ), 78 | ]); 79 | $query = "SELECT glpi_tickets.id AS tickets_id, 80 | sum(glpi_tickettasks.actiontime) AS duration, 81 | sum(actual_actiontime) AS totalduration, 82 | (sum(glpi_tickettasks.actiontime) - sum(actual_actiontime)) AS diff, 83 | concat(round(((sum(glpi_tickettasks.actiontime) - sum(actual_actiontime)) / sum(actual_actiontime) * 100 ),2),'%') AS diffpercent 84 | FROM glpi_plugin_actualtime_tasks 85 | RIGHT JOIN glpi_tickettasks ON glpi_tickettasks.id = glpi_plugin_actualtime_tasks.tasks_id 86 | INNER JOIN glpi_tickets ON glpi_tickets.id = glpi_tickettasks.tickets_id 87 | INNER JOIN glpi_tickets_users ON glpi_tickets_users.tickets_id = glpi_tickets.id 88 | WHERE status = 6 AND glpi_tickets_users.type = 1 89 | "; 90 | $query .= $report->addSqlCriteriasRestriction(); 91 | $query .= " 92 | GROUP BY glpi_tickets.id"; 93 | $report->setSqlRequest($query); 94 | $report->execute(); 95 | -------------------------------------------------------------------------------- /templates/forms/modify_timers.html.twig: -------------------------------------------------------------------------------- 1 | {# 2 | #} 3 | 4 | {% import 'components/form/fields_macros.html.twig' as fields %} 5 | 6 | {% if options is not defined %} 7 | {% set options = {} %} 8 | {% endif %} 9 | 10 |
11 | 12 |
13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
{{ __('User') }}{{ __('Duration') }}{{ __('Task limit', 'actualtime') }}
{{ userdata['user']|raw }}{{ userdata['duration'] }}{{ userdata['limit'] }}
36 | 37 | {% for actualtime in actualtimes %} 38 | {{ fields.datetimeField( 39 | 'actual_begin[' ~ actualtime['id'] ~ ']', 40 | actualtime['actual_begin'], 41 | __('Start date'), 42 | options|merge({'readonly': true}) 43 | ) }} 44 | 45 | {% set end_tooltip = __('Max end', 'actualtime') ~ ': ' ~ actualtime['max_date'] %} 46 | {% set limit_tooltip = __('Additional time available', 'actualtime') ~ ': ' ~ actualtime['limit'] %} 47 | {% set actual_end_tooltip %} 48 | {% do call( 49 | 'Html::showToolTip', 50 | [end_tooltip ~ '
' ~ limit_tooltip] 51 | ) %} 52 | {% endset %} 53 | {{ fields.datetimeField( 54 | 'actual_end[' ~ actualtime['id'] ~ ']', 55 | actualtime['actual_end'], 56 | __('End date') ~ ' (' ~ actualtime['stamp_actiontime'] ~ ') ' ~ actual_end_tooltip, 57 | options|merge({'rand': actualtime['rand']}) 58 | ) }} 59 | {# To give it time to load the fullcalendar library #} 60 | 70 | {% endfor %} 71 | 72 |
73 |
74 | 75 |
76 | 80 |
81 | 82 |
-------------------------------------------------------------------------------- /tests/units/PluginActualtimeConfig.php: -------------------------------------------------------------------------------- 1 | . 21 | -------------------------------------------------------------------------- 22 | @package ActualTime 23 | @author the TICGAL team 24 | @copyright Copyright (c) 2018-2022 TICGAL team 25 | @license AGPL License 3.0 or (at your option) any later version 26 | http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | @link https://www.tic.gal/ 28 | @since 2018-2022 29 | ---------------------------------------------------------------------- 30 | */ 31 | 32 | namespace tests\units; 33 | 34 | use atoum; 35 | 36 | class PluginActualtimeConfig extends atoum 37 | { 38 | public function testRightname() 39 | { 40 | $this 41 | ->given($conf = $this->getTestedClassName()) 42 | ->string($conf::$rightname) 43 | ->isEqualTo('config'); 44 | } 45 | 46 | public function testGetTypeName() 47 | { 48 | $this 49 | ->if($class = $this->testedClass->getClass()) 50 | ->then 51 | ->string($class::getTypeName()) 52 | ->isNotEmpty(); 53 | } 54 | 55 | public function testGetConfig() 56 | { 57 | $this 58 | ->given($this->newTestedInstance) 59 | ->object($this->testedInstance->getConfig()) 60 | ->isInstanceOfTestedClass(); 61 | } 62 | 63 | public function testShowTimerPopup() 64 | { 65 | $this 66 | ->given($this->newTestedInstance) 67 | ->boolean($this->testedInstance->showTimerPopup()) 68 | ->isTrue(); 69 | } 70 | 71 | public function testShowInHelpdesk() 72 | { 73 | $this 74 | ->given($this->newTestedInstance) 75 | ->boolean($this->testedInstance->showInHelpdesk()) 76 | ->isFalse(); 77 | } 78 | 79 | public function testShowTimerInBox() 80 | { 81 | $this 82 | ->given($this->newTestedInstance) 83 | ->boolean($this->testedInstance->showTimerInBox()) 84 | ->isTrue(); 85 | } 86 | 87 | public function testAutoOpenNew() 88 | { 89 | $this 90 | ->given($this->newTestedInstance) 91 | ->boolean($this->testedInstance->autoOpenNew()) 92 | ->isFalse(); 93 | } 94 | 95 | public function testAutoOpenRunning() 96 | { 97 | $this 98 | ->given($this->newTestedInstance) 99 | ->boolean($this->testedInstance->autoOpenRunning()) 100 | ->isFalse(); 101 | } 102 | 103 | public function testCanView() 104 | { 105 | $this 106 | ->given($this->newTestedInstance) 107 | ->boolean($this->testedInstance->canView()) 108 | ->isFalse(); 109 | } 110 | 111 | public function testCanCreate() 112 | { 113 | $this 114 | ->given($this->newTestedInstance) 115 | ->boolean($this->testedInstance->canCreate()) 116 | ->isFalse(); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /report/actualtimeuser/actualtimeuser.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | $USEDBREPLICATE = 1; 33 | $DBCONNECTION_REQUIRED = 0; 34 | 35 | include("../../../../inc/includes.php"); 36 | 37 | $report = new PluginReportsAutoReport(__('ActualTimeUser')); 38 | //Filtro fecha 39 | new PluginReportsDateIntervalCriteria( 40 | $report, 41 | 'glpi_tickets.closedate', 42 | __("Close date"), 43 | ); 44 | //Filtro user 45 | $choices = [ 46 | 0 => __('Technician'), 47 | 1 => __('Requester'), 48 | ]; 49 | $filter_active = new PluginReportsArrayCriteria( 50 | $report, 51 | 'glpi_tickets_users.type', 52 | _('Group by'), 53 | $choices, 54 | ); 55 | 56 | $report->displayCriteriasForm(); 57 | $report->setColumns([ 58 | new PluginReportsColumnLink( 59 | 'user_id', 60 | __('User'), 61 | 'User', 62 | [ 63 | 'with_navigate' => true, 64 | ], 65 | ), 66 | new PluginReportsColumnTimestamp( 67 | 'duration', 68 | __("Total duration"), 69 | ), 70 | new PluginReportsColumnTimestamp( 71 | 'totalduration', 72 | "ActualTime - " . __("Total duration"), 73 | ), 74 | new PluginReportsColumnTimestamp( 75 | 'diff', 76 | __( 77 | "Duration Diff", 78 | "actiontime", 79 | ), 80 | ), 81 | new PluginReportsColumn( 82 | 'diffpercent', 83 | __("Duration Diff", "actiontime") . " (%)", 84 | ), 85 | ]); 86 | if ($filter_active->getParameterValue() == 1) { 87 | $query = "SELECT glpi_tickets_users.users_id as user_id,"; 88 | $group = " 89 | AND glpi_tickets_users.type=1 90 | GROUP BY glpi_tickets_users.users_id"; 91 | } else { 92 | $query = "SELECT glpi_tickettasks.users_id_tech as user_id,"; 93 | $group = " 94 | GROUP BY glpi_tickettasks.users_id_tech"; 95 | } 96 | $report->delCriteria('glpi_tickets_users.type'); 97 | $query .= " 98 | sum(glpi_tickettasks.actiontime) AS duration, 99 | sum(actual_actiontime) AS totalduration, 100 | (sum(glpi_tickettasks.actiontime) - sum(actual_actiontime)) AS diff, 101 | concat(round(((sum(glpi_tickettasks.actiontime) - sum(actual_actiontime)) / sum(actual_actiontime) * 100 ),2),'%') AS diffpercent 102 | FROM glpi_plugin_actualtime_tasks 103 | RIGHT JOIN glpi_tickettasks ON glpi_tickettasks.id = glpi_plugin_actualtime_tasks.tasks_id 104 | INNER JOIN glpi_tickets ON glpi_tickets.id = glpi_tickettasks.tickets_id 105 | INNER JOIN glpi_tickets_users ON glpi_tickets_users.tickets_id = glpi_tickets.id 106 | WHERE status = 6 107 | "; 108 | $query .= $report->addSqlCriteriasRestriction(); 109 | $query .= $group; 110 | 111 | $report->setSqlRequest($query); 112 | $report->execute(); 113 | -------------------------------------------------------------------------------- /inc/dashboard.class.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | // phpcs:ignore PSR1.Classes.ClassDeclaration.MissingNamespace 33 | class PluginActualtimeDashboard extends CommonDBTM 34 | { 35 | /** 36 | * dashboardCards 37 | * 38 | * @param ?array $cards 39 | * @return array 40 | */ 41 | public static function dashboardCards(?array $cards = []): array 42 | { 43 | $cards = $cards ?? []; 44 | $group = 'Actualtime'; 45 | 46 | $cards['plugin_actualtime_moreactualtimetasksbyday'] = [ 47 | 'widgettype' => ['stackedbars', 'lines'], 48 | 'label' => Ticket::getTypeName() . ' - ' . __('Top 20 Actualtime tasks per day', 'actualtime'), 49 | 'group' => $group, 50 | 'filters' => ['dates'], 51 | 'provider' => PluginActualtimeProvider::class . '::moreActualtimeTasksByDay', 52 | ]; 53 | 54 | $cards['plugin_actualtime_lessactualtimetasks'] = [ 55 | 'widgettype' => ['stackedbars', 'lines'], 56 | 'label' => Ticket::getTypeName() . ' - ' . __('Bottom 20 Actualtime tasks per day', 'actualtime'), 57 | 'group' => $group, 58 | 'filters' => ['dates'], 59 | 'provider' => PluginActualtimeProvider::class . '::lessActualtimeTasksByDay', 60 | ]; 61 | 62 | $cards['plugin_actualtime_moreactualtimeusagebyday'] = [ 63 | 'widgettype' => ['stackedbars', 'lines'], 64 | 'label' => Ticket::getTypeName() . ' - ' . __('Top 20 Actualtime usage (hours)', 'actualtime'), 65 | 'group' => $group, 66 | 'filters' => ['dates'], 67 | 'provider' => PluginActualtimeProvider::class . '::moreActualtimeUsageByDay', 68 | ]; 69 | 70 | $cards['plugin_actualtime_lessactualtimeusagebyday'] = [ 71 | 'widgettype' => ['stackedbars', 'lines'], 72 | 'label' => Ticket::getTypeName() . ' - ' . __('Bottom 20 Actualtime usage (hours)', 'actualtime'), 73 | 'group' => $group, 74 | 'filters' => ['dates'], 75 | 'provider' => PluginActualtimeProvider::class . '::lessActualtimeUsageByDay', 76 | ]; 77 | 78 | $cards['plugin_actualtime_moreapercentagectualtimetasksbyday'] = [ 79 | 'widgettype' => ['bars', 'lines'], 80 | 'label' => Ticket::getTypeName() . ' - ' . __('Top 20 % Actualtime usage per day', 'actualtime'), 81 | 'group' => $group, 82 | 'filters' => ['dates'], 83 | 'provider' => PluginActualtimeProvider::class . '::morePercentageActualtimeTasksByDay', 84 | ]; 85 | 86 | $cards['plugin_actualtime_lesspercentageactualtimetasks'] = [ 87 | 'widgettype' => ['bars', 'lines'], 88 | 'label' => Ticket::getTypeName() . ' - ' . __('Bottom 20 % Actualtime usage per day', 'actualtime'), 89 | 'group' => $group, 90 | 'filters' => ['dates'], 91 | 'provider' => PluginActualtimeProvider::class . '::lessPercentageActualtimeTasksByDay', 92 | ]; 93 | 94 | return $cards; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /tools/modify_headers.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #!/usr/bin/perl -w 3 | 4 | use Cwd; 5 | use File::Basename; 6 | use File::Spec; 7 | 8 | my $current_directory = getcwd(); 9 | my $directory_name = basename($current_directory); 10 | my $mode = 0; 11 | 12 | if ($directory_name eq "tools"){ 13 | do_dir(".."); 14 | } else { 15 | my $ruta_subcarpeta = File::Spec->catdir($current_directory, "tools"); 16 | if (-d $ruta_subcarpeta) { 17 | $mode = 1; 18 | do_dir("."); 19 | } 20 | } 21 | 22 | sub do_dir{ 23 | local ($dir)=@_; 24 | print "Entering $dir\n"; 25 | 26 | my @excluded_dirs=( 27 | ".git", 28 | "lib", 29 | "plugins", 30 | "vendor", 31 | "tests", 32 | "tools", 33 | "locales", 34 | "pics" 35 | ); 36 | 37 | opendir(DIRHANDLE,$dir) || die "ERROR: can not read current directory\n"; 38 | foreach (readdir(DIRHANDLE)){ 39 | if ($_ ne '..' && $_ ne '.'){ 40 | # Excluded directories 41 | if ( $_ ~~ @excluded_dirs ){ 42 | print "Skipping $dir/$_\n"; 43 | next; 44 | } 45 | if (-d "$dir/$_"){ 46 | do_dir("$dir/$_"); 47 | } else { 48 | if (!(-l "$dir/$_")){ 49 | # Included filetypes - php, css, js => default comment style 50 | if ((index($_,".php",0)!=-1)||(index($_,".css",0)!=-1)||(index($_,".js",0)!=-1)){ 51 | do_file("$dir/$_", "", " * "); 52 | } 53 | # Included filetypes - twig => ({# #}) 54 | if ((index($_,".twig",0)!=-1)){ 55 | do_file("$dir/$_", "", " # "); 56 | } 57 | # Included filetypes - sql, sh, pl => Add a specific comment style (#) 58 | if ((index($_,".sql",0)!=-1)||(index($_,".sh",0)!=-1)||(index($_,".pl",0)!=-1)){ 59 | do_file("$dir/$_", "", "# "); 60 | } 61 | } 62 | } 63 | } 64 | } 65 | closedir DIRHANDLE; 66 | } 67 | 68 | sub do_file{ 69 | local ($file, $format, $decor)=@_; 70 | if ($format ne "") { 71 | print "Replacing header on $file. (Using specific comment $format)\n"; 72 | } else { 73 | print "Replacing header on $file.\n" 74 | } 75 | 76 | ### DELETE HEADERS 77 | open(INIT_FILE,$file); 78 | @lines=; 79 | close(INIT_FILE); 80 | 81 | open(TMP_FILE,">/tmp/tmp_glpi.txt"); 82 | 83 | $status=''; 84 | foreach (@lines){ 85 | # Did we found header closure tag ? 86 | if ($_ =~ m/$format\*\// || $_ =~ m/$format\#\}/){ 87 | # if line starts with */ or #} add a space before to fix comment style 88 | if ($_ =~ m/$format\*\//){ 89 | $_ =~ s/^$format\*\// $format\*\//; 90 | } elsif ($_ =~ m/$format\#\}/){ 91 | $_ =~ s/^$format\#\}/ $format\#\}/; 92 | } 93 | $status="END"; 94 | } 95 | 96 | # If we have reach the header closure tag, we print the rest of the file 97 | if ($status =~ m/END/||$status !~ m/BEGIN/){ 98 | print TMP_FILE $_; 99 | } 100 | 101 | # If we haven't reach the header closure tag 102 | if ($status !~ m/END/){ 103 | # If we found the header open tag... 104 | if ( 105 | ($_ =~ m/$format\/\*\*/ || $_ =~ m/$format\/\*/) 106 | || ($_ =~ m/$format\{\#/) 107 | ){ 108 | # if line is /* replace by /** 109 | if ($_ =~ m/$format\/\*/){ 110 | $_ =~ s/$format\/\*/$format\*\*/; 111 | } 112 | 113 | $status="BEGIN"; 114 | ##### ADD NEW HEADERS 115 | #print "Replacing header on $file.\n"; 116 | 117 | if ($mode == 0) { 118 | open(HEADER_FILE,"TICGAL_HEADER"); 119 | } else { 120 | open(HEADER_FILE,"tools/TICGAL_HEADER"); 121 | } 122 | 123 | @headers=; 124 | foreach (@headers){ 125 | print TMP_FILE $decor; 126 | print TMP_FILE $_; 127 | } 128 | close(HEADER_FILE) ; 129 | } 130 | } 131 | } 132 | close(TMP_FILE); 133 | system("cp -f /tmp/tmp_glpi.txt $file"); 134 | 135 | # If we haven't found an header on the file, report it 136 | if ($status eq '') { 137 | print "Unable to found an header on $file. Please add it manually"; 138 | #exit 1; 139 | } 140 | } -------------------------------------------------------------------------------- /front/sourcetimer.form.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | include("../../../inc/includes.php"); 33 | 34 | if (!isset($_POST["itemtype"])) { 35 | Html::back(); 36 | } 37 | if ( 38 | PluginActualtimeSourcetimer::checkItemtypeRight($_POST["itemtype"]) 39 | && PluginActualtimeSourcetimer::canModify($_POST["itemtype"], $_POST["items_id"]) 40 | ) { 41 | if (isset($_POST["update"])) { 42 | $config = new PluginActualtimeConfig(); 43 | $itemtype = $_POST["itemtype"] ?? ''; 44 | $item_id = $_POST["items_id"] ?? 0; 45 | $task_limit = PluginActualtimeSourcetimer::getTaskLimits($itemtype, $item_id); 46 | foreach ($_POST['actual_end'] as $key => $value) { 47 | if (empty($value)) { 48 | continue; 49 | } 50 | $actualtime = new PluginActualtimeTask(); 51 | if ($actualtime->getFromDB($key)) { 52 | if ( 53 | $value != $actualtime->fields['actual_end'] 54 | && $value > $actualtime->fields['actual_begin'] 55 | && $value >= $task_limit[$key]['min_date'] 56 | && $value <= $task_limit[$key]['max_date'] 57 | ) { 58 | $seconds = (strtotime($value) - strtotime($actualtime->fields['actual_begin'])); 59 | $input = [ 60 | 'id' => $key, 61 | 'actual_end' => $value, 62 | 'actual_actiontime' => $seconds, 63 | 'is_modified' => 1, 64 | ]; 65 | if ($actualtime->fields['is_modified'] == 0) { 66 | $source = new PluginActualtimeSourcetimer(); 67 | $input_source = [ 68 | 'plugin_actualtime_tasks_id' => $actualtime->fields['id'], 69 | 'users_id' => Session::getLoginUserID(), 70 | 'source_end' => $actualtime->fields['actual_end'], 71 | 'source_actiontime' => $actualtime->fields['actual_actiontime'], 72 | ]; 73 | $source->add($input_source); 74 | } 75 | $actualtime->update($input); 76 | } 77 | } 78 | } 79 | 80 | if ($config->autoUpdateDuration()) { 81 | $task_id = $_POST["items_id"]; 82 | $itemtype = $_POST["itemtype"]; 83 | $task = new $itemtype(); 84 | $task->getFromDB($task_id); 85 | $input = [ 86 | 'id' => $task_id, 87 | ]; 88 | 89 | /** @var array $CFG_GLPI */ 90 | global $CFG_GLPI; 91 | $totaltime = PluginActualtimeTask::totalEndTime($task_id, $itemtype); 92 | $step = $CFG_GLPI["time_step"]; 93 | $ceil = ceil($totaltime / ($step * MINUTE_TIMESTAMP)) * ($step * MINUTE_TIMESTAMP); 94 | if (isset($task->fields['actiontime'])) { 95 | $input['actiontime'] = $ceil; 96 | } else { 97 | $input['effective_duration'] = $ceil; 98 | } 99 | $task->update($input); 100 | } 101 | } 102 | } 103 | Html::back(); 104 | -------------------------------------------------------------------------------- /inc/profile.class.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | // phpcs:ignore PSR1.Classes.ClassDeclaration.MissingNamespace 33 | class PluginActualtimeProfile extends Profile 34 | { 35 | public static $rightname = 'profile'; 36 | 37 | /** 38 | * {@inheritDoc} 39 | */ 40 | public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0): string|array 41 | { 42 | switch ($item->getType()) { 43 | case 'Profile': 44 | return self::createTabEntry(PLUGIN_ACTUALTIME_NAME); 45 | } 46 | 47 | return ''; 48 | } 49 | 50 | /** 51 | * {@inheritDoc} 52 | */ 53 | public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0): bool 54 | { 55 | switch ($item->getType()) { 56 | case Profile::class: 57 | /** @var Profile $item */ 58 | $profile = new self(); 59 | return $profile->displayProfileForm($item); 60 | } 61 | 62 | return false; 63 | } 64 | 65 | /** 66 | * @param Profile $profile 67 | * 68 | * @return bool 69 | */ 70 | public function displayProfileForm(Profile $profile): bool 71 | { 72 | if (!Session::haveRight(self::$rightname, READ)) { 73 | return false; 74 | } 75 | 76 | $can_edit = Session::haveRight(self::$rightname, UPDATE); 77 | 78 | echo "
"; 79 | if ($can_edit) { 80 | echo "
"; 81 | } 82 | 83 | $rights = array_merge( 84 | self::getGeneralRights(), 85 | self::getCentralRights(), 86 | ); 87 | $matrix_options = [ 88 | 'canedit' => $can_edit, 89 | 'title' => 'ActualTime', 90 | ]; 91 | $profile->displayRightsChoiceMatrix($rights, $matrix_options); 92 | 93 | if ($can_edit) { 94 | echo "
"; 95 | echo Html::hidden('id', ['value' => $profile->getID()]); 96 | echo Html::submit(_sx('button', 'Save'), ['name' => 'update']); 97 | echo "
\n"; 98 | Html::closeForm(); 99 | } 100 | echo '
'; 101 | 102 | return true; 103 | } 104 | 105 | /** 106 | * getGeneralRights 107 | * 108 | * @return array 109 | */ 110 | public static function getGeneralRights(): array 111 | { 112 | return [ 113 | [ 114 | 'rights' => [READ => __('Read')], 115 | 'label' => __("Running timers", "actualtime"), 116 | 'field' => 'plugin_actualtime_running', 117 | ], 118 | ]; 119 | } 120 | 121 | /** 122 | * getCentralRights 123 | * 124 | * @return array 125 | */ 126 | public static function getCentralRights(): array 127 | { 128 | return [ 129 | [ 130 | 'itemtype' => PluginActualtimeSourcetimer::getType(), 131 | 'label' => __("Modify timers", "actualtime"), 132 | 'field' => PluginActualtimeSourcetimer::$rightname, 133 | ], 134 | ]; 135 | } 136 | 137 | /** 138 | * uninstall 139 | * 140 | * @param Migration $migration 141 | * @return void 142 | */ 143 | public static function uninstall(Migration $migration): void 144 | { 145 | $migration->displayMessage("Deleting actualtime profile rights"); 146 | $rights = array_merge(self::getGeneralRights(), self::getCentralRights()); 147 | foreach ($rights as $data) { 148 | ProfileRight::deleteProfileRights([$data['field']]); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /locales/actualtime.pot: -------------------------------------------------------------------------------- 1 | # Actualtime Glpi Plugin. 2 | # Copyright (C) 2024 TICGAL 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # TICGAL, 2024 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 12 | "PO-Revision-Date: 2024-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 21 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 22 | msgid "Duration Diff" 23 | msgstr "" 24 | 25 | #. TRANS: d is a symbol for days in a time (displays: 3d) 26 | #: ajax/timer.php:70 27 | #, php-format 28 | msgid "%dd" 29 | msgstr "" 30 | 31 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 32 | #: ajax/timer.php:74 33 | #, php-format 34 | msgid "%dh" 35 | msgstr "" 36 | 37 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 38 | #: ajax/timer.php:78 39 | #, php-format 40 | msgid "%dmin" 41 | msgstr "" 42 | 43 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 44 | #: ajax/timer.php:82 45 | #, php-format 46 | msgid "%ds" 47 | msgstr "" 48 | 49 | #: ajax/timer.php:93 50 | msgid "Timer started on" 51 | msgstr "" 52 | 53 | #: inc/config.class.php:65 54 | msgid "ActualTime Setup" 55 | msgstr "" 56 | 57 | #: inc/config.class.php:99 58 | msgid "In Standard interface only (default)" 59 | msgstr "" 60 | 61 | #: inc/config.class.php:100 62 | msgid "Both in Standard and Helpdesk interfaces" 63 | msgstr "" 64 | 65 | #: inc/config.class.php:106 66 | msgid "Enable timer on tasks" 67 | msgstr "" 68 | 69 | #: inc/config.class.php:118 70 | msgid "Display pop-up window with current running timer" 71 | msgstr "" 72 | 73 | #: inc/config.class.php:124 74 | msgid "Display actual time in closed task box ('Processing ticket' list)" 75 | msgstr "" 76 | 77 | #: inc/config.class.php:130 78 | msgid "Automatically open task with timer running" 79 | msgstr "" 80 | 81 | #: inc/config.class.php:136 82 | msgid "Automatically update the duration" 83 | msgstr "" 84 | 85 | #: inc/config.class.php:142 86 | msgid "Enable Timer Only on Scheduled Task Day" 87 | msgstr "" 88 | 89 | #: inc/config.class.php:148 90 | msgid "Enable Timer Only on Task's Start Day" 91 | msgstr "" 92 | 93 | #: inc/dashboard.class.php:48 94 | msgid "Top 20 Actualtime tasks per day" 95 | msgstr "" 96 | 97 | #: inc/dashboard.class.php:56 98 | msgid "Bottom 20 Actualtime tasks per day" 99 | msgstr "" 100 | 101 | #: inc/dashboard.class.php:64 102 | msgid "Top 20 Actualtime usage (hours)" 103 | msgstr "" 104 | 105 | #: inc/dashboard.class.php:72 106 | msgid "Bottom 20 Actualtime usage (hours)" 107 | msgstr "" 108 | 109 | #: inc/dashboard.class.php:79 110 | msgid "Top 20 % Actualtime usage per day" 111 | msgstr "" 112 | 113 | #: inc/dashboard.class.php:87 114 | msgid "Bottom 20 % Actualtime usage per day" 115 | msgstr "" 116 | 117 | #: inc/profile.class.php:103 118 | msgid "General" 119 | msgstr "" 120 | 121 | #: inc/profile.class.php:138 inc/running.class.php:71 122 | msgid "Running timers" 123 | msgstr "" 124 | 125 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 126 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 127 | msgid "Modify timers" 128 | msgstr "" 129 | 130 | #: inc/running.class.php:76 131 | msgid "Update every (s)" 132 | msgstr "" 133 | 134 | #: inc/sourcetimer.class.php:53 135 | msgid "Modify tickets" 136 | msgstr "" 137 | 138 | #: inc/sourcetimer.class.php:54 139 | msgid "Modify changes" 140 | msgstr "" 141 | 142 | #: inc/sourcetimer.class.php:55 143 | msgid "Modify projects" 144 | msgstr "" 145 | 146 | #: inc/task.class.php:321 inc/task.class.php:482 147 | msgid "Actual Duration" 148 | msgstr "" 149 | 150 | #: inc/task.class.php:332 inc/task.class.php:493 151 | msgid "Partial actual duration" 152 | msgstr "" 153 | 154 | #: inc/task.class.php:970 155 | msgid "Original end date" 156 | msgstr "" 157 | 158 | #: inc/task.class.php:971 159 | msgid "Original duration" 160 | msgstr "" 161 | 162 | #: inc/task.class.php:972 163 | #, php-format 164 | msgid "First modification by %s" 165 | msgstr "" 166 | 167 | #: inc/task.class.php:1362 inc/task.class.php:1368 168 | #, php-format 169 | msgid "You cannot start a timer because the task was scheduled for %d." 170 | msgstr "" 171 | 172 | #: inc/task.class.php:1392 173 | msgid "You cannot add a timer on a different day." 174 | msgstr "" 175 | 176 | #: inc/task.class.php:1435 177 | msgid "Today is marked as absence you can not initialize the timer" 178 | msgstr "" 179 | 180 | #: inc/task.class.php:1441 181 | msgid "Timer has not been initialized" 182 | msgstr "" 183 | 184 | #: inc/task.class.php:1458 185 | msgid "You are already doing a waypoint" 186 | msgstr "" 187 | 188 | #: inc/task.class.php:1495 inc/task.class.php:1500 189 | msgid "Technician not in charge of the task" 190 | msgstr "" 191 | 192 | #: inc/task.class.php:1506 193 | msgid "A user is already performing the task" 194 | msgstr "" 195 | 196 | #: inc/task.class.php:1556 197 | #, php-format 198 | msgid "You are already working on %s" 199 | msgstr "" 200 | 201 | #: inc/task.class.php:1587 202 | msgid "Timer started" 203 | msgstr "" 204 | 205 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 206 | msgid "Timer completed" 207 | msgstr "" 208 | 209 | #: inc/task.class.php:1699 inc/task.class.php:1813 210 | msgid "Only the user who initiated the task can close it" 211 | msgstr "" 212 | 213 | #: inc/task.class.php:1702 214 | msgid "The task had not been initialized" 215 | msgstr "" 216 | -------------------------------------------------------------------------------- /tools/make_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_DIR=$(dirname "$(readlink -f "$0")") 4 | PARENT_FOLDER_PATH=$(dirname "$SCRIPT_DIR") 5 | PLUGINNAME=$(basename "$PARENT_FOLDER_PATH") 6 | 7 | PUBLIC_RELEASE=0 8 | while getopts ":p" opt; do 9 | case $opt in 10 | p) 11 | PUBLIC_RELEASE=1 12 | ;; 13 | \?) 14 | echo "Invalid option: -$OPTARG" >&2 15 | exit 1 16 | ;; 17 | esac 18 | done 19 | shift $((OPTIND - 1)) 20 | 21 | if [ ! "$#" -eq 1 ]; then 22 | echo "Usage $0 [-p] " 23 | exit 1 24 | fi 25 | 26 | INIT_PWD=$PWD 27 | if [ ! "$PARENT_FOLDER_PATH" = "$INIT_PWD" ]; then 28 | cd $PARENT_FOLDER_PATH 29 | fi 30 | 31 | # Check core file 32 | if [ ! -f setup.php ]; then 33 | echo "setup.php not found" 34 | exit 1 35 | fi 36 | 37 | # Check if the version is in the setup.php file 38 | RELEASE=$1 39 | SEMVER_REGEX="^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$" 40 | if grep --quiet "'$RELEASE'" setup.php; then 41 | if [[ $RELEASE =~ $SEMVER_REGEX ]]; then 42 | echo "$RELEASE found in setup.php" 43 | else 44 | echo "Version $RELEASE does not match the semantic versioning format" 45 | exit 1 46 | fi 47 | else 48 | echo "$RELEASE has not been found in setup.php" 49 | exit 1 50 | fi 51 | 52 | # Download dependencies if necessary 53 | if [ -f $PARENT_FOLDER_PATH"/composer.json" ]; then 54 | INSTALL_COMPOSER=0 55 | MOVE_TO_PUBLIC=0 56 | 57 | if [ ! -d "$PARENT_FOLDER_PATH/vendor" ]; then 58 | if [ -d "$PARENT_FOLDER_PATH/public" ] && [ -d "$PARENT_FOLDER_PATH/public/vendor" ]; then 59 | if [ ! "$(ls -A "$PARENT_FOLDER_PATH/public/vendor")" ]; then 60 | INSTALL_COMPOSER=1 61 | MOVE_TO_PUBLIC=1 62 | fi 63 | else 64 | INSTALL_COMPOSER=1 65 | fi 66 | elif [ ! "$(ls -A "$PARENT_FOLDER_PATH/vendor")" ]; then 67 | INSTALL_COMPOSER=1 68 | fi 69 | 70 | if [ "$INSTALL_COMPOSER" = 1 ]; then 71 | VERIFICA_COMPOSER=$(which "composer") 72 | if [ -z $VERIFICA_COMPOSER ]; then 73 | echo "Composer is not installed" 74 | exit 1 75 | else 76 | echo "Downloading dependencies" 77 | composer install 78 | if [ "$MOVE_TO_PUBLIC" = 1 ]; then 79 | mv "$PARENT_FOLDER_PATH/vendor" "$PARENT_FOLDER_PATH/public" 80 | fi 81 | fi 82 | fi 83 | fi 84 | 85 | # Update locales if necessary 86 | if [ -d "$PARENT_FOLDER_PATH/locales" ]; then 87 | if [ -f "$PARENT_FOLDER_PATH/locales/localazy.keys.json" ]; then 88 | read -p "Are translations up to date? [Y/n] " -n 1 -r 89 | echo "\n"; 90 | if [[ ! $REPLY =~ ^[Yy]$ ]]; then 91 | if [ -f "$PARENT_FOLDER_PATH/tools/extract_template.sh" ]; then 92 | echo "Extract locales" 93 | ./tools/extract_template.sh 94 | elif [ -f "$PARENT_FOLDER_PATH/tools/generate_locales.sh" ]; then 95 | echo "Generate locales" 96 | ./tools/generate_locales.sh 97 | fi 98 | fi 99 | fi 100 | fi 101 | 102 | # Clean code with PHP CS Fixer 103 | if [ -f "$PARENT_FOLDER_PATH/tools/php-cs-fixer.sh" ]; then 104 | echo "Initiating PHP CS Fixer" 105 | chmod +x $PARENT_FOLDER_PATH/tools/php-cs-fixer.sh 106 | bash $PARENT_FOLDER_PATH/tools/php-cs-fixer.sh 107 | fi 108 | 109 | # Perform PHPStan analysis 110 | if [ -f "$PARENT_FOLDER_PATH/tools/phpstan.sh" ]; then 111 | echo "Initiating PHPStan analysis" 112 | chmod +x $PARENT_FOLDER_PATH/tools/phpstan.sh 113 | bash $PARENT_FOLDER_PATH/tools/phpstan.sh 114 | fi 115 | 116 | # remove old tmp files 117 | if [ -e /tmp/$PLUGINNAME ]; then 118 | echo "Delete existing temp directory" 119 | rm -rf /tmp/$PLUGINNAME 120 | fi 121 | 122 | echo "Copy to /tmp directory" 123 | git checkout-index -a -f --prefix=/tmp/$PLUGINNAME/ 124 | 125 | if [ -e vendor ]; then 126 | cp -R vendor/ /tmp/$PLUGINNAME/ 127 | fi 128 | 129 | echo "Move to this directory" 130 | cd /tmp/$PLUGINNAME 131 | 132 | echo "Delete various scripts and directories" 133 | # array of files and folders to delete 134 | FILES_TO_DELETE=( 135 | # github files 136 | ".github" 137 | ".gitignore" 138 | ".keep" 139 | "ISSUE_TEMPLATE.md" 140 | "PULL_REQUEST_TEMPLATE.md" 141 | # development folders 142 | "tools" 143 | "tests" 144 | "phpunit" 145 | # CI/CD config files 146 | ".php-cs-fixer.php" 147 | ".phpcs.xml" 148 | ".twig_cs.dist.php" 149 | "phpstan.neon" 150 | "composer.lock" 151 | ".composer.hash" 152 | "phpunit.xml.dist" 153 | "locales/localazy*" 154 | "RoboFile.php" 155 | ".travis.yml" 156 | ".coveralls.yml" 157 | ".tx" 158 | # Marketplace files 159 | "$PLUGINNAME.xml" 160 | "screenshots" 161 | ) 162 | 163 | # loop through the array and delete each file 164 | for file in "${FILES_TO_DELETE[@]}"; do 165 | if [ -e "$file" ]; then 166 | rm -rf "$file" 167 | fi 168 | done 169 | 170 | # if exist composer.json, use composer install --no-dev 171 | if [ -f composer.json ]; then 172 | echo "Removing development dependencies" 173 | composer install --no-dev --quiet 174 | fi 175 | 176 | cd .. 177 | 178 | if [ "$PUBLIC_RELEASE" = 1 ]; then 179 | echo "Creating public release" 180 | PACKAGE_NAME="glpi-$PLUGINNAME-$RELEASE" 181 | else 182 | echo "Creating private release" 183 | PACKAGE_NAME="$PLUGINNAME-$RELEASE" 184 | fi 185 | tar cjf "$PACKAGE_NAME.tar.bz2" $PLUGINNAME 186 | 187 | cd $INIT_PWD 188 | 189 | rm -rf /tmp/$PLUGINNAME 190 | 191 | echo "The Tarball is in the /tmp directory" 192 | -------------------------------------------------------------------------------- /locales/ja_JP.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: ja_JP\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=1; plural=0;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "時間の差" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%d日" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%d時間" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%d分" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%d秒" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "タイマー開始" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "実時間の設定" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "標準インターフェースのみ (デフォルト)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "標準インターフェース・ヘルプデスク インターフェースとも" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "タスクでタイマーを有効にする" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "現在稼働中のタイマーをポップアップウィンドウで表示" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "終了タスクのボックスに実時間を表示(「対応中のチケット」リスト)" 69 | 70 | #: inc/config.class.php:130 71 | msgid "Automatically open task with timer running" 72 | msgstr "タイマーを稼働させタスクを自動的に開く" 73 | 74 | #: inc/config.class.php:136 75 | msgid "Automatically update the duration" 76 | msgstr "所要時間を自動更新" 77 | 78 | #: inc/config.class.php:142 79 | msgid "Enable Timer Only on Scheduled Task Day" 80 | msgstr "スケジュールしたタスク日にのみタイマーを有効に" 81 | 82 | #: inc/config.class.php:148 83 | msgid "Enable Timer Only on Task's Start Day" 84 | msgstr "タスクの開始日のみタイマーを有効に" 85 | 86 | #: inc/dashboard.class.php:48 87 | msgid "Top 20 Actualtime tasks per day" 88 | msgstr "1 日の実時間が長いタスク上位 20 件" 89 | 90 | #: inc/dashboard.class.php:56 91 | msgid "Bottom 20 Actualtime tasks per day" 92 | msgstr "1 日の実時間が短いタスク上位 20 件" 93 | 94 | #: inc/dashboard.class.php:64 95 | msgid "Top 20 Actualtime usage (hours)" 96 | msgstr "実時間が長い上位 20 件" 97 | 98 | #: inc/dashboard.class.php:72 99 | msgid "Bottom 20 Actualtime usage (hours)" 100 | msgstr "実時間が短い上位 20 件" 101 | 102 | #: inc/dashboard.class.php:79 103 | msgid "Top 20 % Actualtime usage per day" 104 | msgstr "1 日の実時間が長い上位 20%" 105 | 106 | #: inc/dashboard.class.php:87 107 | msgid "Bottom 20 % Actualtime usage per day" 108 | msgstr "1 日の実時間が短い上位 20%" 109 | 110 | #: inc/profile.class.php:103 111 | msgid "General" 112 | msgstr "一般" 113 | 114 | #: inc/profile.class.php:138 inc/running.class.php:71 115 | msgid "Running timers" 116 | msgstr "実行中のタイマー" 117 | 118 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 119 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 120 | msgid "Modify timers" 121 | msgstr "Modify timers" 122 | 123 | #: inc/running.class.php:76 124 | msgid "Update every (s)" 125 | msgstr "更新間隔 (秒)" 126 | 127 | #: inc/sourcetimer.class.php:53 128 | msgid "Modify tickets" 129 | msgstr "Modify tickets" 130 | 131 | #: inc/sourcetimer.class.php:54 132 | msgid "Modify changes" 133 | msgstr "Modify changes" 134 | 135 | #: inc/sourcetimer.class.php:55 136 | msgid "Modify projects" 137 | msgstr "Modify projects" 138 | 139 | #: inc/task.class.php:321 inc/task.class.php:482 140 | msgid "Actual Duration" 141 | msgstr "実所要時間" 142 | 143 | #: inc/task.class.php:332 inc/task.class.php:493 144 | msgid "Partial actual duration" 145 | msgstr "部分的な実時間" 146 | 147 | #: inc/task.class.php:970 148 | msgid "Original end date" 149 | msgstr "Original end date" 150 | 151 | #: inc/task.class.php:971 152 | msgid "Original duration" 153 | msgstr "Original duration" 154 | 155 | #: inc/task.class.php:972 156 | #, php-format 157 | msgid "First modification by %s" 158 | msgstr "First modification by %s" 159 | 160 | #: inc/task.class.php:1362 inc/task.class.php:1368 161 | #, php-format 162 | msgid "You cannot start a timer because the task was scheduled for %d." 163 | msgstr "タスクが %d からに予定しているため、タイマーをスタートできません。" 164 | 165 | #: inc/task.class.php:1392 166 | msgid "You cannot add a timer on a different day." 167 | msgstr "別の日にタイマーを追加することはできません。" 168 | 169 | #: inc/task.class.php:1435 170 | msgid "Today is marked as absence you can not initialize the timer" 171 | msgstr "本日不在となっているため、タイマーを初期化できません" 172 | 173 | #: inc/task.class.php:1441 174 | msgid "Timer has not been initialized" 175 | msgstr "タイマーが初期化されていません" 176 | 177 | #: inc/task.class.php:1458 178 | msgid "You are already doing a waypoint" 179 | msgstr "すでに中間地点で作業中です" 180 | 181 | #: inc/task.class.php:1495 inc/task.class.php:1500 182 | msgid "Technician not in charge of the task" 183 | msgstr "タスクを担当していない技術者" 184 | 185 | #: inc/task.class.php:1506 186 | msgid "A user is already performing the task" 187 | msgstr "そのタスクはユーザーがすでに実行中" 188 | 189 | #: inc/task.class.php:1556 190 | #, php-format 191 | msgid "You are already working on %s" 192 | msgstr "あなたはすでに %s の作業中です。" 193 | 194 | #: inc/task.class.php:1587 195 | msgid "Timer started" 196 | msgstr "タイマーをスタートしました" 197 | 198 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 199 | msgid "Timer completed" 200 | msgstr "タイマー完了" 201 | 202 | #: inc/task.class.php:1699 inc/task.class.php:1813 203 | msgid "Only the user who initiated the task can close it" 204 | msgstr "開始ユーザーのみタスクを終了可" 205 | 206 | #: inc/task.class.php:1702 207 | msgid "The task had not been initialized" 208 | msgstr "タスクは初期化されていませんでした" 209 | -------------------------------------------------------------------------------- /locales/he_IL.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: he_IL\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (((n<0 || n>10)) " 12 | "&& (n%10==0)) ? 2 : 3;\n" 13 | 14 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 15 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 16 | msgid "Duration Diff" 17 | msgstr "Duration Diff" 18 | 19 | #. TRANS: d is a symbol for days in a time (displays: 3d) 20 | #: ajax/timer.php:70 21 | #, php-format 22 | msgid "%dd" 23 | msgstr "%dd" 24 | 25 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 26 | #: ajax/timer.php:74 27 | #, php-format 28 | msgid "%dh" 29 | msgstr "%dh" 30 | 31 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 32 | #: ajax/timer.php:78 33 | #, php-format 34 | msgid "%dmin" 35 | msgstr "דקה %d" 36 | 37 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 38 | #: ajax/timer.php:82 39 | #, php-format 40 | msgid "%ds" 41 | msgstr "%ds" 42 | 43 | #: ajax/timer.php:93 44 | msgid "Timer started on" 45 | msgstr "טיימר התחיל" 46 | 47 | #: inc/config.class.php:65 48 | msgid "ActualTime Setup" 49 | msgstr "ActualTime Setup" 50 | 51 | #: inc/config.class.php:99 52 | msgid "In Standard interface only (default)" 53 | msgstr "בממשק סטנדרטי בלבד (ברירת מחדל)" 54 | 55 | #: inc/config.class.php:100 56 | msgid "Both in Standard and Helpdesk interfaces" 57 | msgstr "הן בממשק רגיל והן בממשק צוות תמיכה" 58 | 59 | #: inc/config.class.php:106 60 | msgid "Enable timer on tasks" 61 | msgstr "הפעלת טיימר במשימות" 62 | 63 | #: inc/config.class.php:118 64 | msgid "Display pop-up window with current running timer" 65 | msgstr "Display pop-up window with current running timer" 66 | 67 | #: inc/config.class.php:124 68 | msgid "Display actual time in closed task box ('Processing ticket' list)" 69 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 70 | 71 | #: inc/config.class.php:130 72 | msgid "Automatically open task with timer running" 73 | msgstr "פתיחה אוטומטית של משימה עם טיימר פועל" 74 | 75 | #: inc/config.class.php:136 76 | msgid "Automatically update the duration" 77 | msgstr "עדכן אוטומטית את משך הזמן" 78 | 79 | #: inc/config.class.php:142 80 | msgid "Enable Timer Only on Scheduled Task Day" 81 | msgstr "Enable Timer Only on Scheduled Task Day" 82 | 83 | #: inc/config.class.php:148 84 | msgid "Enable Timer Only on Task's Start Day" 85 | msgstr "Enable Timer Only on Task's Start Day" 86 | 87 | #: inc/dashboard.class.php:48 88 | msgid "Top 20 Actualtime tasks per day" 89 | msgstr "Top 20 Actualtime tasks per day" 90 | 91 | #: inc/dashboard.class.php:56 92 | msgid "Bottom 20 Actualtime tasks per day" 93 | msgstr "Bottom 20 Actualtime tasks per day" 94 | 95 | #: inc/dashboard.class.php:64 96 | msgid "Top 20 Actualtime usage (hours)" 97 | msgstr "Top 20 Actualtime usage (hours)" 98 | 99 | #: inc/dashboard.class.php:72 100 | msgid "Bottom 20 Actualtime usage (hours)" 101 | msgstr "Bottom 20 Actualtime usage (hours)" 102 | 103 | #: inc/dashboard.class.php:79 104 | msgid "Top 20 % Actualtime usage per day" 105 | msgstr "Top 20 % Actualtime usage per day" 106 | 107 | #: inc/dashboard.class.php:87 108 | msgid "Bottom 20 % Actualtime usage per day" 109 | msgstr "Bottom 20 % Actualtime usage per day" 110 | 111 | #: inc/profile.class.php:103 112 | msgid "General" 113 | msgstr "General" 114 | 115 | #: inc/profile.class.php:138 inc/running.class.php:71 116 | msgid "Running timers" 117 | msgstr "טיימרים פועלים" 118 | 119 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 120 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 121 | msgid "Modify timers" 122 | msgstr "Modify timers" 123 | 124 | #: inc/running.class.php:76 125 | msgid "Update every (s)" 126 | msgstr "עדכן כל (ים)" 127 | 128 | #: inc/sourcetimer.class.php:53 129 | msgid "Modify tickets" 130 | msgstr "Modify tickets" 131 | 132 | #: inc/sourcetimer.class.php:54 133 | msgid "Modify changes" 134 | msgstr "Modify changes" 135 | 136 | #: inc/sourcetimer.class.php:55 137 | msgid "Modify projects" 138 | msgstr "Modify projects" 139 | 140 | #: inc/task.class.php:321 inc/task.class.php:482 141 | msgid "Actual Duration" 142 | msgstr "Actual Duration" 143 | 144 | #: inc/task.class.php:332 inc/task.class.php:493 145 | msgid "Partial actual duration" 146 | msgstr "Partial actual duration" 147 | 148 | #: inc/task.class.php:970 149 | msgid "Original end date" 150 | msgstr "Original end date" 151 | 152 | #: inc/task.class.php:971 153 | msgid "Original duration" 154 | msgstr "Original duration" 155 | 156 | #: inc/task.class.php:972 157 | #, php-format 158 | msgid "First modification by %s" 159 | msgstr "First modification by %s" 160 | 161 | #: inc/task.class.php:1362 inc/task.class.php:1368 162 | #, php-format 163 | msgid "You cannot start a timer because the task was scheduled for %d." 164 | msgstr "You cannot start a timer because the task was scheduled for %d." 165 | 166 | #: inc/task.class.php:1392 167 | msgid "You cannot add a timer on a different day." 168 | msgstr "You cannot add a timer on a different day." 169 | 170 | #: inc/task.class.php:1435 171 | msgid "Today is marked as absence you can not initialize the timer" 172 | msgstr "היום מסומן כהיעדרות, אתה לא יכול לאתחל את הטיימר" 173 | 174 | #: inc/task.class.php:1441 175 | msgid "Timer has not been initialized" 176 | msgstr "שעון העצר לא אותחל" 177 | 178 | #: inc/task.class.php:1458 179 | msgid "You are already doing a waypoint" 180 | msgstr "You are already doing a waypoint" 181 | 182 | #: inc/task.class.php:1495 inc/task.class.php:1500 183 | msgid "Technician not in charge of the task" 184 | msgstr "Technician not in charge of the task" 185 | 186 | #: inc/task.class.php:1506 187 | msgid "A user is already performing the task" 188 | msgstr "אדם אחד כבר מבצע את המשימה" 189 | 190 | #: inc/task.class.php:1556 191 | #, php-format 192 | msgid "You are already working on %s" 193 | msgstr "You are already working on %s" 194 | 195 | #: inc/task.class.php:1587 196 | msgid "Timer started" 197 | msgstr "Timer started" 198 | 199 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 200 | msgid "Timer completed" 201 | msgstr "טיימר הושלם" 202 | 203 | #: inc/task.class.php:1699 inc/task.class.php:1813 204 | msgid "Only the user who initiated the task can close it" 205 | msgstr "רק המשתמש שיזם את המשימה יכול לסגור אותה" 206 | 207 | #: inc/task.class.php:1702 208 | msgid "The task had not been initialized" 209 | msgstr "המשימה לא אותחלה" 210 | -------------------------------------------------------------------------------- /setup.php: -------------------------------------------------------------------------------- 1 | . 21 | * ------------------------------------------------------------------------- 22 | * @package ActualTime 23 | * @author the TICGAL team 24 | * @copyright Copyright (c) 2018-2025 TICGAL team 25 | * @license AGPL License 3.0 or (at your option) any later version 26 | * http://www.gnu.org/licenses/agpl-3.0-standalone.html 27 | * @link https://www.tic.gal/ 28 | * @since 2018 29 | * ------------------------------------------------------------------------- 30 | */ 31 | 32 | use Glpi\Plugin\Hooks; 33 | 34 | define('PLUGIN_ACTUALTIME_VERSION', '3.2.2'); 35 | 36 | // Minimal GLPI version, inclusive 37 | define("PLUGIN_ACTUALTIME_MIN_GLPI", "10.0.10"); 38 | // Maximum GLPI version, exclusive 39 | define("PLUGIN_ACTUALTIME_MAX_GLPI", "10.1.0"); 40 | define("PLUGIN_ACTUALTIME_NAME", "ActualTime"); 41 | 42 | /** 43 | * plugin_version_actualtime 44 | * 45 | * @return array 46 | */ 47 | function plugin_version_actualtime(): array 48 | { 49 | return [ 50 | 'name' => PLUGIN_ACTUALTIME_NAME, 51 | 'version' => PLUGIN_ACTUALTIME_VERSION, 52 | 'author' => 'TICGAL', 53 | 'homepage' => 'https://tic.gal/en/project/actualtime-plugin-glpi/', 54 | 'license' => 'AGPLv3+', 55 | 'requirements' => [ 56 | 'glpi' => [ 57 | 'min' => PLUGIN_ACTUALTIME_MIN_GLPI, 58 | 'max' => PLUGIN_ACTUALTIME_MAX_GLPI, 59 | ], 60 | ], 61 | ]; 62 | } 63 | 64 | /** 65 | * plugin_init_actualtime 66 | * 67 | * @return void 68 | */ 69 | function plugin_init_actualtime(): void 70 | { 71 | /** @var array $PLUGIN_HOOKS */ 72 | global $PLUGIN_HOOKS; 73 | 74 | $PLUGIN_HOOKS[Hooks::CSRF_COMPLIANT]['actualtime'] = true; 75 | 76 | if (Plugin::isPluginActive('actualtime')) { 77 | // Classes 78 | Plugin::registerClass(PluginActualtimeProfile::class, ['addtabon' => Profile::class]); 79 | // Add settings form as a tab on Setup - General page 80 | Plugin::registerClass(PluginActualtimeConfig::class, ['addtabon' => Config::class]); 81 | 82 | Plugin::registerClass(PluginActualtimeTask::class, ['planning_types' => true]); 83 | 84 | // Hooks 85 | $PLUGIN_HOOKS[Hooks::POST_ITEM_FORM]['actualtime'] = [ 86 | PluginActualtimeTask::class, 'postForm', 87 | ]; 88 | 89 | $PLUGIN_HOOKS[Hooks::SHOW_ITEM_STATS]['actualtime'] = [ 90 | Ticket::class => 'plugin_actualtime_item_stats', 91 | Change::class => 'plugin_actualtime_item_stats', 92 | Problem::class => 'plugin_actualtime_item_stats', 93 | ]; 94 | 95 | $PLUGIN_HOOKS[Hooks::PRE_ITEM_UPDATE]['actualtime'] = [ 96 | TicketTask::class => 'plugin_actualtime_item_update', 97 | ChangeTask::class => 'plugin_actualtime_item_update', 98 | ProblemTask::class => 'plugin_actualtime_item_update', 99 | ProjectTask::class => 'plugin_actualtime_item_update', 100 | ]; 101 | 102 | $PLUGIN_HOOKS[Hooks::ITEM_DELETE]['actualtime'] = [ 103 | Ticket::class => 'plugin_actualtime_parent_delete', 104 | Change::class => 'plugin_actualtime_parent_delete', 105 | Problem::class => 'plugin_actualtime_parent_delete', 106 | Project::class => 'plugin_actualtime_project_delete', 107 | ]; 108 | 109 | $PLUGIN_HOOKS[Hooks::ITEM_PURGE]['actualtime'] = [ 110 | TicketTask::class => 'plugin_actualtime_item_purge', 111 | ChangeTask::class => 'plugin_actualtime_item_purge', 112 | ProblemTask::class => 'plugin_actualtime_item_purge', 113 | ProjectTask::class => 'plugin_actualtime_item_purge', 114 | ]; 115 | 116 | $PLUGIN_HOOKS[Hooks::PRE_ITEM_ADD]['actualtime'] = [ 117 | ITILSolution::class => 'plugin_actualtime_preSolutionAdd', 118 | ]; 119 | 120 | $PLUGIN_HOOKS[Hooks::ITEM_ADD]['actualtime'] = [ 121 | TicketTask::class => 'plugin_actualtime_item_add', 122 | ChangeTask::class => 'plugin_actualtime_item_add', 123 | ProblemTask::class => 'plugin_actualtime_item_add', 124 | ]; 125 | 126 | $PLUGIN_HOOKS[Hooks::POST_SHOW_ITEM]['actualtime'] = 'plugin_actualtime_postshowitem'; 127 | 128 | $PLUGIN_HOOKS[Hooks::DASHBOARD_CARDS]['actualtime'] = [ 129 | PluginActualtimeDashboard::class, 'dashboardCards', 130 | ]; 131 | 132 | $config = new PluginActualtimeConfig(); 133 | if ($config->showTimerPopup()) { 134 | // This hook is not needed if not showing popup 135 | $PLUGIN_HOOKS[Hooks::POST_SHOW_TAB]['actualtime'] = [ 136 | PluginActualtimeTask::class, 'postShowTab', 137 | ]; 138 | } 139 | 140 | if (Session::getLoginUserID()) { 141 | $PLUGIN_HOOKS[Hooks::ADD_JAVASCRIPT]['actualtime'] = 'js/actualtime.js'; 142 | 143 | /** @var array $CFG_GLPI */ 144 | global $CFG_GLPI; 145 | 146 | // preload the fullcalendar library 147 | $CFG_GLPI['javascript']['actualtime']['sourcetimer'] = ['fullcalendar']; 148 | } 149 | 150 | if (Session::haveRight('plugin_actualtime_running', READ)) { 151 | $PLUGIN_HOOKS['menu_toadd']['actualtime'] = [ 152 | 'admin' => 'PluginActualtimeRunning', 153 | ]; 154 | } 155 | 156 | // Standard settings link, on Setup - Plugins page 157 | $PLUGIN_HOOKS[Hooks::CONFIG_PAGE]['actualtime'] = 'front/config.form.php'; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /locales/ca_ES.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: ca_ES\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=2; plural=(n==1) ? 0 : 1;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Duration Diff" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%dd" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%dh" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%dmin" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%ds" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Timer started on" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime Setup" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "In Standard interface only (default)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Both in Standard and Helpdesk interfaces" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Enable timer on tasks" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Display pop-up window with current running timer" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 69 | 70 | #: inc/config.class.php:130 71 | msgid "Automatically open task with timer running" 72 | msgstr "Automatically open task with timer running" 73 | 74 | #: inc/config.class.php:136 75 | msgid "Automatically update the duration" 76 | msgstr "Automatically update the duration" 77 | 78 | #: inc/config.class.php:142 79 | msgid "Enable Timer Only on Scheduled Task Day" 80 | msgstr "Enable Timer Only on Scheduled Task Day" 81 | 82 | #: inc/config.class.php:148 83 | msgid "Enable Timer Only on Task's Start Day" 84 | msgstr "Enable Timer Only on Task's Start Day" 85 | 86 | #: inc/dashboard.class.php:48 87 | msgid "Top 20 Actualtime tasks per day" 88 | msgstr "Top 20 Actualtime tasks per day" 89 | 90 | #: inc/dashboard.class.php:56 91 | msgid "Bottom 20 Actualtime tasks per day" 92 | msgstr "Bottom 20 Actualtime tasks per day" 93 | 94 | #: inc/dashboard.class.php:64 95 | msgid "Top 20 Actualtime usage (hours)" 96 | msgstr "Top 20 Actualtime usage (hours)" 97 | 98 | #: inc/dashboard.class.php:72 99 | msgid "Bottom 20 Actualtime usage (hours)" 100 | msgstr "Bottom 20 Actualtime usage (hours)" 101 | 102 | #: inc/dashboard.class.php:79 103 | msgid "Top 20 % Actualtime usage per day" 104 | msgstr "Top 20 % Actualtime usage per day" 105 | 106 | #: inc/dashboard.class.php:87 107 | msgid "Bottom 20 % Actualtime usage per day" 108 | msgstr "Bottom 20 % Actualtime usage per day" 109 | 110 | #: inc/profile.class.php:103 111 | msgid "General" 112 | msgstr "General" 113 | 114 | #: inc/profile.class.php:138 inc/running.class.php:71 115 | msgid "Running timers" 116 | msgstr "Running timers" 117 | 118 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 119 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 120 | msgid "Modify timers" 121 | msgstr "Modify timers" 122 | 123 | #: inc/running.class.php:76 124 | msgid "Update every (s)" 125 | msgstr "Update every (s)" 126 | 127 | #: inc/sourcetimer.class.php:53 128 | msgid "Modify tickets" 129 | msgstr "Modify tickets" 130 | 131 | #: inc/sourcetimer.class.php:54 132 | msgid "Modify changes" 133 | msgstr "Modify changes" 134 | 135 | #: inc/sourcetimer.class.php:55 136 | msgid "Modify projects" 137 | msgstr "Modify projects" 138 | 139 | #: inc/task.class.php:321 inc/task.class.php:482 140 | msgid "Actual Duration" 141 | msgstr "Actual Duration" 142 | 143 | #: inc/task.class.php:332 inc/task.class.php:493 144 | msgid "Partial actual duration" 145 | msgstr "Partial actual duration" 146 | 147 | #: inc/task.class.php:970 148 | msgid "Original end date" 149 | msgstr "Original end date" 150 | 151 | #: inc/task.class.php:971 152 | msgid "Original duration" 153 | msgstr "Original duration" 154 | 155 | #: inc/task.class.php:972 156 | #, php-format 157 | msgid "First modification by %s" 158 | msgstr "First modification by %s" 159 | 160 | #: inc/task.class.php:1362 inc/task.class.php:1368 161 | #, php-format 162 | msgid "You cannot start a timer because the task was scheduled for %d." 163 | msgstr "You cannot start a timer because the task was scheduled for %d." 164 | 165 | #: inc/task.class.php:1392 166 | msgid "You cannot add a timer on a different day." 167 | msgstr "You cannot add a timer on a different day." 168 | 169 | #: inc/task.class.php:1435 170 | msgid "Today is marked as absence you can not initialize the timer" 171 | msgstr "Today is marked as absence you can not initialize the timer" 172 | 173 | #: inc/task.class.php:1441 174 | msgid "Timer has not been initialized" 175 | msgstr "Timer has not been initialized" 176 | 177 | #: inc/task.class.php:1458 178 | msgid "You are already doing a waypoint" 179 | msgstr "You are already doing a waypoint" 180 | 181 | #: inc/task.class.php:1495 inc/task.class.php:1500 182 | msgid "Technician not in charge of the task" 183 | msgstr "Technician not in charge of the task" 184 | 185 | #: inc/task.class.php:1506 186 | msgid "A user is already performing the task" 187 | msgstr "A user is already performing the task" 188 | 189 | #: inc/task.class.php:1556 190 | #, php-format 191 | msgid "You are already working on %s" 192 | msgstr "You are already working on %s" 193 | 194 | #: inc/task.class.php:1587 195 | msgid "Timer started" 196 | msgstr "Timer started" 197 | 198 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 199 | msgid "Timer completed" 200 | msgstr "Timer completed" 201 | 202 | #: inc/task.class.php:1699 inc/task.class.php:1813 203 | msgid "Only the user who initiated the task can close it" 204 | msgstr "Only the user who initiated the task can close it" 205 | 206 | #: inc/task.class.php:1702 207 | msgid "The task had not been initialized" 208 | msgstr "The task had not been initialized" 209 | -------------------------------------------------------------------------------- /locales/el_GR.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: el_GR\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=2; plural=(n==1) ? 0 : 1;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Duration Diff" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%dd" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%dh" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%dmin" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%ds" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Timer started on" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime Setup" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "In Standard interface only (default)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Both in Standard and Helpdesk interfaces" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Enable timer on tasks" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Display pop-up window with current running timer" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 69 | 70 | #: inc/config.class.php:130 71 | msgid "Automatically open task with timer running" 72 | msgstr "Automatically open task with timer running" 73 | 74 | #: inc/config.class.php:136 75 | msgid "Automatically update the duration" 76 | msgstr "Automatically update the duration" 77 | 78 | #: inc/config.class.php:142 79 | msgid "Enable Timer Only on Scheduled Task Day" 80 | msgstr "Enable Timer Only on Scheduled Task Day" 81 | 82 | #: inc/config.class.php:148 83 | msgid "Enable Timer Only on Task's Start Day" 84 | msgstr "Enable Timer Only on Task's Start Day" 85 | 86 | #: inc/dashboard.class.php:48 87 | msgid "Top 20 Actualtime tasks per day" 88 | msgstr "Top 20 Actualtime tasks per day" 89 | 90 | #: inc/dashboard.class.php:56 91 | msgid "Bottom 20 Actualtime tasks per day" 92 | msgstr "Bottom 20 Actualtime tasks per day" 93 | 94 | #: inc/dashboard.class.php:64 95 | msgid "Top 20 Actualtime usage (hours)" 96 | msgstr "Top 20 Actualtime usage (hours)" 97 | 98 | #: inc/dashboard.class.php:72 99 | msgid "Bottom 20 Actualtime usage (hours)" 100 | msgstr "Bottom 20 Actualtime usage (hours)" 101 | 102 | #: inc/dashboard.class.php:79 103 | msgid "Top 20 % Actualtime usage per day" 104 | msgstr "Top 20 % Actualtime usage per day" 105 | 106 | #: inc/dashboard.class.php:87 107 | msgid "Bottom 20 % Actualtime usage per day" 108 | msgstr "Bottom 20 % Actualtime usage per day" 109 | 110 | #: inc/profile.class.php:103 111 | msgid "General" 112 | msgstr "General" 113 | 114 | #: inc/profile.class.php:138 inc/running.class.php:71 115 | msgid "Running timers" 116 | msgstr "Running timers" 117 | 118 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 119 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 120 | msgid "Modify timers" 121 | msgstr "Modify timers" 122 | 123 | #: inc/running.class.php:76 124 | msgid "Update every (s)" 125 | msgstr "Update every (s)" 126 | 127 | #: inc/sourcetimer.class.php:53 128 | msgid "Modify tickets" 129 | msgstr "Modify tickets" 130 | 131 | #: inc/sourcetimer.class.php:54 132 | msgid "Modify changes" 133 | msgstr "Modify changes" 134 | 135 | #: inc/sourcetimer.class.php:55 136 | msgid "Modify projects" 137 | msgstr "Modify projects" 138 | 139 | #: inc/task.class.php:321 inc/task.class.php:482 140 | msgid "Actual Duration" 141 | msgstr "Actual Duration" 142 | 143 | #: inc/task.class.php:332 inc/task.class.php:493 144 | msgid "Partial actual duration" 145 | msgstr "Partial actual duration" 146 | 147 | #: inc/task.class.php:970 148 | msgid "Original end date" 149 | msgstr "Original end date" 150 | 151 | #: inc/task.class.php:971 152 | msgid "Original duration" 153 | msgstr "Original duration" 154 | 155 | #: inc/task.class.php:972 156 | #, php-format 157 | msgid "First modification by %s" 158 | msgstr "First modification by %s" 159 | 160 | #: inc/task.class.php:1362 inc/task.class.php:1368 161 | #, php-format 162 | msgid "You cannot start a timer because the task was scheduled for %d." 163 | msgstr "You cannot start a timer because the task was scheduled for %d." 164 | 165 | #: inc/task.class.php:1392 166 | msgid "You cannot add a timer on a different day." 167 | msgstr "You cannot add a timer on a different day." 168 | 169 | #: inc/task.class.php:1435 170 | msgid "Today is marked as absence you can not initialize the timer" 171 | msgstr "Today is marked as absence you can not initialize the timer" 172 | 173 | #: inc/task.class.php:1441 174 | msgid "Timer has not been initialized" 175 | msgstr "Timer has not been initialized" 176 | 177 | #: inc/task.class.php:1458 178 | msgid "You are already doing a waypoint" 179 | msgstr "You are already doing a waypoint" 180 | 181 | #: inc/task.class.php:1495 inc/task.class.php:1500 182 | msgid "Technician not in charge of the task" 183 | msgstr "Technician not in charge of the task" 184 | 185 | #: inc/task.class.php:1506 186 | msgid "A user is already performing the task" 187 | msgstr "A user is already performing the task" 188 | 189 | #: inc/task.class.php:1556 190 | #, php-format 191 | msgid "You are already working on %s" 192 | msgstr "You are already working on %s" 193 | 194 | #: inc/task.class.php:1587 195 | msgid "Timer started" 196 | msgstr "Timer started" 197 | 198 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 199 | msgid "Timer completed" 200 | msgstr "Timer completed" 201 | 202 | #: inc/task.class.php:1699 inc/task.class.php:1813 203 | msgid "Only the user who initiated the task can close it" 204 | msgstr "Only the user who initiated the task can close it" 205 | 206 | #: inc/task.class.php:1702 207 | msgid "The task had not been initialized" 208 | msgstr "The task had not been initialized" 209 | -------------------------------------------------------------------------------- /locales/en_GB.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: en_GB\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=2; plural=(n==1) ? 0 : 1;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Duration Diff" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%dd" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%dh" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%dmin" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%ds" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Timer started on" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime Setup" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "In Standard interface only (default)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Both in Standard and Helpdesk interfaces" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Enable timer on tasks" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Display pop-up window with current running timer" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 69 | 70 | #: inc/config.class.php:130 71 | msgid "Automatically open task with timer running" 72 | msgstr "Automatically open task with timer running" 73 | 74 | #: inc/config.class.php:136 75 | msgid "Automatically update the duration" 76 | msgstr "Automatically update the duration" 77 | 78 | #: inc/config.class.php:142 79 | msgid "Enable Timer Only on Scheduled Task Day" 80 | msgstr "Enable Timer Only on Scheduled Task Day" 81 | 82 | #: inc/config.class.php:148 83 | msgid "Enable Timer Only on Task's Start Day" 84 | msgstr "Enable Timer Only on Task's Start Day" 85 | 86 | #: inc/dashboard.class.php:48 87 | msgid "Top 20 Actualtime tasks per day" 88 | msgstr "Top 20 Actualtime tasks per day" 89 | 90 | #: inc/dashboard.class.php:56 91 | msgid "Bottom 20 Actualtime tasks per day" 92 | msgstr "Bottom 20 Actualtime tasks per day" 93 | 94 | #: inc/dashboard.class.php:64 95 | msgid "Top 20 Actualtime usage (hours)" 96 | msgstr "Top 20 Actualtime usage (hours)" 97 | 98 | #: inc/dashboard.class.php:72 99 | msgid "Bottom 20 Actualtime usage (hours)" 100 | msgstr "Bottom 20 Actualtime usage (hours)" 101 | 102 | #: inc/dashboard.class.php:79 103 | msgid "Top 20 % Actualtime usage per day" 104 | msgstr "Top 20 % Actualtime usage per day" 105 | 106 | #: inc/dashboard.class.php:87 107 | msgid "Bottom 20 % Actualtime usage per day" 108 | msgstr "Bottom 20 % Actualtime usage per day" 109 | 110 | #: inc/profile.class.php:103 111 | msgid "General" 112 | msgstr "General" 113 | 114 | #: inc/profile.class.php:138 inc/running.class.php:71 115 | msgid "Running timers" 116 | msgstr "Running timers" 117 | 118 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 119 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 120 | msgid "Modify timers" 121 | msgstr "Modify timers" 122 | 123 | #: inc/running.class.php:76 124 | msgid "Update every (s)" 125 | msgstr "Update every (s)" 126 | 127 | #: inc/sourcetimer.class.php:53 128 | msgid "Modify tickets" 129 | msgstr "Modify tickets" 130 | 131 | #: inc/sourcetimer.class.php:54 132 | msgid "Modify changes" 133 | msgstr "Modify changes" 134 | 135 | #: inc/sourcetimer.class.php:55 136 | msgid "Modify projects" 137 | msgstr "Modify projects" 138 | 139 | #: inc/task.class.php:321 inc/task.class.php:482 140 | msgid "Actual Duration" 141 | msgstr "Actual Duration" 142 | 143 | #: inc/task.class.php:332 inc/task.class.php:493 144 | msgid "Partial actual duration" 145 | msgstr "Partial actual duration" 146 | 147 | #: inc/task.class.php:970 148 | msgid "Original end date" 149 | msgstr "Original end date" 150 | 151 | #: inc/task.class.php:971 152 | msgid "Original duration" 153 | msgstr "Original duration" 154 | 155 | #: inc/task.class.php:972 156 | #, php-format 157 | msgid "First modification by %s" 158 | msgstr "First modification by %s" 159 | 160 | #: inc/task.class.php:1362 inc/task.class.php:1368 161 | #, php-format 162 | msgid "You cannot start a timer because the task was scheduled for %d." 163 | msgstr "You cannot start a timer because the task was scheduled for %d." 164 | 165 | #: inc/task.class.php:1392 166 | msgid "You cannot add a timer on a different day." 167 | msgstr "You cannot add a timer on a different day." 168 | 169 | #: inc/task.class.php:1435 170 | msgid "Today is marked as absence you can not initialize the timer" 171 | msgstr "Today is marked as absence you can not initialize the timer" 172 | 173 | #: inc/task.class.php:1441 174 | msgid "Timer has not been initialized" 175 | msgstr "Timer has not been initialized" 176 | 177 | #: inc/task.class.php:1458 178 | msgid "You are already doing a waypoint" 179 | msgstr "You are already doing a waypoint" 180 | 181 | #: inc/task.class.php:1495 inc/task.class.php:1500 182 | msgid "Technician not in charge of the task" 183 | msgstr "Technician not in charge of the task" 184 | 185 | #: inc/task.class.php:1506 186 | msgid "A user is already performing the task" 187 | msgstr "A user is already performing the task" 188 | 189 | #: inc/task.class.php:1556 190 | #, php-format 191 | msgid "You are already working on %s" 192 | msgstr "You are already working on %s" 193 | 194 | #: inc/task.class.php:1587 195 | msgid "Timer started" 196 | msgstr "Timer started" 197 | 198 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 199 | msgid "Timer completed" 200 | msgstr "Timer completed" 201 | 202 | #: inc/task.class.php:1699 inc/task.class.php:1813 203 | msgid "Only the user who initiated the task can close it" 204 | msgstr "Only the user who initiated the task can close it" 205 | 206 | #: inc/task.class.php:1702 207 | msgid "The task had not been initialized" 208 | msgstr "The task had not been initialized" 209 | -------------------------------------------------------------------------------- /locales/hu_HU.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: hu_HU\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=2; plural=(n==1) ? 0 : 1;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Duration Diff" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%dd" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%dh" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%dmin" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%ds" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Timer started on" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime Setup" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "In Standard interface only (default)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Both in Standard and Helpdesk interfaces" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Enable timer on tasks" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Display pop-up window with current running timer" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 69 | 70 | #: inc/config.class.php:130 71 | msgid "Automatically open task with timer running" 72 | msgstr "Automatically open task with timer running" 73 | 74 | #: inc/config.class.php:136 75 | msgid "Automatically update the duration" 76 | msgstr "Automatically update the duration" 77 | 78 | #: inc/config.class.php:142 79 | msgid "Enable Timer Only on Scheduled Task Day" 80 | msgstr "Enable Timer Only on Scheduled Task Day" 81 | 82 | #: inc/config.class.php:148 83 | msgid "Enable Timer Only on Task's Start Day" 84 | msgstr "Enable Timer Only on Task's Start Day" 85 | 86 | #: inc/dashboard.class.php:48 87 | msgid "Top 20 Actualtime tasks per day" 88 | msgstr "Top 20 Actualtime tasks per day" 89 | 90 | #: inc/dashboard.class.php:56 91 | msgid "Bottom 20 Actualtime tasks per day" 92 | msgstr "Bottom 20 Actualtime tasks per day" 93 | 94 | #: inc/dashboard.class.php:64 95 | msgid "Top 20 Actualtime usage (hours)" 96 | msgstr "Top 20 Actualtime usage (hours)" 97 | 98 | #: inc/dashboard.class.php:72 99 | msgid "Bottom 20 Actualtime usage (hours)" 100 | msgstr "Bottom 20 Actualtime usage (hours)" 101 | 102 | #: inc/dashboard.class.php:79 103 | msgid "Top 20 % Actualtime usage per day" 104 | msgstr "Top 20 % Actualtime usage per day" 105 | 106 | #: inc/dashboard.class.php:87 107 | msgid "Bottom 20 % Actualtime usage per day" 108 | msgstr "Bottom 20 % Actualtime usage per day" 109 | 110 | #: inc/profile.class.php:103 111 | msgid "General" 112 | msgstr "General" 113 | 114 | #: inc/profile.class.php:138 inc/running.class.php:71 115 | msgid "Running timers" 116 | msgstr "Running timers" 117 | 118 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 119 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 120 | msgid "Modify timers" 121 | msgstr "Modify timers" 122 | 123 | #: inc/running.class.php:76 124 | msgid "Update every (s)" 125 | msgstr "Update every (s)" 126 | 127 | #: inc/sourcetimer.class.php:53 128 | msgid "Modify tickets" 129 | msgstr "Modify tickets" 130 | 131 | #: inc/sourcetimer.class.php:54 132 | msgid "Modify changes" 133 | msgstr "Modify changes" 134 | 135 | #: inc/sourcetimer.class.php:55 136 | msgid "Modify projects" 137 | msgstr "Modify projects" 138 | 139 | #: inc/task.class.php:321 inc/task.class.php:482 140 | msgid "Actual Duration" 141 | msgstr "Actual Duration" 142 | 143 | #: inc/task.class.php:332 inc/task.class.php:493 144 | msgid "Partial actual duration" 145 | msgstr "Partial actual duration" 146 | 147 | #: inc/task.class.php:970 148 | msgid "Original end date" 149 | msgstr "Original end date" 150 | 151 | #: inc/task.class.php:971 152 | msgid "Original duration" 153 | msgstr "Original duration" 154 | 155 | #: inc/task.class.php:972 156 | #, php-format 157 | msgid "First modification by %s" 158 | msgstr "First modification by %s" 159 | 160 | #: inc/task.class.php:1362 inc/task.class.php:1368 161 | #, php-format 162 | msgid "You cannot start a timer because the task was scheduled for %d." 163 | msgstr "You cannot start a timer because the task was scheduled for %d." 164 | 165 | #: inc/task.class.php:1392 166 | msgid "You cannot add a timer on a different day." 167 | msgstr "You cannot add a timer on a different day." 168 | 169 | #: inc/task.class.php:1435 170 | msgid "Today is marked as absence you can not initialize the timer" 171 | msgstr "Today is marked as absence you can not initialize the timer" 172 | 173 | #: inc/task.class.php:1441 174 | msgid "Timer has not been initialized" 175 | msgstr "Timer has not been initialized" 176 | 177 | #: inc/task.class.php:1458 178 | msgid "You are already doing a waypoint" 179 | msgstr "You are already doing a waypoint" 180 | 181 | #: inc/task.class.php:1495 inc/task.class.php:1500 182 | msgid "Technician not in charge of the task" 183 | msgstr "Technician not in charge of the task" 184 | 185 | #: inc/task.class.php:1506 186 | msgid "A user is already performing the task" 187 | msgstr "A user is already performing the task" 188 | 189 | #: inc/task.class.php:1556 190 | #, php-format 191 | msgid "You are already working on %s" 192 | msgstr "You are already working on %s" 193 | 194 | #: inc/task.class.php:1587 195 | msgid "Timer started" 196 | msgstr "Timer started" 197 | 198 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 199 | msgid "Timer completed" 200 | msgstr "Timer completed" 201 | 202 | #: inc/task.class.php:1699 inc/task.class.php:1813 203 | msgid "Only the user who initiated the task can close it" 204 | msgstr "Only the user who initiated the task can close it" 205 | 206 | #: inc/task.class.php:1702 207 | msgid "The task had not been initialized" 208 | msgstr "The task had not been initialized" 209 | -------------------------------------------------------------------------------- /locales/pt_PT.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: pt_PT\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=2; plural=(n==1) ? 0 : 1;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Duration Diff" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%dd" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%dh" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%dmin" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%ds" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Timer started on" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime Setup" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "In Standard interface only (default)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Both in Standard and Helpdesk interfaces" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Enable timer on tasks" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Display pop-up window with current running timer" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 69 | 70 | #: inc/config.class.php:130 71 | msgid "Automatically open task with timer running" 72 | msgstr "Automatically open task with timer running" 73 | 74 | #: inc/config.class.php:136 75 | msgid "Automatically update the duration" 76 | msgstr "Automatically update the duration" 77 | 78 | #: inc/config.class.php:142 79 | msgid "Enable Timer Only on Scheduled Task Day" 80 | msgstr "Enable Timer Only on Scheduled Task Day" 81 | 82 | #: inc/config.class.php:148 83 | msgid "Enable Timer Only on Task's Start Day" 84 | msgstr "Enable Timer Only on Task's Start Day" 85 | 86 | #: inc/dashboard.class.php:48 87 | msgid "Top 20 Actualtime tasks per day" 88 | msgstr "Top 20 Actualtime tasks per day" 89 | 90 | #: inc/dashboard.class.php:56 91 | msgid "Bottom 20 Actualtime tasks per day" 92 | msgstr "Bottom 20 Actualtime tasks per day" 93 | 94 | #: inc/dashboard.class.php:64 95 | msgid "Top 20 Actualtime usage (hours)" 96 | msgstr "Top 20 Actualtime usage (hours)" 97 | 98 | #: inc/dashboard.class.php:72 99 | msgid "Bottom 20 Actualtime usage (hours)" 100 | msgstr "Bottom 20 Actualtime usage (hours)" 101 | 102 | #: inc/dashboard.class.php:79 103 | msgid "Top 20 % Actualtime usage per day" 104 | msgstr "Top 20 % Actualtime usage per day" 105 | 106 | #: inc/dashboard.class.php:87 107 | msgid "Bottom 20 % Actualtime usage per day" 108 | msgstr "Bottom 20 % Actualtime usage per day" 109 | 110 | #: inc/profile.class.php:103 111 | msgid "General" 112 | msgstr "General" 113 | 114 | #: inc/profile.class.php:138 inc/running.class.php:71 115 | msgid "Running timers" 116 | msgstr "Running timers" 117 | 118 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 119 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 120 | msgid "Modify timers" 121 | msgstr "Modify timers" 122 | 123 | #: inc/running.class.php:76 124 | msgid "Update every (s)" 125 | msgstr "Update every (s)" 126 | 127 | #: inc/sourcetimer.class.php:53 128 | msgid "Modify tickets" 129 | msgstr "Modify tickets" 130 | 131 | #: inc/sourcetimer.class.php:54 132 | msgid "Modify changes" 133 | msgstr "Modify changes" 134 | 135 | #: inc/sourcetimer.class.php:55 136 | msgid "Modify projects" 137 | msgstr "Modify projects" 138 | 139 | #: inc/task.class.php:321 inc/task.class.php:482 140 | msgid "Actual Duration" 141 | msgstr "Actual Duration" 142 | 143 | #: inc/task.class.php:332 inc/task.class.php:493 144 | msgid "Partial actual duration" 145 | msgstr "Partial actual duration" 146 | 147 | #: inc/task.class.php:970 148 | msgid "Original end date" 149 | msgstr "Original end date" 150 | 151 | #: inc/task.class.php:971 152 | msgid "Original duration" 153 | msgstr "Original duration" 154 | 155 | #: inc/task.class.php:972 156 | #, php-format 157 | msgid "First modification by %s" 158 | msgstr "First modification by %s" 159 | 160 | #: inc/task.class.php:1362 inc/task.class.php:1368 161 | #, php-format 162 | msgid "You cannot start a timer because the task was scheduled for %d." 163 | msgstr "You cannot start a timer because the task was scheduled for %d." 164 | 165 | #: inc/task.class.php:1392 166 | msgid "You cannot add a timer on a different day." 167 | msgstr "You cannot add a timer on a different day." 168 | 169 | #: inc/task.class.php:1435 170 | msgid "Today is marked as absence you can not initialize the timer" 171 | msgstr "Today is marked as absence you can not initialize the timer" 172 | 173 | #: inc/task.class.php:1441 174 | msgid "Timer has not been initialized" 175 | msgstr "Timer has not been initialized" 176 | 177 | #: inc/task.class.php:1458 178 | msgid "You are already doing a waypoint" 179 | msgstr "You are already doing a waypoint" 180 | 181 | #: inc/task.class.php:1495 inc/task.class.php:1500 182 | msgid "Technician not in charge of the task" 183 | msgstr "Technician not in charge of the task" 184 | 185 | #: inc/task.class.php:1506 186 | msgid "A user is already performing the task" 187 | msgstr "A user is already performing the task" 188 | 189 | #: inc/task.class.php:1556 190 | #, php-format 191 | msgid "You are already working on %s" 192 | msgstr "You are already working on %s" 193 | 194 | #: inc/task.class.php:1587 195 | msgid "Timer started" 196 | msgstr "Temporizador iniciado." 197 | 198 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 199 | msgid "Timer completed" 200 | msgstr "Timer completed" 201 | 202 | #: inc/task.class.php:1699 inc/task.class.php:1813 203 | msgid "Only the user who initiated the task can close it" 204 | msgstr "Only the user who initiated the task can close it" 205 | 206 | #: inc/task.class.php:1702 207 | msgid "The task had not been initialized" 208 | msgstr "The task had not been initialized" 209 | -------------------------------------------------------------------------------- /locales/ar_MA.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: ar_MA\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=6; plural=(n==0) ? 0 : (n==1) ? 1 : (n==2) ? 2 : " 12 | "(n%100>=3 && n%100<=10) ? 3 : (n%100>=11 && n%100<=99) ? 4 : 5;\n" 13 | 14 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 15 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 16 | msgid "Duration Diff" 17 | msgstr "Duration Diff" 18 | 19 | #. TRANS: d is a symbol for days in a time (displays: 3d) 20 | #: ajax/timer.php:70 21 | #, php-format 22 | msgid "%dd" 23 | msgstr "%dd" 24 | 25 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 26 | #: ajax/timer.php:74 27 | #, php-format 28 | msgid "%dh" 29 | msgstr "%dh" 30 | 31 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 32 | #: ajax/timer.php:78 33 | #, php-format 34 | msgid "%dmin" 35 | msgstr "%dmin" 36 | 37 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 38 | #: ajax/timer.php:82 39 | #, php-format 40 | msgid "%ds" 41 | msgstr "%ds" 42 | 43 | #: ajax/timer.php:93 44 | msgid "Timer started on" 45 | msgstr "Timer started on" 46 | 47 | #: inc/config.class.php:65 48 | msgid "ActualTime Setup" 49 | msgstr "ActualTime Setup" 50 | 51 | #: inc/config.class.php:99 52 | msgid "In Standard interface only (default)" 53 | msgstr "In Standard interface only (default)" 54 | 55 | #: inc/config.class.php:100 56 | msgid "Both in Standard and Helpdesk interfaces" 57 | msgstr "Both in Standard and Helpdesk interfaces" 58 | 59 | #: inc/config.class.php:106 60 | msgid "Enable timer on tasks" 61 | msgstr "Enable timer on tasks" 62 | 63 | #: inc/config.class.php:118 64 | msgid "Display pop-up window with current running timer" 65 | msgstr "Display pop-up window with current running timer" 66 | 67 | #: inc/config.class.php:124 68 | msgid "Display actual time in closed task box ('Processing ticket' list)" 69 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 70 | 71 | #: inc/config.class.php:130 72 | msgid "Automatically open task with timer running" 73 | msgstr "Automatically open task with timer running" 74 | 75 | #: inc/config.class.php:136 76 | msgid "Automatically update the duration" 77 | msgstr "Automatically update the duration" 78 | 79 | #: inc/config.class.php:142 80 | msgid "Enable Timer Only on Scheduled Task Day" 81 | msgstr "Enable Timer Only on Scheduled Task Day" 82 | 83 | #: inc/config.class.php:148 84 | msgid "Enable Timer Only on Task's Start Day" 85 | msgstr "Enable Timer Only on Task's Start Day" 86 | 87 | #: inc/dashboard.class.php:48 88 | msgid "Top 20 Actualtime tasks per day" 89 | msgstr "Top 20 Actualtime tasks per day" 90 | 91 | #: inc/dashboard.class.php:56 92 | msgid "Bottom 20 Actualtime tasks per day" 93 | msgstr "Bottom 20 Actualtime tasks per day" 94 | 95 | #: inc/dashboard.class.php:64 96 | msgid "Top 20 Actualtime usage (hours)" 97 | msgstr "Top 20 Actualtime usage (hours)" 98 | 99 | #: inc/dashboard.class.php:72 100 | msgid "Bottom 20 Actualtime usage (hours)" 101 | msgstr "Bottom 20 Actualtime usage (hours)" 102 | 103 | #: inc/dashboard.class.php:79 104 | msgid "Top 20 % Actualtime usage per day" 105 | msgstr "Top 20 % Actualtime usage per day" 106 | 107 | #: inc/dashboard.class.php:87 108 | msgid "Bottom 20 % Actualtime usage per day" 109 | msgstr "Bottom 20 % Actualtime usage per day" 110 | 111 | #: inc/profile.class.php:103 112 | msgid "General" 113 | msgstr "General" 114 | 115 | #: inc/profile.class.php:138 inc/running.class.php:71 116 | msgid "Running timers" 117 | msgstr "Running timers" 118 | 119 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 120 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 121 | msgid "Modify timers" 122 | msgstr "Modify timers" 123 | 124 | #: inc/running.class.php:76 125 | msgid "Update every (s)" 126 | msgstr "Update every (s)" 127 | 128 | #: inc/sourcetimer.class.php:53 129 | msgid "Modify tickets" 130 | msgstr "Modify tickets" 131 | 132 | #: inc/sourcetimer.class.php:54 133 | msgid "Modify changes" 134 | msgstr "Modify changes" 135 | 136 | #: inc/sourcetimer.class.php:55 137 | msgid "Modify projects" 138 | msgstr "Modify projects" 139 | 140 | #: inc/task.class.php:321 inc/task.class.php:482 141 | msgid "Actual Duration" 142 | msgstr "Actual Duration" 143 | 144 | #: inc/task.class.php:332 inc/task.class.php:493 145 | msgid "Partial actual duration" 146 | msgstr "Partial actual duration" 147 | 148 | #: inc/task.class.php:970 149 | msgid "Original end date" 150 | msgstr "Original end date" 151 | 152 | #: inc/task.class.php:971 153 | msgid "Original duration" 154 | msgstr "Original duration" 155 | 156 | #: inc/task.class.php:972 157 | #, php-format 158 | msgid "First modification by %s" 159 | msgstr "First modification by %s" 160 | 161 | #: inc/task.class.php:1362 inc/task.class.php:1368 162 | #, php-format 163 | msgid "You cannot start a timer because the task was scheduled for %d." 164 | msgstr "You cannot start a timer because the task was scheduled for %d." 165 | 166 | #: inc/task.class.php:1392 167 | msgid "You cannot add a timer on a different day." 168 | msgstr "You cannot add a timer on a different day." 169 | 170 | #: inc/task.class.php:1435 171 | msgid "Today is marked as absence you can not initialize the timer" 172 | msgstr "Today is marked as absence you can not initialize the timer" 173 | 174 | #: inc/task.class.php:1441 175 | msgid "Timer has not been initialized" 176 | msgstr "لم يتم تهيئة الوقت " 177 | 178 | #: inc/task.class.php:1458 179 | msgid "You are already doing a waypoint" 180 | msgstr "You are already doing a waypoint" 181 | 182 | #: inc/task.class.php:1495 inc/task.class.php:1500 183 | msgid "Technician not in charge of the task" 184 | msgstr "Technician not in charge of the task" 185 | 186 | #: inc/task.class.php:1506 187 | msgid "A user is already performing the task" 188 | msgstr "A user is already performing the task" 189 | 190 | #: inc/task.class.php:1556 191 | #, php-format 192 | msgid "You are already working on %s" 193 | msgstr "You are already working on %s" 194 | 195 | #: inc/task.class.php:1587 196 | msgid "Timer started" 197 | msgstr "الوقت بدأ" 198 | 199 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 200 | msgid "Timer completed" 201 | msgstr "الوقت إنتهى" 202 | 203 | #: inc/task.class.php:1699 inc/task.class.php:1813 204 | msgid "Only the user who initiated the task can close it" 205 | msgstr "يمكن فقط للمستخدم الذي بدأ المهمة إغلاقها" 206 | 207 | #: inc/task.class.php:1702 208 | msgid "The task had not been initialized" 209 | msgstr "" 210 | -------------------------------------------------------------------------------- /locales/hi_IN.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: hi_IN\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=2; plural=(n==0 || n==1) ? 0 : 1;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Duration Diff" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%dd" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%dh" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%dmin" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%ds" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Timer started on" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime Setup" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "In Standard interface only (default)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Both in Standard and Helpdesk interfaces" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Enable timer on tasks" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Display pop-up window with current running timer" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 69 | 70 | #: inc/config.class.php:130 71 | msgid "Automatically open task with timer running" 72 | msgstr "Automatically open task with timer running" 73 | 74 | #: inc/config.class.php:136 75 | msgid "Automatically update the duration" 76 | msgstr "Automatically update the duration" 77 | 78 | #: inc/config.class.php:142 79 | msgid "Enable Timer Only on Scheduled Task Day" 80 | msgstr "Enable Timer Only on Scheduled Task Day" 81 | 82 | #: inc/config.class.php:148 83 | msgid "Enable Timer Only on Task's Start Day" 84 | msgstr "Enable Timer Only on Task's Start Day" 85 | 86 | #: inc/dashboard.class.php:48 87 | msgid "Top 20 Actualtime tasks per day" 88 | msgstr "Top 20 Actualtime tasks per day" 89 | 90 | #: inc/dashboard.class.php:56 91 | msgid "Bottom 20 Actualtime tasks per day" 92 | msgstr "Bottom 20 Actualtime tasks per day" 93 | 94 | #: inc/dashboard.class.php:64 95 | msgid "Top 20 Actualtime usage (hours)" 96 | msgstr "Top 20 Actualtime usage (hours)" 97 | 98 | #: inc/dashboard.class.php:72 99 | msgid "Bottom 20 Actualtime usage (hours)" 100 | msgstr "Bottom 20 Actualtime usage (hours)" 101 | 102 | #: inc/dashboard.class.php:79 103 | msgid "Top 20 % Actualtime usage per day" 104 | msgstr "Top 20 % Actualtime usage per day" 105 | 106 | #: inc/dashboard.class.php:87 107 | msgid "Bottom 20 % Actualtime usage per day" 108 | msgstr "Bottom 20 % Actualtime usage per day" 109 | 110 | #: inc/profile.class.php:103 111 | msgid "General" 112 | msgstr "General" 113 | 114 | #: inc/profile.class.php:138 inc/running.class.php:71 115 | msgid "Running timers" 116 | msgstr "Running timers" 117 | 118 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 119 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 120 | msgid "Modify timers" 121 | msgstr "Modify timers" 122 | 123 | #: inc/running.class.php:76 124 | msgid "Update every (s)" 125 | msgstr "Update every (s)" 126 | 127 | #: inc/sourcetimer.class.php:53 128 | msgid "Modify tickets" 129 | msgstr "Modify tickets" 130 | 131 | #: inc/sourcetimer.class.php:54 132 | msgid "Modify changes" 133 | msgstr "Modify changes" 134 | 135 | #: inc/sourcetimer.class.php:55 136 | msgid "Modify projects" 137 | msgstr "Modify projects" 138 | 139 | #: inc/task.class.php:321 inc/task.class.php:482 140 | msgid "Actual Duration" 141 | msgstr "Actual Duration" 142 | 143 | #: inc/task.class.php:332 inc/task.class.php:493 144 | msgid "Partial actual duration" 145 | msgstr "Partial actual duration" 146 | 147 | #: inc/task.class.php:970 148 | msgid "Original end date" 149 | msgstr "Original end date" 150 | 151 | #: inc/task.class.php:971 152 | msgid "Original duration" 153 | msgstr "Original duration" 154 | 155 | #: inc/task.class.php:972 156 | #, php-format 157 | msgid "First modification by %s" 158 | msgstr "First modification by %s" 159 | 160 | #: inc/task.class.php:1362 inc/task.class.php:1368 161 | #, php-format 162 | msgid "You cannot start a timer because the task was scheduled for %d." 163 | msgstr "You cannot start a timer because the task was scheduled for %d." 164 | 165 | #: inc/task.class.php:1392 166 | msgid "You cannot add a timer on a different day." 167 | msgstr "You cannot add a timer on a different day." 168 | 169 | #: inc/task.class.php:1435 170 | msgid "Today is marked as absence you can not initialize the timer" 171 | msgstr "आज को अनुपस्थिति के रूप में चिह्नित किया गया है, आप टाइमर प्रारंभ नहीं कर सकते" 172 | 173 | #: inc/task.class.php:1441 174 | msgid "Timer has not been initialized" 175 | msgstr "टाइमर प्रारंभ नहीं किया गया है" 176 | 177 | #: inc/task.class.php:1458 178 | msgid "You are already doing a waypoint" 179 | msgstr "You are already doing a waypoint" 180 | 181 | #: inc/task.class.php:1495 inc/task.class.php:1500 182 | msgid "Technician not in charge of the task" 183 | msgstr "Technician not in charge of the task" 184 | 185 | #: inc/task.class.php:1506 186 | msgid "A user is already performing the task" 187 | msgstr "एक उपयोगकर्ता पहले से ही कार्य निष्पादित कर रहा है" 188 | 189 | #: inc/task.class.php:1556 190 | #, php-format 191 | msgid "You are already working on %s" 192 | msgstr "You are already working on %s" 193 | 194 | #: inc/task.class.php:1587 195 | msgid "Timer started" 196 | msgstr "Timer started" 197 | 198 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 199 | msgid "Timer completed" 200 | msgstr "Timer completed" 201 | 202 | #: inc/task.class.php:1699 inc/task.class.php:1813 203 | msgid "Only the user who initiated the task can close it" 204 | msgstr "Only the user who initiated the task can close it" 205 | 206 | #: inc/task.class.php:1702 207 | msgid "The task had not been initialized" 208 | msgstr "The task had not been initialized" 209 | -------------------------------------------------------------------------------- /locales/pl_PL.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: pl_PL\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : ((n%10>=2 && n%10<=4) && " 12 | "((n%100<12 || n%100>14))) ? 1 : 2;\n" 13 | 14 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 15 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 16 | msgid "Duration Diff" 17 | msgstr "Duration Diff" 18 | 19 | #. TRANS: d is a symbol for days in a time (displays: 3d) 20 | #: ajax/timer.php:70 21 | #, php-format 22 | msgid "%dd" 23 | msgstr "%dd" 24 | 25 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 26 | #: ajax/timer.php:74 27 | #, php-format 28 | msgid "%dh" 29 | msgstr "%dh" 30 | 31 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 32 | #: ajax/timer.php:78 33 | #, php-format 34 | msgid "%dmin" 35 | msgstr "%dmin" 36 | 37 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 38 | #: ajax/timer.php:82 39 | #, php-format 40 | msgid "%ds" 41 | msgstr "%ds" 42 | 43 | #: ajax/timer.php:93 44 | msgid "Timer started on" 45 | msgstr "Timer started on" 46 | 47 | #: inc/config.class.php:65 48 | msgid "ActualTime Setup" 49 | msgstr "ActualTime Setup" 50 | 51 | #: inc/config.class.php:99 52 | msgid "In Standard interface only (default)" 53 | msgstr "In Standard interface only (default)" 54 | 55 | #: inc/config.class.php:100 56 | msgid "Both in Standard and Helpdesk interfaces" 57 | msgstr "Both in Standard and Helpdesk interfaces" 58 | 59 | #: inc/config.class.php:106 60 | msgid "Enable timer on tasks" 61 | msgstr "Enable timer on tasks" 62 | 63 | #: inc/config.class.php:118 64 | msgid "Display pop-up window with current running timer" 65 | msgstr "Display pop-up window with current running timer" 66 | 67 | #: inc/config.class.php:124 68 | msgid "Display actual time in closed task box ('Processing ticket' list)" 69 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 70 | 71 | #: inc/config.class.php:130 72 | msgid "Automatically open task with timer running" 73 | msgstr "Automatically open task with timer running" 74 | 75 | #: inc/config.class.php:136 76 | msgid "Automatically update the duration" 77 | msgstr "Automatically update the duration" 78 | 79 | #: inc/config.class.php:142 80 | msgid "Enable Timer Only on Scheduled Task Day" 81 | msgstr "Enable Timer Only on Scheduled Task Day" 82 | 83 | #: inc/config.class.php:148 84 | msgid "Enable Timer Only on Task's Start Day" 85 | msgstr "Enable Timer Only on Task's Start Day" 86 | 87 | #: inc/dashboard.class.php:48 88 | msgid "Top 20 Actualtime tasks per day" 89 | msgstr "Top 20 Actualtime tasks per day" 90 | 91 | #: inc/dashboard.class.php:56 92 | msgid "Bottom 20 Actualtime tasks per day" 93 | msgstr "Bottom 20 Actualtime tasks per day" 94 | 95 | #: inc/dashboard.class.php:64 96 | msgid "Top 20 Actualtime usage (hours)" 97 | msgstr "Top 20 Actualtime usage (hours)" 98 | 99 | #: inc/dashboard.class.php:72 100 | msgid "Bottom 20 Actualtime usage (hours)" 101 | msgstr "Bottom 20 Actualtime usage (hours)" 102 | 103 | #: inc/dashboard.class.php:79 104 | msgid "Top 20 % Actualtime usage per day" 105 | msgstr "Top 20 % Actualtime usage per day" 106 | 107 | #: inc/dashboard.class.php:87 108 | msgid "Bottom 20 % Actualtime usage per day" 109 | msgstr "Bottom 20 % Actualtime usage per day" 110 | 111 | #: inc/profile.class.php:103 112 | msgid "General" 113 | msgstr "General" 114 | 115 | #: inc/profile.class.php:138 inc/running.class.php:71 116 | msgid "Running timers" 117 | msgstr "Running timers" 118 | 119 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 120 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 121 | msgid "Modify timers" 122 | msgstr "Modify timers" 123 | 124 | #: inc/running.class.php:76 125 | msgid "Update every (s)" 126 | msgstr "Update every (s)" 127 | 128 | #: inc/sourcetimer.class.php:53 129 | msgid "Modify tickets" 130 | msgstr "Modify tickets" 131 | 132 | #: inc/sourcetimer.class.php:54 133 | msgid "Modify changes" 134 | msgstr "Modify changes" 135 | 136 | #: inc/sourcetimer.class.php:55 137 | msgid "Modify projects" 138 | msgstr "Modify projects" 139 | 140 | #: inc/task.class.php:321 inc/task.class.php:482 141 | msgid "Actual Duration" 142 | msgstr "Actual Duration" 143 | 144 | #: inc/task.class.php:332 inc/task.class.php:493 145 | msgid "Partial actual duration" 146 | msgstr "Partial actual duration" 147 | 148 | #: inc/task.class.php:970 149 | msgid "Original end date" 150 | msgstr "Original end date" 151 | 152 | #: inc/task.class.php:971 153 | msgid "Original duration" 154 | msgstr "Original duration" 155 | 156 | #: inc/task.class.php:972 157 | #, php-format 158 | msgid "First modification by %s" 159 | msgstr "First modification by %s" 160 | 161 | #: inc/task.class.php:1362 inc/task.class.php:1368 162 | #, php-format 163 | msgid "You cannot start a timer because the task was scheduled for %d." 164 | msgstr "You cannot start a timer because the task was scheduled for %d." 165 | 166 | #: inc/task.class.php:1392 167 | msgid "You cannot add a timer on a different day." 168 | msgstr "You cannot add a timer on a different day." 169 | 170 | #: inc/task.class.php:1435 171 | msgid "Today is marked as absence you can not initialize the timer" 172 | msgstr "Today is marked as absence you can not initialize the timer" 173 | 174 | #: inc/task.class.php:1441 175 | msgid "Timer has not been initialized" 176 | msgstr "Timer has not been initialized" 177 | 178 | #: inc/task.class.php:1458 179 | msgid "You are already doing a waypoint" 180 | msgstr "You are already doing a waypoint" 181 | 182 | #: inc/task.class.php:1495 inc/task.class.php:1500 183 | msgid "Technician not in charge of the task" 184 | msgstr "Technician not in charge of the task" 185 | 186 | #: inc/task.class.php:1506 187 | msgid "A user is already performing the task" 188 | msgstr "A user is already performing the task" 189 | 190 | #: inc/task.class.php:1556 191 | #, php-format 192 | msgid "You are already working on %s" 193 | msgstr "You are already working on %s" 194 | 195 | #: inc/task.class.php:1587 196 | msgid "Timer started" 197 | msgstr "Timer started" 198 | 199 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 200 | msgid "Timer completed" 201 | msgstr "Timer completed" 202 | 203 | #: inc/task.class.php:1699 inc/task.class.php:1813 204 | msgid "Only the user who initiated the task can close it" 205 | msgstr "Only the user who initiated the task can close it" 206 | 207 | #: inc/task.class.php:1702 208 | msgid "The task had not been initialized" 209 | msgstr "The task had not been initialized" 210 | -------------------------------------------------------------------------------- /locales/ar_DZ.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: ar_DZ\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=6; plural=(n==0) ? 0 : (n==1) ? 1 : (n==2) ? 2 : " 12 | "(n%100>=3 && n%100<=10) ? 3 : (n%100>=11 && n%100<=99) ? 4 : 5;\n" 13 | 14 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 15 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 16 | msgid "Duration Diff" 17 | msgstr "Duration Diff" 18 | 19 | #. TRANS: d is a symbol for days in a time (displays: 3d) 20 | #: ajax/timer.php:70 21 | #, php-format 22 | msgid "%dd" 23 | msgstr "%dd" 24 | 25 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 26 | #: ajax/timer.php:74 27 | #, php-format 28 | msgid "%dh" 29 | msgstr "%dh" 30 | 31 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 32 | #: ajax/timer.php:78 33 | #, php-format 34 | msgid "%dmin" 35 | msgstr "%dmin" 36 | 37 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 38 | #: ajax/timer.php:82 39 | #, php-format 40 | msgid "%ds" 41 | msgstr "%ds" 42 | 43 | #: ajax/timer.php:93 44 | msgid "Timer started on" 45 | msgstr "Timer started on" 46 | 47 | #: inc/config.class.php:65 48 | msgid "ActualTime Setup" 49 | msgstr "ActualTime Setup" 50 | 51 | #: inc/config.class.php:99 52 | msgid "In Standard interface only (default)" 53 | msgstr "In Standard interface only (default)" 54 | 55 | #: inc/config.class.php:100 56 | msgid "Both in Standard and Helpdesk interfaces" 57 | msgstr "Both in Standard and Helpdesk interfaces" 58 | 59 | #: inc/config.class.php:106 60 | msgid "Enable timer on tasks" 61 | msgstr "Enable timer on tasks" 62 | 63 | #: inc/config.class.php:118 64 | msgid "Display pop-up window with current running timer" 65 | msgstr "Display pop-up window with current running timer" 66 | 67 | #: inc/config.class.php:124 68 | msgid "Display actual time in closed task box ('Processing ticket' list)" 69 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 70 | 71 | #: inc/config.class.php:130 72 | msgid "Automatically open task with timer running" 73 | msgstr "Automatically open task with timer running" 74 | 75 | #: inc/config.class.php:136 76 | msgid "Automatically update the duration" 77 | msgstr "Automatically update the duration" 78 | 79 | #: inc/config.class.php:142 80 | msgid "Enable Timer Only on Scheduled Task Day" 81 | msgstr "Enable Timer Only on Scheduled Task Day" 82 | 83 | #: inc/config.class.php:148 84 | msgid "Enable Timer Only on Task's Start Day" 85 | msgstr "Enable Timer Only on Task's Start Day" 86 | 87 | #: inc/dashboard.class.php:48 88 | msgid "Top 20 Actualtime tasks per day" 89 | msgstr "Top 20 Actualtime tasks per day" 90 | 91 | #: inc/dashboard.class.php:56 92 | msgid "Bottom 20 Actualtime tasks per day" 93 | msgstr "Bottom 20 Actualtime tasks per day" 94 | 95 | #: inc/dashboard.class.php:64 96 | msgid "Top 20 Actualtime usage (hours)" 97 | msgstr "Top 20 Actualtime usage (hours)" 98 | 99 | #: inc/dashboard.class.php:72 100 | msgid "Bottom 20 Actualtime usage (hours)" 101 | msgstr "Bottom 20 Actualtime usage (hours)" 102 | 103 | #: inc/dashboard.class.php:79 104 | msgid "Top 20 % Actualtime usage per day" 105 | msgstr "Top 20 % Actualtime usage per day" 106 | 107 | #: inc/dashboard.class.php:87 108 | msgid "Bottom 20 % Actualtime usage per day" 109 | msgstr "Bottom 20 % Actualtime usage per day" 110 | 111 | #: inc/profile.class.php:103 112 | msgid "General" 113 | msgstr "General" 114 | 115 | #: inc/profile.class.php:138 inc/running.class.php:71 116 | msgid "Running timers" 117 | msgstr "Running timers" 118 | 119 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 120 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 121 | msgid "Modify timers" 122 | msgstr "Modify timers" 123 | 124 | #: inc/running.class.php:76 125 | msgid "Update every (s)" 126 | msgstr "Update every (s)" 127 | 128 | #: inc/sourcetimer.class.php:53 129 | msgid "Modify tickets" 130 | msgstr "Modify tickets" 131 | 132 | #: inc/sourcetimer.class.php:54 133 | msgid "Modify changes" 134 | msgstr "Modify changes" 135 | 136 | #: inc/sourcetimer.class.php:55 137 | msgid "Modify projects" 138 | msgstr "Modify projects" 139 | 140 | #: inc/task.class.php:321 inc/task.class.php:482 141 | msgid "Actual Duration" 142 | msgstr "Actual Duration" 143 | 144 | #: inc/task.class.php:332 inc/task.class.php:493 145 | msgid "Partial actual duration" 146 | msgstr "Partial actual duration" 147 | 148 | #: inc/task.class.php:970 149 | msgid "Original end date" 150 | msgstr "Original end date" 151 | 152 | #: inc/task.class.php:971 153 | msgid "Original duration" 154 | msgstr "Original duration" 155 | 156 | #: inc/task.class.php:972 157 | #, php-format 158 | msgid "First modification by %s" 159 | msgstr "First modification by %s" 160 | 161 | #: inc/task.class.php:1362 inc/task.class.php:1368 162 | #, php-format 163 | msgid "You cannot start a timer because the task was scheduled for %d." 164 | msgstr "You cannot start a timer because the task was scheduled for %d." 165 | 166 | #: inc/task.class.php:1392 167 | msgid "You cannot add a timer on a different day." 168 | msgstr "You cannot add a timer on a different day." 169 | 170 | #: inc/task.class.php:1435 171 | msgid "Today is marked as absence you can not initialize the timer" 172 | msgstr "تم وضع علامة اليوم على أنها غياب لا يمكنك تهيئة المؤقت" 173 | 174 | #: inc/task.class.php:1441 175 | msgid "Timer has not been initialized" 176 | msgstr "لم يتم تهيئة المؤقت" 177 | 178 | #: inc/task.class.php:1458 179 | msgid "You are already doing a waypoint" 180 | msgstr "You are already doing a waypoint" 181 | 182 | #: inc/task.class.php:1495 inc/task.class.php:1500 183 | msgid "Technician not in charge of the task" 184 | msgstr "Technician not in charge of the task" 185 | 186 | #: inc/task.class.php:1506 187 | msgid "A user is already performing the task" 188 | msgstr "A user is already performing the task" 189 | 190 | #: inc/task.class.php:1556 191 | #, php-format 192 | msgid "You are already working on %s" 193 | msgstr "You are already working on %s" 194 | 195 | #: inc/task.class.php:1587 196 | msgid "Timer started" 197 | msgstr "بدأ الموقت" 198 | 199 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 200 | msgid "Timer completed" 201 | msgstr "Timer completed" 202 | 203 | #: inc/task.class.php:1699 inc/task.class.php:1813 204 | msgid "Only the user who initiated the task can close it" 205 | msgstr "Only the user who initiated the task can close it" 206 | 207 | #: inc/task.class.php:1702 208 | msgid "The task had not been initialized" 209 | msgstr "The task had not been initialized" 210 | -------------------------------------------------------------------------------- /locales/sr_RS.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: sr_RS@Cyrl\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=3; plural=((n%10==1) && (n%100!=11)) ? 0 : ((n%10>=2 " 12 | "&& n%10<=4) && ((n%100<12 || n%100>14))) ? 1 : 2;\n" 13 | 14 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 15 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 16 | msgid "Duration Diff" 17 | msgstr "Duration Diff" 18 | 19 | #. TRANS: d is a symbol for days in a time (displays: 3d) 20 | #: ajax/timer.php:70 21 | #, php-format 22 | msgid "%dd" 23 | msgstr "%dd" 24 | 25 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 26 | #: ajax/timer.php:74 27 | #, php-format 28 | msgid "%dh" 29 | msgstr "%dh" 30 | 31 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 32 | #: ajax/timer.php:78 33 | #, php-format 34 | msgid "%dmin" 35 | msgstr "%dmin" 36 | 37 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 38 | #: ajax/timer.php:82 39 | #, php-format 40 | msgid "%ds" 41 | msgstr "%ds" 42 | 43 | #: ajax/timer.php:93 44 | msgid "Timer started on" 45 | msgstr "Тајмер је покренут" 46 | 47 | #: inc/config.class.php:65 48 | msgid "ActualTime Setup" 49 | msgstr "ActualTime Setup" 50 | 51 | #: inc/config.class.php:99 52 | msgid "In Standard interface only (default)" 53 | msgstr "In Standard interface only (default)" 54 | 55 | #: inc/config.class.php:100 56 | msgid "Both in Standard and Helpdesk interfaces" 57 | msgstr "Both in Standard and Helpdesk interfaces" 58 | 59 | #: inc/config.class.php:106 60 | msgid "Enable timer on tasks" 61 | msgstr "Enable timer on tasks" 62 | 63 | #: inc/config.class.php:118 64 | msgid "Display pop-up window with current running timer" 65 | msgstr "Display pop-up window with current running timer" 66 | 67 | #: inc/config.class.php:124 68 | msgid "Display actual time in closed task box ('Processing ticket' list)" 69 | msgstr "Display actual time in closed task box ('Processing ticket' list)" 70 | 71 | #: inc/config.class.php:130 72 | msgid "Automatically open task with timer running" 73 | msgstr "Automatically open task with timer running" 74 | 75 | #: inc/config.class.php:136 76 | msgid "Automatically update the duration" 77 | msgstr "Automatically update the duration" 78 | 79 | #: inc/config.class.php:142 80 | msgid "Enable Timer Only on Scheduled Task Day" 81 | msgstr "Enable Timer Only on Scheduled Task Day" 82 | 83 | #: inc/config.class.php:148 84 | msgid "Enable Timer Only on Task's Start Day" 85 | msgstr "Enable Timer Only on Task's Start Day" 86 | 87 | #: inc/dashboard.class.php:48 88 | msgid "Top 20 Actualtime tasks per day" 89 | msgstr "Top 20 Actualtime tasks per day" 90 | 91 | #: inc/dashboard.class.php:56 92 | msgid "Bottom 20 Actualtime tasks per day" 93 | msgstr "Bottom 20 Actualtime tasks per day" 94 | 95 | #: inc/dashboard.class.php:64 96 | msgid "Top 20 Actualtime usage (hours)" 97 | msgstr "Top 20 Actualtime usage (hours)" 98 | 99 | #: inc/dashboard.class.php:72 100 | msgid "Bottom 20 Actualtime usage (hours)" 101 | msgstr "Bottom 20 Actualtime usage (hours)" 102 | 103 | #: inc/dashboard.class.php:79 104 | msgid "Top 20 % Actualtime usage per day" 105 | msgstr "Top 20 % Actualtime usage per day" 106 | 107 | #: inc/dashboard.class.php:87 108 | msgid "Bottom 20 % Actualtime usage per day" 109 | msgstr "Bottom 20 % Actualtime usage per day" 110 | 111 | #: inc/profile.class.php:103 112 | msgid "General" 113 | msgstr "General" 114 | 115 | #: inc/profile.class.php:138 inc/running.class.php:71 116 | msgid "Running timers" 117 | msgstr "Running timers" 118 | 119 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 120 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 121 | msgid "Modify timers" 122 | msgstr "Modify timers" 123 | 124 | #: inc/running.class.php:76 125 | msgid "Update every (s)" 126 | msgstr "Update every (s)" 127 | 128 | #: inc/sourcetimer.class.php:53 129 | msgid "Modify tickets" 130 | msgstr "Modify tickets" 131 | 132 | #: inc/sourcetimer.class.php:54 133 | msgid "Modify changes" 134 | msgstr "Modify changes" 135 | 136 | #: inc/sourcetimer.class.php:55 137 | msgid "Modify projects" 138 | msgstr "Modify projects" 139 | 140 | #: inc/task.class.php:321 inc/task.class.php:482 141 | msgid "Actual Duration" 142 | msgstr "Actual Duration" 143 | 144 | #: inc/task.class.php:332 inc/task.class.php:493 145 | msgid "Partial actual duration" 146 | msgstr "Partial actual duration" 147 | 148 | #: inc/task.class.php:970 149 | msgid "Original end date" 150 | msgstr "Original end date" 151 | 152 | #: inc/task.class.php:971 153 | msgid "Original duration" 154 | msgstr "Original duration" 155 | 156 | #: inc/task.class.php:972 157 | #, php-format 158 | msgid "First modification by %s" 159 | msgstr "First modification by %s" 160 | 161 | #: inc/task.class.php:1362 inc/task.class.php:1368 162 | #, php-format 163 | msgid "You cannot start a timer because the task was scheduled for %d." 164 | msgstr "You cannot start a timer because the task was scheduled for %d." 165 | 166 | #: inc/task.class.php:1392 167 | msgid "You cannot add a timer on a different day." 168 | msgstr "You cannot add a timer on a different day." 169 | 170 | #: inc/task.class.php:1435 171 | msgid "Today is marked as absence you can not initialize the timer" 172 | msgstr "Today is marked as absence you can not initialize the timer" 173 | 174 | #: inc/task.class.php:1441 175 | msgid "Timer has not been initialized" 176 | msgstr "Тајмер није иницијализован" 177 | 178 | #: inc/task.class.php:1458 179 | msgid "You are already doing a waypoint" 180 | msgstr "You are already doing a waypoint" 181 | 182 | #: inc/task.class.php:1495 inc/task.class.php:1500 183 | msgid "Technician not in charge of the task" 184 | msgstr "Technician not in charge of the task" 185 | 186 | #: inc/task.class.php:1506 187 | msgid "A user is already performing the task" 188 | msgstr "Корисник већ обавља задатак" 189 | 190 | #: inc/task.class.php:1556 191 | #, php-format 192 | msgid "You are already working on %s" 193 | msgstr "You are already working on %s" 194 | 195 | #: inc/task.class.php:1587 196 | msgid "Timer started" 197 | msgstr "Tajmer je počeo" 198 | 199 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 200 | msgid "Timer completed" 201 | msgstr "Тајмер је завршен" 202 | 203 | #: inc/task.class.php:1699 inc/task.class.php:1813 204 | msgid "Only the user who initiated the task can close it" 205 | msgstr "Само корисник који је покренуо задатак може да га затвори" 206 | 207 | #: inc/task.class.php:1702 208 | msgid "The task had not been initialized" 209 | msgstr "Задатак није био иницијализован" 210 | -------------------------------------------------------------------------------- /locales/vi_VN.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: vi_VN\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=1; plural=0;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Khoảng thời gian chênh lệch" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%d ngày" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%d giờ" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%d phút" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%d giây" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Bắt đầu tính giờ cho" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime Setup" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "Chỉ trong giao diện chuẩn (mặc định)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Cả giao diện chuẩn và giao diện hỗ trợ" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Bật tính giờ cho công việc" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Hiện popup thời gian" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "" 69 | "Hiển thị thời gian thực tế trong hộp nhiệm vụ đã đóng (danh sách 'Xử lý " 70 | "phiếu”)" 71 | 72 | #: inc/config.class.php:130 73 | msgid "Automatically open task with timer running" 74 | msgstr "Tự động mở công việc với thời gian đang chạy" 75 | 76 | #: inc/config.class.php:136 77 | msgid "Automatically update the duration" 78 | msgstr "Tự động cạp nhật khoảng thời gian" 79 | 80 | #: inc/config.class.php:142 81 | msgid "Enable Timer Only on Scheduled Task Day" 82 | msgstr "Enable Timer Only on Scheduled Task Day" 83 | 84 | #: inc/config.class.php:148 85 | msgid "Enable Timer Only on Task's Start Day" 86 | msgstr "Enable Timer Only on Task's Start Day" 87 | 88 | #: inc/dashboard.class.php:48 89 | msgid "Top 20 Actualtime tasks per day" 90 | msgstr "20 nhiệm vụ thực tế hàng đầu mỗi ngày" 91 | 92 | #: inc/dashboard.class.php:56 93 | msgid "Bottom 20 Actualtime tasks per day" 94 | msgstr "20 nhiệm vụ thực tế dưới cùng mỗi ngày" 95 | 96 | #: inc/dashboard.class.php:64 97 | msgid "Top 20 Actualtime usage (hours)" 98 | msgstr "Top 20 Thời gian sử dụng thực tế (giờ)" 99 | 100 | #: inc/dashboard.class.php:72 101 | msgid "Bottom 20 Actualtime usage (hours)" 102 | msgstr "Dưới 20 Thời gian sử dụng thực tế (giờ)" 103 | 104 | #: inc/dashboard.class.php:79 105 | msgid "Top 20 % Actualtime usage per day" 106 | msgstr "20% mức sử dụng thời gian thực tế hàng đầu mỗi ngày" 107 | 108 | #: inc/dashboard.class.php:87 109 | msgid "Bottom 20 % Actualtime usage per day" 110 | msgstr "Dưới 20 % Thời gian sử dụng thực tế mỗi ngày" 111 | 112 | #: inc/profile.class.php:103 113 | msgid "General" 114 | msgstr "General" 115 | 116 | #: inc/profile.class.php:138 inc/running.class.php:71 117 | msgid "Running timers" 118 | msgstr "Đang chạy bộ hẹn giờ" 119 | 120 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 121 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 122 | msgid "Modify timers" 123 | msgstr "Modify timers" 124 | 125 | #: inc/running.class.php:76 126 | msgid "Update every (s)" 127 | msgstr "Cập nhật từng (giây)" 128 | 129 | #: inc/sourcetimer.class.php:53 130 | msgid "Modify tickets" 131 | msgstr "Modify tickets" 132 | 133 | #: inc/sourcetimer.class.php:54 134 | msgid "Modify changes" 135 | msgstr "Modify changes" 136 | 137 | #: inc/sourcetimer.class.php:55 138 | msgid "Modify projects" 139 | msgstr "Modify projects" 140 | 141 | #: inc/task.class.php:321 inc/task.class.php:482 142 | msgid "Actual Duration" 143 | msgstr "Thời lượng thực tế" 144 | 145 | #: inc/task.class.php:332 inc/task.class.php:493 146 | msgid "Partial actual duration" 147 | msgstr "Một phần thời lượng thực tế" 148 | 149 | #: inc/task.class.php:970 150 | msgid "Original end date" 151 | msgstr "Original end date" 152 | 153 | #: inc/task.class.php:971 154 | msgid "Original duration" 155 | msgstr "Original duration" 156 | 157 | #: inc/task.class.php:972 158 | #, php-format 159 | msgid "First modification by %s" 160 | msgstr "First modification by %s" 161 | 162 | #: inc/task.class.php:1362 inc/task.class.php:1368 163 | #, php-format 164 | msgid "You cannot start a timer because the task was scheduled for %d." 165 | msgstr "You cannot start a timer because the task was scheduled for %d." 166 | 167 | #: inc/task.class.php:1392 168 | msgid "You cannot add a timer on a different day." 169 | msgstr "You cannot add a timer on a different day." 170 | 171 | #: inc/task.class.php:1435 172 | msgid "Today is marked as absence you can not initialize the timer" 173 | msgstr "" 174 | "Hôm nay được đánh dấu là vắng mặt, bạn không thể khởi tạo bộ đếm thời gian" 175 | 176 | #: inc/task.class.php:1441 177 | msgid "Timer has not been initialized" 178 | msgstr "Chưa khởi tạo thời gian" 179 | 180 | #: inc/task.class.php:1458 181 | msgid "You are already doing a waypoint" 182 | msgstr "Bạn đã làm một điểm tham chiếu" 183 | 184 | #: inc/task.class.php:1495 inc/task.class.php:1500 185 | msgid "Technician not in charge of the task" 186 | msgstr "Kỹ thuật viên không phụ trách nhiệm vụ" 187 | 188 | #: inc/task.class.php:1506 189 | msgid "A user is already performing the task" 190 | msgstr "Người dùng đã thực hiện việc này" 191 | 192 | #: inc/task.class.php:1556 193 | #, php-format 194 | msgid "You are already working on %s" 195 | msgstr "You are already working on %s" 196 | 197 | #: inc/task.class.php:1587 198 | msgid "Timer started" 199 | msgstr "Bắt đầu đếm giờ" 200 | 201 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 202 | msgid "Timer completed" 203 | msgstr "Thời gian hoàn thành" 204 | 205 | #: inc/task.class.php:1699 inc/task.class.php:1813 206 | msgid "Only the user who initiated the task can close it" 207 | msgstr "Chỉ ai bắt đầu việc này mới có thể kết thúc nó" 208 | 209 | #: inc/task.class.php:1702 210 | msgid "The task had not been initialized" 211 | msgstr "Chưa khởi tạo công việc" 212 | -------------------------------------------------------------------------------- /locales/es_AR.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: es_AR\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=2; plural=(n==1) ? 0 : 1;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Desviación" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%dd" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%dh" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%dmin" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%ds" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Temporizador iniciado a las" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime Setup" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "Sólo en la interfaz estándar (por defecto)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Tanto en interfaces estándar como en interfaces de Helpdesk" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Habilite el temporizador en las tareas" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Mostrar pop-up con temporizador actual" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "Mostrar el tiempo real en la tarea cerrada (\"Tramitando petición\")" 69 | 70 | #: inc/config.class.php:130 71 | msgid "Automatically open task with timer running" 72 | msgstr "Abrir automáticamente la tarea con el temporizador en ejecución" 73 | 74 | #: inc/config.class.php:136 75 | msgid "Automatically update the duration" 76 | msgstr "Actualizar automáticamente la duración" 77 | 78 | #: inc/config.class.php:142 79 | msgid "Enable Timer Only on Scheduled Task Day" 80 | msgstr "Enable Timer Only on Scheduled Task Day" 81 | 82 | #: inc/config.class.php:148 83 | msgid "Enable Timer Only on Task's Start Day" 84 | msgstr "Enable Timer Only on Task's Start Day" 85 | 86 | #: inc/dashboard.class.php:48 87 | msgid "Top 20 Actualtime tasks per day" 88 | msgstr "Top 20 Actualtime tasks per day" 89 | 90 | #: inc/dashboard.class.php:56 91 | msgid "Bottom 20 Actualtime tasks per day" 92 | msgstr "Bottom 20 Actualtime tasks per day" 93 | 94 | #: inc/dashboard.class.php:64 95 | msgid "Top 20 Actualtime usage (hours)" 96 | msgstr "Top 20 Actualtime usage (hours)" 97 | 98 | #: inc/dashboard.class.php:72 99 | msgid "Bottom 20 Actualtime usage (hours)" 100 | msgstr "Bottom 20 Actualtime usage (hours)" 101 | 102 | #: inc/dashboard.class.php:79 103 | msgid "Top 20 % Actualtime usage per day" 104 | msgstr "Top 20 % Actualtime usage per day" 105 | 106 | #: inc/dashboard.class.php:87 107 | msgid "Bottom 20 % Actualtime usage per day" 108 | msgstr "Bottom 20 % Actualtime usage per day" 109 | 110 | #: inc/profile.class.php:103 111 | msgid "General" 112 | msgstr "General" 113 | 114 | #: inc/profile.class.php:138 inc/running.class.php:71 115 | msgid "Running timers" 116 | msgstr "Temporizadores funcionando" 117 | 118 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 119 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 120 | msgid "Modify timers" 121 | msgstr "Modify timers" 122 | 123 | #: inc/running.class.php:76 124 | msgid "Update every (s)" 125 | msgstr "Actualizar cada (s)" 126 | 127 | #: inc/sourcetimer.class.php:53 128 | msgid "Modify tickets" 129 | msgstr "Modify tickets" 130 | 131 | #: inc/sourcetimer.class.php:54 132 | msgid "Modify changes" 133 | msgstr "Modify changes" 134 | 135 | #: inc/sourcetimer.class.php:55 136 | msgid "Modify projects" 137 | msgstr "Modify projects" 138 | 139 | #: inc/task.class.php:321 inc/task.class.php:482 140 | msgid "Actual Duration" 141 | msgstr "Duración real" 142 | 143 | #: inc/task.class.php:332 inc/task.class.php:493 144 | msgid "Partial actual duration" 145 | msgstr "Duración real parcial" 146 | 147 | #: inc/task.class.php:970 148 | msgid "Original end date" 149 | msgstr "Original end date" 150 | 151 | #: inc/task.class.php:971 152 | msgid "Original duration" 153 | msgstr "Original duration" 154 | 155 | #: inc/task.class.php:972 156 | #, php-format 157 | msgid "First modification by %s" 158 | msgstr "First modification by %s" 159 | 160 | #: inc/task.class.php:1362 inc/task.class.php:1368 161 | #, php-format 162 | msgid "You cannot start a timer because the task was scheduled for %d." 163 | msgstr "You cannot start a timer because the task was scheduled for %d." 164 | 165 | #: inc/task.class.php:1392 166 | msgid "You cannot add a timer on a different day." 167 | msgstr "You cannot add a timer on a different day." 168 | 169 | #: inc/task.class.php:1435 170 | msgid "Today is marked as absence you can not initialize the timer" 171 | msgstr "Hoy esta marcado como ausencia no se puede inicializar el temporizador" 172 | 173 | #: inc/task.class.php:1441 174 | msgid "Timer has not been initialized" 175 | msgstr "El temporizador no se había inicializado" 176 | 177 | #: inc/task.class.php:1458 178 | msgid "You are already doing a waypoint" 179 | msgstr "You are already doing a waypoint" 180 | 181 | #: inc/task.class.php:1495 inc/task.class.php:1500 182 | msgid "Technician not in charge of the task" 183 | msgstr "Technician not in charge of the task" 184 | 185 | #: inc/task.class.php:1506 186 | msgid "A user is already performing the task" 187 | msgstr "Otro usuario ya está realizando la tarea" 188 | 189 | #: inc/task.class.php:1556 190 | #, php-format 191 | msgid "You are already working on %s" 192 | msgstr "You are already working on %s" 193 | 194 | #: inc/task.class.php:1587 195 | msgid "Timer started" 196 | msgstr "Temporizador iniciado" 197 | 198 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 199 | msgid "Timer completed" 200 | msgstr "Temporizador finalizado" 201 | 202 | #: inc/task.class.php:1699 inc/task.class.php:1813 203 | msgid "Only the user who initiated the task can close it" 204 | msgstr "Sólo el usuario que inició la tarea puede cerrarla" 205 | 206 | #: inc/task.class.php:1702 207 | msgid "The task had not been initialized" 208 | msgstr "La tarea no se había inicializado" 209 | -------------------------------------------------------------------------------- /locales/et_EE.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: et_EE\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=2; plural=(n==1) ? 0 : 1;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Kestuste vahe" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%dp" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%dt" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%dmin" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%dsek" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Taimer käivitus" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime'i seadistus" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "Vaid tavaliideses (vaikimisi valik)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Nii tavaliideses kui kasutatoe liideses" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Kasuta tegevustes taimerit" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Näita hüpikakent hetkel tiksuva taimeriga" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "" 69 | "Näita tegelikku aega suletud tegevuse väljal (loendis „Töötluses olevad " 70 | "teated“)" 71 | 72 | #: inc/config.class.php:130 73 | msgid "Automatically open task with timer running" 74 | msgstr "Käivita taimer tegevuse avamisel automaatselt" 75 | 76 | #: inc/config.class.php:136 77 | msgid "Automatically update the duration" 78 | msgstr "Uuenda kestust automaatselt" 79 | 80 | #: inc/config.class.php:142 81 | msgid "Enable Timer Only on Scheduled Task Day" 82 | msgstr "Kasuta taimerit vaid tegevuseks plaanitud päeval" 83 | 84 | #: inc/config.class.php:148 85 | msgid "Enable Timer Only on Task's Start Day" 86 | msgstr "Kasuta taimerit vaid tegevuse alguspäeval" 87 | 88 | #: inc/dashboard.class.php:48 89 | msgid "Top 20 Actualtime tasks per day" 90 | msgstr "Esimesed 20 Actualtime'i tegevust päevas" 91 | 92 | #: inc/dashboard.class.php:56 93 | msgid "Bottom 20 Actualtime tasks per day" 94 | msgstr "Esimesed 20 Actualtime'i tegevust päevas" 95 | 96 | #: inc/dashboard.class.php:64 97 | msgid "Top 20 Actualtime usage (hours)" 98 | msgstr "Esimesed 20 Actualtime'i kasutust (tundides)" 99 | 100 | #: inc/dashboard.class.php:72 101 | msgid "Bottom 20 Actualtime usage (hours)" 102 | msgstr "Viimased 20 Actualtime'i kasutust (tundides)" 103 | 104 | #: inc/dashboard.class.php:79 105 | msgid "Top 20 % Actualtime usage per day" 106 | msgstr "Esimesed 20% Actualtime'i kasutust päevas" 107 | 108 | #: inc/dashboard.class.php:87 109 | msgid "Bottom 20 % Actualtime usage per day" 110 | msgstr "Viimased 20% Actualtime'i kasutust päevas" 111 | 112 | #: inc/profile.class.php:103 113 | msgid "General" 114 | msgstr "Üldist" 115 | 116 | #: inc/profile.class.php:138 inc/running.class.php:71 117 | msgid "Running timers" 118 | msgstr "Hetkel tiksuvad taimerid" 119 | 120 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 121 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 122 | msgid "Modify timers" 123 | msgstr "Modify timers" 124 | 125 | #: inc/running.class.php:76 126 | msgid "Update every (s)" 127 | msgstr "Uuenduse välp (sekundites)" 128 | 129 | #: inc/sourcetimer.class.php:53 130 | msgid "Modify tickets" 131 | msgstr "Modify tickets" 132 | 133 | #: inc/sourcetimer.class.php:54 134 | msgid "Modify changes" 135 | msgstr "Modify changes" 136 | 137 | #: inc/sourcetimer.class.php:55 138 | msgid "Modify projects" 139 | msgstr "Modify projects" 140 | 141 | #: inc/task.class.php:321 inc/task.class.php:482 142 | msgid "Actual Duration" 143 | msgstr "Tegelik kestus" 144 | 145 | #: inc/task.class.php:332 inc/task.class.php:493 146 | msgid "Partial actual duration" 147 | msgstr "Osaline tegelik kestus" 148 | 149 | #: inc/task.class.php:970 150 | msgid "Original end date" 151 | msgstr "Original end date" 152 | 153 | #: inc/task.class.php:971 154 | msgid "Original duration" 155 | msgstr "Original duration" 156 | 157 | #: inc/task.class.php:972 158 | #, php-format 159 | msgid "First modification by %s" 160 | msgstr "First modification by %s" 161 | 162 | #: inc/task.class.php:1362 inc/task.class.php:1368 163 | #, php-format 164 | msgid "You cannot start a timer because the task was scheduled for %d." 165 | msgstr "Sa ei saa käivitada taimerit, sest tegevus on määratud vastutajale %d." 166 | 167 | #: inc/task.class.php:1392 168 | msgid "You cannot add a timer on a different day." 169 | msgstr "Sa ei saa lisada taimerit teiseks päevaks" 170 | 171 | #: inc/task.class.php:1435 172 | msgid "Today is marked as absence you can not initialize the timer" 173 | msgstr "Tänane päev pole märgitud tööpäevaks ja sa ei saa taimerit käivitada" 174 | 175 | #: inc/task.class.php:1441 176 | msgid "Timer has not been initialized" 177 | msgstr "Taimer on initsialiseerimata" 178 | 179 | #: inc/task.class.php:1458 180 | msgid "You are already doing a waypoint" 181 | msgstr "Vahetegevus on sul juba töös" 182 | 183 | #: inc/task.class.php:1495 inc/task.class.php:1500 184 | msgid "Technician not in charge of the task" 185 | msgstr "See tegevus pole antud vastutaja ülesandeks" 186 | 187 | #: inc/task.class.php:1506 188 | msgid "A user is already performing the task" 189 | msgstr "Keegi teine on selle tegevuse juba töösse võtnud" 190 | 191 | #: inc/task.class.php:1556 192 | #, php-format 193 | msgid "You are already working on %s" 194 | msgstr "%s on sul juba töös" 195 | 196 | #: inc/task.class.php:1587 197 | msgid "Timer started" 198 | msgstr "Taimer on käivitatud" 199 | 200 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 201 | msgid "Timer completed" 202 | msgstr "Taimer lõpetas" 203 | 204 | #: inc/task.class.php:1699 inc/task.class.php:1813 205 | msgid "Only the user who initiated the task can close it" 206 | msgstr "Ainult tegevusega alustanud kasutaja saab seda sulgeda" 207 | 208 | #: inc/task.class.php:1702 209 | msgid "The task had not been initialized" 210 | msgstr "Tegevus on initsialiseerimata" 211 | -------------------------------------------------------------------------------- /locales/pt_BR.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: ActualTime\n" 4 | "Report-Msgid-Bugs-To: \n" 5 | "POT-Creation-Date: 2024-11-06 14:55+0100\n" 6 | "Language: pt_BR\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "X-Generator: Localazy (https://localazy.com)\n" 11 | "Plural-Forms: nplurals=2; plural=(n>=0 && n<=1) ? 0 : 1;\n" 12 | 13 | #: hook.php:343 hook.php:362 inc/task.class.php:87 inc/task.class.php:105 14 | #: inc/task.class.php:845 inc/task.class.php:851 inc/task.class.php:857 15 | msgid "Duration Diff" 16 | msgstr "Diferença" 17 | 18 | #. TRANS: d is a symbol for days in a time (displays: 3d) 19 | #: ajax/timer.php:70 20 | #, php-format 21 | msgid "%dd" 22 | msgstr "%dd" 23 | 24 | #. TRANS: h is a symbol for hours in a time (displays: 3h) 25 | #: ajax/timer.php:74 26 | #, php-format 27 | msgid "%dh" 28 | msgstr "%dh" 29 | 30 | #. TRANS: min is a symbol for minutes in a time (displays: 3min) 31 | #: ajax/timer.php:78 32 | #, php-format 33 | msgid "%dmin" 34 | msgstr "%d min" 35 | 36 | #. TRANS: s is a symbol for seconds in a time (displays: 3s) 37 | #: ajax/timer.php:82 38 | #, php-format 39 | msgid "%ds" 40 | msgstr "%ds" 41 | 42 | #: ajax/timer.php:93 43 | msgid "Timer started on" 44 | msgstr "Cronômetro iniciado no" 45 | 46 | #: inc/config.class.php:65 47 | msgid "ActualTime Setup" 48 | msgstr "ActualTime Setup" 49 | 50 | #: inc/config.class.php:99 51 | msgid "In Standard interface only (default)" 52 | msgstr "Somente na interface padrão (standard)" 53 | 54 | #: inc/config.class.php:100 55 | msgid "Both in Standard and Helpdesk interfaces" 56 | msgstr "Tanto na interface padrão quanto na helpdesk" 57 | 58 | #: inc/config.class.php:106 59 | msgid "Enable timer on tasks" 60 | msgstr "Habilitar cronômetro nas tarefas" 61 | 62 | #: inc/config.class.php:118 63 | msgid "Display pop-up window with current running timer" 64 | msgstr "Janela pop-up com temporizador em tempo real" 65 | 66 | #: inc/config.class.php:124 67 | msgid "Display actual time in closed task box ('Processing ticket' list)" 68 | msgstr "" 69 | "Exibe o tempo atual na janela de tarefas fechada(lista de 'ticket em " 70 | "processamento')" 71 | 72 | #: inc/config.class.php:130 73 | msgid "Automatically open task with timer running" 74 | msgstr "Abre tarefas com temporizador em execução automaticamente" 75 | 76 | #: inc/config.class.php:136 77 | msgid "Automatically update the duration" 78 | msgstr "Atualiza automaticamente a duração" 79 | 80 | #: inc/config.class.php:142 81 | msgid "Enable Timer Only on Scheduled Task Day" 82 | msgstr "Enable Timer Only on Scheduled Task Day" 83 | 84 | #: inc/config.class.php:148 85 | msgid "Enable Timer Only on Task's Start Day" 86 | msgstr "Enable Timer Only on Task's Start Day" 87 | 88 | #: inc/dashboard.class.php:48 89 | msgid "Top 20 Actualtime tasks per day" 90 | msgstr "Top 20 tarefas actualtime por dia" 91 | 92 | #: inc/dashboard.class.php:56 93 | msgid "Bottom 20 Actualtime tasks per day" 94 | msgstr "20 tarefas actualtime mais baixas por dia" 95 | 96 | #: inc/dashboard.class.php:64 97 | msgid "Top 20 Actualtime usage (hours)" 98 | msgstr "Top 20 usos actualtime (horas)" 99 | 100 | #: inc/dashboard.class.php:72 101 | msgid "Bottom 20 Actualtime usage (hours)" 102 | msgstr "20 usos inferiores actualtime(horas)" 103 | 104 | #: inc/dashboard.class.php:79 105 | msgid "Top 20 % Actualtime usage per day" 106 | msgstr "Top 20% de uso actualtime por dia" 107 | 108 | #: inc/dashboard.class.php:87 109 | msgid "Bottom 20 % Actualtime usage per day" 110 | msgstr "20% de usos inferiores actualtime por dia" 111 | 112 | #: inc/profile.class.php:103 113 | msgid "General" 114 | msgstr "General" 115 | 116 | #: inc/profile.class.php:138 inc/running.class.php:71 117 | msgid "Running timers" 118 | msgstr "Temporizadores em execução " 119 | 120 | #: inc/profile.class.php:154 inc/sourcetimer.class.php:173 121 | #: inc/sourcetimer.class.php:188 inc/task.class.php:476 122 | msgid "Modify timers" 123 | msgstr "Modify timers" 124 | 125 | #: inc/running.class.php:76 126 | msgid "Update every (s)" 127 | msgstr "Atualizado a cada (s)" 128 | 129 | #: inc/sourcetimer.class.php:53 130 | msgid "Modify tickets" 131 | msgstr "Modify tickets" 132 | 133 | #: inc/sourcetimer.class.php:54 134 | msgid "Modify changes" 135 | msgstr "Modify changes" 136 | 137 | #: inc/sourcetimer.class.php:55 138 | msgid "Modify projects" 139 | msgstr "Modify projects" 140 | 141 | #: inc/task.class.php:321 inc/task.class.php:482 142 | msgid "Actual Duration" 143 | msgstr "Duração real" 144 | 145 | #: inc/task.class.php:332 inc/task.class.php:493 146 | msgid "Partial actual duration" 147 | msgstr "Duração real parcial" 148 | 149 | #: inc/task.class.php:970 150 | msgid "Original end date" 151 | msgstr "Original end date" 152 | 153 | #: inc/task.class.php:971 154 | msgid "Original duration" 155 | msgstr "Original duration" 156 | 157 | #: inc/task.class.php:972 158 | #, php-format 159 | msgid "First modification by %s" 160 | msgstr "First modification by %s" 161 | 162 | #: inc/task.class.php:1362 inc/task.class.php:1368 163 | #, php-format 164 | msgid "You cannot start a timer because the task was scheduled for %d." 165 | msgstr "You cannot start a timer because the task was scheduled for %d." 166 | 167 | #: inc/task.class.php:1392 168 | msgid "You cannot add a timer on a different day." 169 | msgstr "You cannot add a timer on a different day." 170 | 171 | #: inc/task.class.php:1435 172 | msgid "Today is marked as absence you can not initialize the timer" 173 | msgstr "Hoje está marcado como ausência, você não pode iniciar o temporizador" 174 | 175 | #: inc/task.class.php:1441 176 | msgid "Timer has not been initialized" 177 | msgstr "A tarefa não foi inicializada" 178 | 179 | #: inc/task.class.php:1458 180 | msgid "You are already doing a waypoint" 181 | msgstr "Você já está fazendo um ponto de referência" 182 | 183 | #: inc/task.class.php:1495 inc/task.class.php:1500 184 | msgid "Technician not in charge of the task" 185 | msgstr "Técnico não encarregado da tarefa" 186 | 187 | #: inc/task.class.php:1506 188 | msgid "A user is already performing the task" 189 | msgstr "Outro usuário já está realizando a tarefa" 190 | 191 | #: inc/task.class.php:1556 192 | #, php-format 193 | msgid "You are already working on %s" 194 | msgstr "You are already working on %s" 195 | 196 | #: inc/task.class.php:1587 197 | msgid "Timer started" 198 | msgstr "Cronômetro iniciado" 199 | 200 | #: inc/task.class.php:1661 inc/task.class.php:1776 inc/task.class.php:1834 201 | msgid "Timer completed" 202 | msgstr "Cronômetro finalizado" 203 | 204 | #: inc/task.class.php:1699 inc/task.class.php:1813 205 | msgid "Only the user who initiated the task can close it" 206 | msgstr "Somente o usuário que iniciou a tarefa pode encerrá-la" 207 | 208 | #: inc/task.class.php:1702 209 | msgid "The task had not been initialized" 210 | msgstr "A tarefa não foi inicializada" 211 | --------------------------------------------------------------------------------