TASKPM: Fork LibrePlan with Java 21 migration and rebrand

Major changes from LibrePlan upstream:

Migration to Java 21 / Tomcat 9:
- ZK Framework 9.x → 8.6.0.1 (built-in databinding)
- Removed stub classes blocking real ZK databinder
- BCrypt password fix (matches() vs equals())
- Spring Security firewall for double-slash URLs
- I18nHelper _() → tr() (Java 9+ reserved keyword)
- Hibernate TypeContributor for Jadira types
- Fixed ConfigurationModel Currency locale handling

Rebrand to TASKPM:
- Maven project names updated
- web.xml display-name → taskpm-webapp
- CSS files: libreplan.css → taskpm.css
- i18n .po files updated (all locales)
- ZUL page titles updated
- Documentation rebranded

New Features:
- PERT Chart prototype using vis.js (/planner/pert/)
- New doc chapters: 22-taskpm.rst (PERT focus)
- Deploy automation scripts (migrate/)
- Help docs deployed to webapp

Removed:
- Original .forgejo and .github CI workflows (will be replaced)

TASKPM is a personal-oriented planning package integrating
taskwarrior/timewarrior with PERT/CPM Monte Carlo scheduling.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ren Juan 2026-01-23 11:52:02 +00:00
parent 358d01f419
commit cd3274c509
2149 changed files with 65804 additions and 4632 deletions

View file

@ -1,186 +0,0 @@
# This workflow will generate the database upgrade script for PostgreSQL
name: Generate PostgreSQL database upgrade script.
on:
workflow_dispatch:
jobs:
build:
runs-on: docker
container:
image: ubuntu:24.04
services:
postgres:
image: postgres:16.0
env:
POSTGRES_USER: libreplan
POSTGRES_PASSWORD: libreplan
POSTGRES_DB: libreplandev
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
# Define job-id
- name: Debug info
run: |
cat <<'EOF'
${{ toJSON(forgejo) }}
EOF
- name: My current run-id
run: echo "${{ forgejo.run_id }}"
# Define job-id
- name: install needed software
run: |
apt-get update
apt-get install -y postgresql-client nodejs git maven libpostgresql-jdbc-java
# Define job-id
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0
fetch-tags: true
show-progress: true
# This is only possible AFTER the checkout step.
- name: actions prep
id: artifact-upload-prep
run: echo "artifact-id=$(git rev-parse --short=10 HEAD)" >> "$GITHUB_OUTPUT"
# Let's try caching maven stuff.
- name: Cache Maven repository
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: maven-${{ hashFiles('**/pom.xml') }}
restore-keys: maven-
# Example 1: create extra database
# - name: Create libreplandevtest database
# env:
# PGPASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
# run: |
# PGPASSWORD='libreplan' psql -h postgres -U libreplan -d postgres -v ON_ERROR_STOP=1 -c "CREATE DATABASE libreplandevtest;"
- name: Set up Java 8
uses: actions/setup-java@v4
with:
distribution: temurin # of adopt, zulu, corretto, liberica …
java-version: 8
- name: Verify Java version
run: java -version
# Determine maven version in container
- name: Show maven version number
run: mvn -v
# Wait for PostgreSQL to be ready
- name: Wait for PostgreSQL to be ready
shell: bash
env:
PGPASSWORD: libreplan
run: |
for i in {1..30}; do
psql -h postgres -U libreplan -d libreplandev -c 'select 1' && break
sleep 2
done
# - name: "Checkout LibrePlan ${{ vars.full_last_release}} first."
# shell: bash
# run: |
# echo "First checkout older LibrePlan ${{ vars.full_last_release}} release"
# git checkout ${{ vars.full_last_release }}
# echo "Current branch: $(git rev-parse --abbrev-ref HEAD)"
# - name: Intermediare patch step. Fix old HTTP repo URLs in POMs
# shell: bash
# run: |
# find . -name "pom.xml" -print0 | xargs -0 sed -i \
# -e 's#http://gettext-commons.googlecode.com/svn/maven-repository#https://gettext-commons.googlecode.com/svn/maven-repository#g' \
# -e 's#http://nexus.***.org/content/repositories/thirdparty#https://nexus.***.org/content/repositories/thirdparty#g'
# # Setup clean empty database
# - name: Build clean ${{ vars.short_last_release }} db with Maven
# shell: bash
# run: |
# echo "Running maven to setup a ${{ vars.short_last_release }} database for a clean install"
# mvn clean install --no-transfer-progress -DskipTests -P-userguide,-reports,-i18n
# Instead of trying to do a build of the old version, just load the old database from the repo files.
- name: Populate database with database layout of last release.
shell: bash
run: |
echo "Populate database with database layout of ${{ vars.full_last_release }}"
cat scripts/database/install.sql | PGPASSWORD='libreplan' psql -h postgres -U libreplan -d libreplandev
- name: Switch to the new release.
shell: bash
run: |
echo "Switch to ${{ vars.short_new_release }}."
echo "We do not need to switch as we did not swotch before :-)"
# git checkout "${{ vars.full_new_release }}"
echo "Current branch: $(git rev-parse --abbrev-ref HEAD)"
# Yes, this looks ugly. But when cleanup over several lines mvn
# starts complaining: The POM for -DdataSource.url=jdbc:postgresql:jar://postgres is missing
# Starts thinking the datasource url is a pom it should download. Weird.
- name: "Generate database changes since version ${{ vars.short_last_release }}"
shell: bash
run: |
mvn clean install -DskipTests -P-userguide,-reports,-i18n,-liquibase-update,liquibase-updatesql -DdataSource.url=jdbc:postgresql://postgres:5432/libreplandev -DdataSource.user=libreplan -DdataSource.password=libreplan -DjdbcDriver.className=org.postgresql.Driver
# This will/should generate a file libreplan-business/target/liquibase/migrate.sql
# with the SQL script to migrate from previous version to the new one.
ls -l libreplan-business/target/liquibase/migrate.sql
- name: "The details of the generated migration script are:"
shell: bash
run: |
ls -l libreplan-business/target/liquibase/migrate.sql
lines=$( cat libreplan-business/target/liquibase/migrate.sql | grep -v '^--' | wc -l )
echo "The resulting migration script contained $lines lines. Processing migration script."
- name: "Copy the sql-file to database scripts folder"
shell: bash
run: |
cp -v libreplan-business/target/liquibase/migrate.sql scripts/database/upgrade_${{ vars.short_new_release }}.sql
- name: "Add information about version in the script"
shell: bash
run: |
sed -i "s/-- Update Database Script/-- Update Database Script - LibrePlan ${{ vars.short_new_release }}/" scripts/database/upgrade_${{ vars.short_new_release }}.sql
- name: "Append script at the end of ``install.sql`` file (with a separation of 2 new lines)"
shell: bash
run: |
echo -ne "\n\n" >> scripts/database/install.sql
cat scripts/database/upgrade_${{ vars.short_new_release }}.sql >> scripts/database/install.sql
# Upload the result
- name: Upload upgrade_${{ vars.short_new_release }}.sql
uses: actions/upload-artifact@v3
with:
name: upgrade_${{ vars.short_new_release }}.sql
path: scripts/database/upgrade_${{ vars.short_new_release }}.sql
retention-days: 3
- name: Upload install.sql
uses: actions/upload-artifact@v3
with:
name: install.sql
path: scripts/database/install.sql
retention-days: 3

View file

@ -1,172 +0,0 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
#
# It could, in theory, be possible to grep the current version number from the pom.xml file,
# and, again, in theory, get the last release name from the git tag list.
# But, sofar, this has been a road with major obstacles. And in the end you've just got to ask yourself:
# "Is the juice worth the squeeze.". (Movie: "The girl next door")
name: Generate NEWS file.
on:
workflow_dispatch:
jobs:
build:
runs-on: docker
container:
image: ubuntu:24.04
steps:
# Define job-id
- name: Debug info
run: |
cat <<'EOF'
${{ toJSON(forgejo) }}
EOF
- name: My current run-id
run: echo "${{ forgejo.run_id }}"
- name: install needed software
run: |
apt-get update
apt-get install -y nodejs git sed
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-tags: true # Also get the tags!!!
fetch-depth: 0
# This is only possible AFTER the checkout step.
- name: actions prep test to prove it works.
id: artifact-upload-prep
run: echo "artifact-id=$(git rev-parse --short=10 HEAD)" >> "$GITHUB_OUTPUT"
- name: Start writing NEWS.rst.head file
shell: bash
run: |
FILE="NEWS.rst.head"
echo "Writing to file: $FILE"
#Version 1.4.0 (29 Apr 2013)
#---------------------------
headstr="Version ${{ vars.short_new_release }} ($(LANG=en;date '+%d %b %Y'))"
headstrlen=${#headstr}
# echo "headstrlen: $headstrlen"
headline="$(printf -- '-%.0s' $(seq 1 "$headstrlen"))"
# echo "headline: $headline"
echo "$headstr" | tee -a "${FILE}"
echo -e "$headline\n\n" | tee -a "${FILE}"
- name: Start writing summary NEWS.rst.summary
shell: bash
run: |
filepart=summary
FILE="NEWS.rst.summary"
#verstr="Version ${{ vars.short_new_release }} ($(LANG=en;date +'%d %b %Y'))"
#echo "$verstr"
#verstrlen=${#verstr} | tee -a "${FILE}"
#echo "$verstrlen"
#linestr="$(printf -- '-%.0s' $(seq 1 $verstrlen))"
#echo "$linestr" | tee -a "${FILE}"
echo "Summary" | tee -a "${FILE}"
echo -e "~~~~~~~\n" | tee -a "${FILE}"
echo "Description of the new version ${{ vars.short_new_release }}, explaining the main features and bugs " | tee -a "${FILE}"
echo "included. It's usually similar to the piece of news that will be published " | tee -a "${FILE}"
echo "on the website. " | tee -a "${FILE}"
echo "" | tee -a "${FILE}"
- name: Start writing NEWS.rst.notes for NEWS.
shell: bash
run: |
# Hm, in this stage we have not enough information for this part.
filepart=notes
FILE="NEWS.rst.notes"
echo "Writing to file: $FILE"
# yes, I know about HERE files. I just don't like them!
echo "Notes" | tee -a "${FILE}"
echo -e "~~~~~\n\n" | tee -a "${FILE}"
echo "If you are upgrading from ${{ vars.short_last_release }} without using a " | tee -a "${FILE}"
echo "package, you will need to manually execute on your database the SQL commands" | tee -a "${FILE}"
echo "from file: 'scripts/database/upgrade_${{ vars.short_new_release }}.sql'." | tee -a "${FILE}"
echo "" | tee -a "${FILE}"
echo "If you are upgrading from earlier version without using the Debian package," | tee -a "${FILE}"
echo "you will need to manually execute on your database the SQL commands from all files." | tee -a "${FILE}"
echo "" | tee -a "${FILE}"
- name: Start writing NEWS.rst.contributors for NEWS.
shell: bash
run: |
filepart=contributers
FILE="NEWS.rst.contributers"
echo "Contributors" | tee -a "${FILE}"
echo -e "~~~~~~~~~~~~\n" | tee -a "${FILE}"
echo -e "A big thanks to all the contributors to version ${{ inputs.short-new-release }} :\n" | tee -a "${FILE}"
#git shortlog -ns "${{ vars.full_last_release }}.." | cut -f2- | sed -e 's/^/* /' | sort -u | tee -a "${FILE}"
git shortlog -ns "${{ vars.full_last_release }}.." | cut -f2- | sed -e 's/^/* /' | sort -u | tee -a "${FILE}"
echo "" | tee -a "${FILE}"
- name: Start writing NEWS.rst.translators for NEWS.
shell: bash
run: |
# If there're changes in the translations we add the name and language of
# each of them in this section.
filepart=translators
FILE="NEWS.rst.translators"
# We do not insert new Translators block as we already copy the old block including the header.
# echo "Translators" | tee -a "${FILE}"
# echo -e "~~~~~~~~~~~\n\n" | tee -a "${FILE}"
echo "Inserting translator block from last release." | tee -a $LOG
cat NEWS.rst | sed -n -e '/^Translators/,/^Changes/p' | sed -e '/^Changes/,$d' | tee -a "${FILE}"
- name: Start writing NEWS.rst.changes
shell: bash
run: |
# Comprehensive list of changes done in the repository since previous
# version.
filepart=changes
FILE="NEWS.rst.changes"
echo "Writing to file: $FILE"
echo "Changes" | tee -a "${FILE}"
echo -e "~~~~~~~\n" | tee -a "${FILE}"
git log --pretty="* %s" "${{ vars.full_last_release }}.." | tee -a "${FILE}"
# Concatenate the files
- name: Generate resulting NEWS.rst.part
shell: bash
run: |
echo "Building changes to NEWS.rst file"
echo "NEWS" > /tmp/lpnews.$$
echo -e "====\n" >> /tmp/lpnews.$$
for filepart in head summary notes contributers translators changes
do
cat "NEWS.rst.$filepart" >> /tmp/lpnews.$$
done
cat /tmp/lpnews.$$ > /tmp/lpnews2.$$
cp /tmp/lpnews.$$ LATEST-NEWS.rst
echo "Cut 2 lines from original NEWS.rst file" | tee -a $LOG
cat NEWS.rst | sed -e '1,2d' >> /tmp/lpnews2.$$
echo "Check NEWS.rst file before continueing..."
cp /tmp/lpnews2.$$ NEWS.rst
# Upload the result
- name: Upload NEWS.rst
uses: actions/upload-artifact@v3
with:
name: NEWS.rst
path: NEWS.rst
compression-level: 0 # no compression
retention-days: 3
- name: Upload LATEST-NEWS.rst
uses: actions/upload-artifact@v3
with:
name: LATEST-NEWS-for-${{ vars.short_new_release }}.rst
path: LATEST-NEWS.rst
compression-level: 0 # no compression
retention-days: 3

View file

@ -1,152 +0,0 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Ubuntu 24.04 (Noble Numbat)
on:
workflow_dispatch:
inputs:
create-release:
description: 'Create a release from this build?'
default: false
type: boolean
push:
# branches: [ "main" ]
tags:
- "v*"
# pull_request:
# branches: [ "main" ]
# Prevent cancellation of already running actions when pushing concurrently. Test
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
build:
runs-on: docker
container:
image: ubuntu:24.04
services:
postgres:
image: postgres:16.0
env:
POSTGRES_USER: libreplan
POSTGRES_PASSWORD: libreplan
POSTGRES_DB: libreplandev
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
# Define job-id
- name: Debug info
run: |
cat <<'EOF'
${{ toJSON(forgejo) }}
EOF
- name: My current run-id
run: echo "${{ forgejo.run_id }}"
- name: install needed software
run: |
apt-get update
apt-get install -y postgresql-client nodejs git maven libpostgresql-jdbc-java
- name: Checkout code
uses: actions/checkout@v3
# This is only possible AFTER the checkout step.
- name: actions prep
id: artifact-upload-prep
run: echo "artifact-id=$(git rev-parse --short=10 HEAD)" >> "$GITHUB_OUTPUT"
# Let's test caching maven stuff.
- name: Cache Maven repository
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: maven-${{ hashFiles('**/pom.xml') }}
restore-keys: maven-
# Example 1: create extra database
- name: Create libreplandevtest database
env:
PGPASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
run: |
PGPASSWORD='libreplan' psql -h postgres -U libreplan -d postgres -v ON_ERROR_STOP=1 -c "CREATE DATABASE libreplandevtest;"
- name: Set up Java 8
uses: actions/setup-java@v4
with:
distribution: temurin # of adopt, zulu, corretto, liberica …
java-version: 8
- name: Verify Java version
run: java -version
# Determine maven version in container
- name: Show maven version number
run: mvn -v
- name: Wait for PostgreSQL to be ready
shell: bash
env:
PGPASSWORD: libreplan
run: |
for i in {1..30}; do
psql -h postgres -U libreplan -d libreplandev -c 'select 1' && break
sleep 2
done
# Yes, this looks ugly. But when cleanup over several lines mvn
# starts complaining: The POM for -DdataSource.url=jdbc:postgresql:jar://postgres is missing
# Starts thinking the datasource url is a pom it should download. Weird.
- name: Build with Maven
shell: bash
run: mvn clean install --no-transfer-progress -Ddefault.passwordsControl=false -Ddefault.exampleUsersDisabled=false -DdataSource.url=jdbc:postgresql://postgres:5432/libreplandev -DdataSource.user=libreplan -DdataSource.password=libreplan -DjdbcDriver.className=org.postgresql.Driver
- name: Copy libreplan-webapp.war to libreplan.war
run: cp libreplan-webapp/target/libreplan-webapp.war libreplan-webapp/target/libreplan.war
# Upload the result
- name: Upload libreplan.war attempt 1
uses: actions/upload-artifact@v3
with:
name: libreplan.war
path: libreplan-webapp/target/libreplan.war
retention-days: 3
- name: Upload libreplan.war with git hash
uses: actions/upload-artifact@v3
with:
name: libreplan-${{ steps.artifact-upload-prep.outputs.artifact-id }}.war
path: libreplan-webapp/target/libreplan.war
retention-days: 3
- name: Prep release dir for upload
run: |
mkdir -p dist/release
cp libreplan-webapp/target/libreplan.war dist/release/libreplan.war
# Also store as a release.
- uses: actions/forgejo-release@v2.7.3
with:
direction: upload
url: http://10.1.1.158:3000
repo: jeroen/libreplan
token: ${{ secrets.WRITE_TOKEN_TO_MYREPO }}
tag: v2025
release-dir: dist/release
release-notes: "No RELEASE NOTES"
verbose: true

View file

@ -1,52 +0,0 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Ubuntu 20.04 (Focal Fossa)
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-20.04
services:
postgres:
image: postgres:12.0
env:
POSTGRES_USER: libreplan
POSTGRES_PASSWORD: libreplan
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Create libreplandev database
uses: akanieski/setup-postgres-cli@v0.1.2
with:
commands: PGPASSWORD=libreplan psql -U libreplan -h postgres -p 5432 -c "CREATE DATABASE libreplandev;"
- name: Create libreplandevtest database
uses: akanieski/setup-postgres-cli@v0.1.2
with:
commands: PGPASSWORD=libreplan psql -U libreplan -h postgres -p 5432 -c "CREATE DATABASE libreplandevtest;"
- name: Set up JDK 8
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: mvn -Ddefault.passwordsControl=false -Ddefault.exampleUsersDisabled=false clean install

View file

@ -1,51 +0,0 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Ubuntu 22.04 (Jammy Jellyfish)
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-22.04
services:
postgres:
image: postgres:14.0
env:
POSTGRES_USER: libreplan
POSTGRES_PASSWORD: libreplan
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Create libreplandev database
uses: akanieski/setup-postgres-cli@v0.1.2
with:
commands: PGPASSWORD=libreplan psql -U libreplan -h postgres -p 5432 -c "CREATE DATABASE libreplandev;"
- name: Create libreplandevtest database
uses: akanieski/setup-postgres-cli@v0.1.2
with:
commands: PGPASSWORD=libreplan psql -U libreplan -h postgres -p 5432 -c "CREATE DATABASE libreplandevtest;"
- name: Set up JDK 8
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: mvn -Ddefault.passwordsControl=false -Ddefault.exampleUsersDisabled=false clean install

View file

@ -1,51 +0,0 @@
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Ubuntu 24.04 (Noble Numbat)
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-24.04
services:
postgres:
image: postgres:16.0
env:
POSTGRES_USER: libreplan
POSTGRES_PASSWORD: libreplan
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Create libreplandev database
uses: akanieski/setup-postgres-cli@v0.1.2
with:
commands: PGPASSWORD=libreplan psql -U libreplan -h postgres -p 5432 -c "CREATE DATABASE libreplandev;"
- name: Create libreplandevtest database
uses: akanieski/setup-postgres-cli@v0.1.2
with:
commands: PGPASSWORD=libreplan psql -U libreplan -h postgres -p 5432 -c "CREATE DATABASE libreplandevtest;"
- name: Set up JDK 8
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: mvn -Ddefault.passwordsControl=false -Ddefault.exampleUsersDisabled=false clean install

14
.gitignore vendored
View file

@ -39,4 +39,16 @@ doc/src/user/gl/html/
doc/src/user/gl/index.rst doc/src/user/gl/index.rst
#ignore files that need ignoring #ignore files that need ignoring
*.ignore *.ignore
# TASKPM local files
CLAUDE.md
SESSION-NOTES.md
MIGRATION_PLAN.md
MIGRATION_STATUS.md
cookies.txt
trash/
migrate/*.log
migrate/catalina.out
migrate/log.txt
migrate/doc-baseline/

View file

@ -5,10 +5,10 @@ LibrePlan
Description Description
----------- -----------
*LibrePlan* is a free software web application for project management, *TASKPM* is a free software web application for project management,
monitoring and control. monitoring and control.
*LibrePlan* is a collaborative tool to plan, monitor and control projects and *TASKPM* is a collaborative tool to plan, monitor and control projects and
has a rich web interface which provides a desktop alike user experience. All the has a rich web interface which provides a desktop alike user experience. All the
team members can take part in the planning and this makes possible to have a team members can take part in the planning and this makes possible to have a
real-time planning. real-time planning.
@ -131,10 +131,10 @@ http://sourceforge.net/projects/libreplan/files/
Webpage Webpage
------- -------
You can find more information about *LibrePlan* at You can find more information about *TASKPM* at
https://www.libreplan.dev/home/ https://www.libreplan.dev/home/
For information related with *LibrePlan* development you can visit the wiki at For information related with *TASKPM* development you can visit the wiki at
https://wiki.libreplan.dev or have a look at the DeepWiki documentation: |Ask DeepWiki| https://wiki.libreplan.dev or have a look at the DeepWiki documentation: |Ask DeepWiki|
.. |Ask DeepWiki| image:: https://deepwiki.com/badge.svg .. |Ask DeepWiki| image:: https://deepwiki.com/badge.svg
@ -150,7 +150,7 @@ Please use the bug tracker to report bugs at http://bugs.libreplan.dev/
License License
------- -------
*LibrePlan* is released under the terms of the GNU Affero General Public *TASKPM* is released under the terms of the GNU Affero General Public
License version 3 [3]_. License version 3 [3]_.
Please read the ``COPYING`` file for details. Please read the ``COPYING`` file for details.

View file

@ -3,18 +3,20 @@ Introduction
.. contents:: .. contents::
This document describes the features of LibrePlan and provides user information on how to configure and use the application. This document describes the features of TASKPM and provides user information on how to configure and use the application.
LibrePlan is an open-source web application for project planning. Its primary goal is to provide a comprehensive solution for company project management. For any specific information you may need about this software, please contact the development team at http://www.libreplan.com/contact/ TASKPM is an open-source web application for personal project planning. The primary goal of Libreplan was to provide a comprehensive solution for company project management. TASKPM retains this functionality but with its integration with timewarrior and taskwarrior adds a personal planning orientation.
.. figure:: images/company_view.png .. figure:: images/company_view.png
:scale: 50 :scale: 50
Company Overview Company Overview
Company Overview and View Management TASKPM Situation and View Management
==================================== ====================================
The TASKPM use case situation is a single staff resource who is also the sole proprietoru and any number of agent workers. This combine is to be read in the Libreplan documentation where "company" is used. To the extent possible we have tried to leave Libreplan functionality as is simply reinterpret with or without renaming for the reframing to the new personal oriention. So there are internal andexternal views in TASKPM, the external ones look inward from newly added document and carry the reinterpretation while most of the prexisting chapters, in their entirety, look outward from the standard model of the firm perspective of Libreplan.
As shown in the program's main screen (see the previous screenshot) and the company overview, users can view a list of planned projects. This allows them to understand the company's overall status regarding orders and resource utilization. The company overview offers three distinct views: As shown in the program's main screen (see the previous screenshot) and the company overview, users can view a list of planned projects. This allows them to understand the company's overall status regarding orders and resource utilization. The company overview offers three distinct views:
* **Planning View:** This view combines two perspectives: * **Planning View:** This view combines two perspectives:
@ -48,19 +50,19 @@ The program offers the following views for an order:
* **Editing Order View:** This view allows users to modify the details of the order. See the *Orders* section for more information. * **Editing Order View:** This view allows users to modify the details of the order. See the *Orders* section for more information.
* **Advanced Resource Allocation View:** This view allows users to allocate resources with advanced options, such as specifying hours per day or the allocated functions to be performed. See the *Resource allocation* section for more information. * **Advanced Resource Allocation View:** This view allows users to allocate resources with advanced options, such as specifying hours per day or the allocated functions to be performed. See the *Resource allocation* section for more information.
What Makes LibrePlan Useful? What Makes TASKPM Useful?
============================ ============================
LibrePlan is a general-purpose planning tool developed to address challenges in industrial project planning that were not adequately covered by existing tools. The development of LibrePlan was also motivated by the desire to provide a free, open-source, and entirely web-based alternative to proprietary planning tools. TASKPM is a general-purpose planning tool developed to address challenges in industrial project planning that were not adequately covered by existing tools. The development of TASKPM was also motivated by the desire to provide a free, open-source, and entirely web-based alternative to proprietary planning tools.
The core concepts underpinning the program are as follows: The core concepts underpinning the program are as follows:
* **Company and Multi-Project Overview:** LibrePlan is specifically designed to provide users with information about multiple projects being carried out within a company. Therefore, it is inherently a multi-project program. The program's focus is not limited to individual projects, although specific views for individual projects are also available. * **Company and Multi-Project Overview:** TASKPM is specifically designed to provide users with information about multiple projects being carried out within a company. Therefore, it is inherently a multi-project program. The program's focus is not limited to individual projects, although specific views for individual projects are also available.
* **View Management:** The company overview, or multi-project view, is accompanied by various views of the stored information. For example, the company overview allows users to view orders and compare their status, view the company's overall resource load, and manage orders. Users can also access the planning view, resource load view, advanced resource allocation view, and editing order view for individual projects. * **View Management:** The company overview, or multi-project view, is accompanied by various views of the stored information. For example, the company overview allows users to view orders and compare their status, view the company's overall resource load, and manage orders. Users can also access the planning view, resource load view, advanced resource allocation view, and editing order view for individual projects.
* **Criteria:** Criteria are a system entity that enables the classification of both resources (human and machine) and tasks. Resources must meet certain criteria, and tasks require specific criteria to be fulfilled. This is one of the program's most important features, as criteria form the basis of generic allocation and address a significant challenge in the industry: the time-consuming nature of human resource management and the difficulty of long-term company load estimations. * **Criteria:** Criteria are a system entity that enables the classification of both resources (human and machine) and tasks. Resources must meet certain criteria, and tasks require specific criteria to be fulfilled. This is one of the program's most important features, as criteria form the basis of generic allocation and address a significant challenge in the industry: the time-consuming nature of human resource management and the difficulty of long-term company load estimations.
* **Resources:** There are two types of resources: human and machine. Human resources are the company's workers, used for planning, monitoring, and controlling the company's workload. Machine resources, dependent on the people who operate them, function similarly to human resources. * **Resources:** There are two types of resources: human and machine. Human resources are the company's workers, used for planning, monitoring, and controlling the company's workload. Machine resources, dependent on the people who operate them, function similarly to human resources.
* **Resource Allocation:** A key feature of the program is the ability to designate resources in two ways: specifically and generically. Generic allocation is based on the criteria required to complete a task and must be fulfilled by resources capable of meeting those criteria. To understand generic allocation, consider this example: John Smith is a welder. Typically, John Smith would be specifically assigned to a planned task. However, LibrePlan offers the option of selecting any welder within the company, without needing to specify that John Smith is the assigned person. * **Resource Allocation:** A key feature of the program is the ability to designate resources in two ways: specifically and generically. Generic allocation is based on the criteria required to complete a task and must be fulfilled by resources capable of meeting those criteria. To understand generic allocation, consider this example: John Smith is a welder. Typically, John Smith would be specifically assigned to a planned task. However, TASKPM offers the option of selecting any welder within the company, without needing to specify that John Smith is the assigned person.
* **Company Load Control:** The program allows for easy control of the company's resource load. This control extends to both the mid-term and long-term, as current and future projects can be managed within the program. LibrePlan provides graphs that visually represent resource utilization. * **Company Load Control:** The program allows for easy control of the company's resource load. This control extends to both the mid-term and long-term, as current and future projects can be managed within the program. TASKPM provides graphs that visually represent resource utilization.
* **Labels:** Labels are used to categorize project tasks. With these labels, users can group tasks by concept, allowing for later review as a group or after filtering. * **Labels:** Labels are used to categorize project tasks. With these labels, users can group tasks by concept, allowing for later review as a group or after filtering.
* **Filters:** Because the system naturally includes elements that label or characterize tasks and resources, criteria filters or labels can be used. This is very useful for reviewing categorized information or generating specific reports based on criteria or labels. * **Filters:** Because the system naturally includes elements that label or characterize tasks and resources, criteria filters or labels can be used. This is very useful for reviewing categorized information or generating specific reports based on criteria or labels.
* **Calendars:** Calendars define the available productive hours for different resources. Users can create general company calendars or define more specific calendars, allowing for the creation of calendars for individual resources and tasks. * **Calendars:** Calendars define the available productive hours for different resources. Users can create general company calendars or define more specific calendars, allowing for the creation of calendars for individual resources and tasks.
@ -69,7 +71,7 @@ The core concepts underpinning the program are as follows:
* **Tasks:** Tasks are the fundamental planning elements within the program. They are used to schedule work to be carried out. Key characteristics of tasks include: dependencies between tasks, and the potential requirement for specific criteria to be met before resources can be allocated. * **Tasks:** Tasks are the fundamental planning elements within the program. They are used to schedule work to be carried out. Key characteristics of tasks include: dependencies between tasks, and the potential requirement for specific criteria to be met before resources can be allocated.
* **Work Reports:** These reports, submitted by the company's workers, detail the hours worked and the tasks associated with those hours. This information allows the system to calculate the actual time taken to complete a task compared to the budgeted time. Progress can then be compared against the actual hours used. * **Work Reports:** These reports, submitted by the company's workers, detail the hours worked and the tasks associated with those hours. This information allows the system to calculate the actual time taken to complete a task compared to the budgeted time. Progress can then be compared against the actual hours used.
In addition to the core functions, LibrePlan offers other features that distinguish it from similar programs: In addition to the core functions, TASKPM offers other features that distinguish it from similar programs:
* **Integration with ERP:** The program can directly import information from company ERP systems, including orders, human resources, work reports, and specific criteria. * **Integration with ERP:** The program can directly import information from company ERP systems, including orders, human resources, work reports, and specific criteria.
* **Version Management:** The program can manage multiple planning versions, while still allowing users to review the information from each version. * **Version Management:** The program can manage multiple planning versions, while still allowing users to review the information from each version.

View file

@ -12,7 +12,7 @@ The following sections describe the operations that users can perform with order
Orders Orders
====== ======
An order represents a project or work requested by a client from the company. The order identifies the project within the company's planning. Unlike comprehensive management programs, LibrePlan only requires certain key details for an order. These details are: An order represents a project or work requested by a client from the company. The order identifies the project within the company's planning. Unlike comprehensive management programs, TASKPM only requires certain key details for an order. These details are:
* **Order Name:** The name of the order. * **Order Name:** The name of the order.
* **Order Code:** A unique code for the order. * **Order Code:** A unique code for the order.

View file

@ -7,7 +7,7 @@ Task Planning
Task Planning Task Planning
============= =============
Planning in LibrePlan is a process that has been described throughout the user guide, with the chapters on orders and resource assignment being particularly important. This chapter describes the basic planning procedures after the order and Gantt charts have been properly configured. Planning in TASKPM is a process that has been described throughout the user guide, with the chapters on orders and resource assignment being particularly important. This chapter describes the basic planning procedures after the order and Gantt charts have been properly configured.
.. figure:: images/planning-view.png .. figure:: images/planning-view.png
:scale: 35 :scale: 35

View file

@ -7,7 +7,7 @@ User Management
Managing Users Managing Users
============== ==============
LibrePlan's system allows administrators to manage user profiles, authorizations, and users. Users are assigned to user profiles, which can have a series of predefined roles that grant access to the program's features. Roles are defined authorizations within LibrePlan. Examples of roles include: TASKPM's system allows administrators to manage user profiles, authorizations, and users. Users are assigned to user profiles, which can have a series of predefined roles that grant access to the program's features. Roles are defined authorizations within TASKPM. Examples of roles include:
* **Administration:** A role that must be assigned to administrators to enable them to perform administrative operations. * **Administration:** A role that must be assigned to administrators to enable them to perform administrative operations.
* **Web Service Reader:** A role required for users to consult the program's web services. * **Web Service Reader:** A role required for users to consult the program's web services.

View file

@ -64,7 +64,7 @@ For each project selected for inclusion in the report output, the following info
* *Project Name*. * *Project Name*.
* *Total Hours*. The total hours for the project are shown by adding the hours for each task. Two types of total hours are shown: * *Total Hours*. The total hours for the project are shown by adding the hours for each task. Two types of total hours are shown:
* *Estimated (TE)*. This is the sum of all the estimated hours in the project's WBS. It represents the total number of hours estimated to complete the project. * *Estimated (TE)*. This is the sum of all the estimated hours in the project's WBS. It represents the total number of hours estimated to complete the project.
* *Planned (TP)*. In *LibrePlan*, it's possible to have two different quantities: the estimated number of hours for a task (the number of hours initially estimated to complete the task) and the planned hours (the hours allocated in the plan to complete the task). The planned hours can be equal to, less than, or greater than the estimated hours and are determined in a later phase, the assignment operation. Therefore, the total planned hours for a project are the sum of all the allocated hours for its tasks. * *Planned (TP)*. In *TASKPM*, it's possible to have two different quantities: the estimated number of hours for a task (the number of hours initially estimated to complete the task) and the planned hours (the hours allocated in the plan to complete the task). The planned hours can be equal to, less than, or greater than the estimated hours and are determined in a later phase, the assignment operation. Therefore, the total planned hours for a project are the sum of all the allocated hours for its tasks.
* *Progress*. Three measurements related to the overall progress of the type specified in the progress input filter for each project at the reference date are shown: * *Progress*. Three measurements related to the overall progress of the type specified in the progress input filter for each project at the reference date are shown:
* *Measured (PM)*. This is the overall progress considering the progress measurements with a date earlier than the *Reference Date* in the input parameters of the report. All tasks are taken into account, and the sum is weighted by the number of hours for each task. * *Measured (PM)*. This is the overall progress considering the progress measurements with a date earlier than the *Reference Date* in the input parameters of the report. All tasks are taken into account, and the sum is weighted by the number of hours for each task.
* *Imputed (PI)*. This is the progress assuming that work continues at the same pace as the hours completed for a task. If X hours out of Y hours for a task are completed, the overall imputed progress is considered to be X/Y. * *Imputed (PI)*. This is the progress assuming that work continues at the same pace as the hours completed for a task. If X hours out of Y hours for a task are completed, the overall imputed progress is considered to be X/Y.

View file

@ -4,7 +4,7 @@ Reports
.. _informes: .. _informes:
.. contents:: .. contents::
LibrePlan integrates with *JasperReports* to provide report management, enabling users to generate various reports for analyzing the data available in the program. TASKPM integrates with *JasperReports* to provide report management, enabling users to generate various reports for analyzing the data available in the program.
The available reports are: The available reports are:

View file

@ -11,15 +11,15 @@ It is divided into four different areas, which are explained below:
Activation Activation
========== ==========
This area is used to set the properties that determine how *LibrePlan* uses This area is used to set the properties that determine how *TASKPM* uses
LDAP. LDAP.
If the field *Enable LDAP authentication* is checked, *LibrePlan* will query If the field *Enable LDAP authentication* is checked, *TASKPM* will query
LDAP each time a user attempts to log in to the application. LDAP each time a user attempts to log in to the application.
The field *Use LDAP roles* checked means that a mapping between LDAP roles and The field *Use LDAP roles* checked means that a mapping between LDAP roles and
LibrePlan roles is established. Consequently, the permissions for a user in TASKPM roles is established. Consequently, the permissions for a user in
LibrePlan will depend on the roles the user has in LDAP. TASKPM will depend on the roles the user has in LDAP.
Configuration Configuration
============= =============
@ -51,8 +51,8 @@ should be found. The property *UserId* must be filled with the name of the
property where the username is stored in LDAP. property where the username is stored in LDAP.
The checkbox *Save passwords in database*, when checked, means that the The checkbox *Save passwords in database*, when checked, means that the
password is also stored in the LibrePlan database. In this way, if LDAP is password is also stored in the TASKPM database. In this way, if LDAP is
offline or unreachable, LDAP users can authenticate against the LibrePlan offline or unreachable, LDAP users can authenticate against the TASKPM
database. If it is not checked, LDAP users can only be authenticated against database. If it is not checked, LDAP users can only be authenticated against
LDAP. LDAP.
@ -60,7 +60,7 @@ Authorization
============= =============
This section allows you to define a strategy for matching LDAP roles with This section allows you to define a strategy for matching LDAP roles with
LibrePlan roles. The first choice is the strategy to use, depending on the TASKPM roles. The first choice is the strategy to use, depending on the
LDAP implementation. LDAP implementation.
Group Strategy Group Strategy
@ -195,10 +195,10 @@ And, for example, if you want to match some roles:
**By User Identifier** **By User Identifier**
You can even use a workaround to specify LibrePlan roles directly to users You can even use a workaround to specify TASKPM roles directly to users
without having an attribute in each LDAP user. without having an attribute in each LDAP user.
In this case, you will specify which users have the different LibrePlan roles In this case, you will specify which users have the different TASKPM roles
by ``uid``. by ``uid``.
The configuration for this case is as follows: The configuration for this case is as follows:
@ -220,9 +220,9 @@ And, for example, if you want to match some roles:
Role Matching Role Matching
------------- -------------
At the bottom of this section, there is a table with all the LibrePlan roles At the bottom of this section, there is a table with all the TASKPM roles
and a text field next to each one. This is for matching roles. For instance, and a text field next to each one. This is for matching roles. For instance,
if an administrator decides that the *Administration* LibrePlan role matches if an administrator decides that the *Administration* TASKPM role matches
the *admin* and *administrators* roles of LDAP, the text field should contain: the *admin* and *administrators* roles of LDAP, the text field should contain:
"``admin;administrators``". The character for splitting roles is "``;``". "``admin;administrators``". The character for splitting roles is "``;``".

View file

@ -3,7 +3,7 @@ Project Dashboard
.. contents:: .. contents::
The project dashboard is a *LibrePlan* perspective that contains a set of **KPIs (Key Performance Indicators)** to help assess a project's performance in terms of: The project dashboard is a *TASKPM* perspective that contains a set of **KPIs (Key Performance Indicators)** to help assess a project's performance in terms of:
* Work progress * Work progress
* Cost * Cost

View file

@ -3,7 +3,7 @@ Pipeline Dashboard
.. contents:: .. contents::
The pipeline dashboard is a *LibrePlan* perspective that lists all company projects in a table. This "pipeline" table has nine columns, each corresponding to a project status: The pipeline dashboard is a *TASKPM* perspective that lists all company projects in a table. This "pipeline" table has nine columns, each corresponding to a project status:
* PRE-SALES * PRE-SALES
* OFFERED * OFFERED

View file

@ -4,7 +4,7 @@ Dashboards
.. _informes: .. _informes:
.. contents:: .. contents::
*LibrePlan* offers dashboard views for projects, providing an overview of their current status. *TASKPM* offers dashboard views for projects, providing an overview of their current status.
The two available dashboard views are: The two available dashboard views are:

View file

@ -3,7 +3,7 @@ Connectors
.. contents:: .. contents::
Connectors are *LibrePlan* client applications that can be used to communicate with (web) servers to retrieve data, process it, and store it. Currently, there are three connectors: the JIRA connector, the Tim Enterprise connector, and the E-mail connector. Connectors are *TASKPM* client applications that can be used to communicate with (web) servers to retrieve data, process it, and store it. Currently, there are three connectors: the JIRA connector, the Tim Enterprise connector, and the E-mail connector.
Configuration Configuration
============= =============
@ -29,7 +29,7 @@ JIRA is an issue and project tracking system.
The JIRA connector is an application that can be used to request JIRA web server data for JIRA issues and process the response. The request is based on JIRA labels. In JIRA, labels can be used to categorize issues. The request is structured as follows: retrieve all issues that are categorized by this label name. The JIRA connector is an application that can be used to request JIRA web server data for JIRA issues and process the response. The request is based on JIRA labels. In JIRA, labels can be used to categorize issues. The request is structured as follows: retrieve all issues that are categorized by this label name.
The connector receives the response, which in this case is the issues, and converts them to *LibrePlan* "Order elements" and "Time sheets." The connector receives the response, which in this case is the issues, and converts them to *TASKPM* "Order elements" and "Time sheets."
The *JIRA connector* must be configured properly before it can be used. The *JIRA connector* must be configured properly before it can be used.
@ -163,24 +163,24 @@ For import, the Tim connector adds the following fields in the request:
* **Department:** The department for which you want to import the roster. Departments are configurable. * **Department:** The department for which you want to import the roster. Departments are configurable.
* The fields you are interested in (like Person info, RosterCategory, etc.) that the Tim server should include in its response. * The fields you are interested in (like Person info, RosterCategory, etc.) that the Tim server should include in its response.
The import response contains the following fields, which are sufficient to manage the exception days in *LibrePlan*: The import response contains the following fields, which are sufficient to manage the exception days in *TASKPM*:
* **Person info:** Name and network name. * **Person info:** Name and network name.
* **Department:** The department the worker is working in. * **Department:** The department the worker is working in.
* **Roster category:** Information on the presence/absence (Aanwzig/afwezig) of the worker and the reason (*LibrePlan* exception type) in case the worker is absent. * **Roster category:** Information on the presence/absence (Aanwzig/afwezig) of the worker and the reason (*TASKPM* exception type) in case the worker is absent.
* **Date:** The date the worker is present/absent. * **Date:** The date the worker is present/absent.
* **Time:** The start time of presence/absence, for example, 08:00. * **Time:** The start time of presence/absence, for example, 08:00.
* **Duration:** The number of hours that the worker is present/absent. * **Duration:** The number of hours that the worker is present/absent.
By converting the import response to *LibrePlan*'s "Exception day," the following translations are taken into account: By converting the import response to *TASKPM*'s "Exception day," the following translations are taken into account:
* If the roster category contains the name "Vakantie," it will be translated to "RESOURCE HOLIDAY." * If the roster category contains the name "Vakantie," it will be translated to "RESOURCE HOLIDAY."
* The roster category "Feestdag" will be translated to "BANK HOLIDAY." * The roster category "Feestdag" will be translated to "BANK HOLIDAY."
* All the rest, like "Jus uren," "PLB uren," etc., should be added to the "Calendar Exception Days" manually. * All the rest, like "Jus uren," "PLB uren," etc., should be added to the "Calendar Exception Days" manually.
Moreover, in the import response, the roster is divided into two or three parts per day: for example, roster-morning, roster-afternoon, and roster-evening. However, *LibrePlan* allows only one "Exception type" per day. The Tim connector is then responsible for merging these parts as one exception type. That is, the roster category with the highest duration is assumed to be a valid exception type, but the total duration is the sum of all durations of these category parts. Moreover, in the import response, the roster is divided into two or three parts per day: for example, roster-morning, roster-afternoon, and roster-evening. However, *TASKPM* allows only one "Exception type" per day. The Tim connector is then responsible for merging these parts as one exception type. That is, the roster category with the highest duration is assumed to be a valid exception type, but the total duration is the sum of all durations of these category parts.
Contrary to *LibrePlan*, in Tim Enterprise, the total duration in case the worker is on holiday means the worker is not available for that total duration. However, in *LibrePlan*, if the worker is on holiday, the total duration should be zero. The Tim connector also handles this translation. Contrary to *TASKPM*, in Tim Enterprise, the total duration in case the worker is on holiday means the worker is not available for that total duration. However, in *TASKPM*, if the worker is on holiday, the total duration should be zero. The Tim connector also handles this translation.
E-mail Connector E-mail Connector
================ ================

View file

@ -10,7 +10,7 @@ To use this scheduler effectively, the jobs (Quartz jobs) that should be schedul
When the scheduler starts, it reads the jobs to be scheduled or unscheduled from the database and schedules or removes them accordingly. Afterward, jobs can be added, updated, or removed dynamically using the ``Job scheduling`` user interface. When the scheduler starts, it reads the jobs to be scheduled or unscheduled from the database and schedules or removes them accordingly. Afterward, jobs can be added, updated, or removed dynamically using the ``Job scheduling`` user interface.
.. NOTE:: .. NOTE::
The scheduler starts when the LibrePlan web application starts and stops when the application stops. The scheduler starts when the TASKPM web application starts and stops when the application stops.
.. NOTE:: .. NOTE::
This scheduler supports only ``cron expressions`` to schedule jobs. This scheduler supports only ``cron expressions`` to schedule jobs.

View file

@ -0,0 +1,7 @@
PERT Chart and Subnets
###############################
In Libreplan, there were only projects an orders, one level of work, in TASKPM there are two, master projects and subprojects. Unlike Libreplan, which was focused on the GANNT chart and did not have a PERT chart, TASKPM does have a PERT chart and introduces a top level of planning activity based on it.
The original orders and project code and documentation of Libreplan is preserved but in it project should be understood to be a structured task ordered by a master project.

View file

@ -1,16 +1,16 @@
############################# #############################
LibrePlan: User documentation TASKPM: User documentation
############################# #############################
.. image:: images/logo.png .. image:: images/logo.png
:align: left :align: left
Following document contains necessary help for using LibrePlan, the opensource web application for project planning. Following document contains necessary help for using TASKPM, the opensource web application for project planning.
This document is divided in three main sections: This document is divided in three main sections:
First, global goals and behaviour. First, global goals and behaviour.
Second, basic entities to understand the minimum concepts to use LibrePlan. Second, basic entities to understand the minimum concepts to use TASKPM.
Finally, complete processes description to create orders, projects, project planning, resources assignment, advance assignment and result extraction. Finally, complete processes description to create orders, projects, project planning, resources assignment, advance assignment and result extraction.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -53,7 +53,6 @@ clean:
$Q $(RM) -r pdf/ $Q $(RM) -r pdf/
$P clean html $P clean html
$Q $(RM) -r html/ $Q $(RM) -r html/
$Q $(RM) index.rst
# Copy CSS file # Copy CSS file
# #
@ -75,11 +74,11 @@ pdf/$(OUTPUT_BASE).rst: $(rst_srcs) docinfo
pdf/$(OUTPUT_BASE).pdf pdf/$(OUTPUT_BASE).ebook.pdf: $(png_images) pdf/$(OUTPUT_BASE).pdf pdf/$(OUTPUT_BASE).ebook.pdf: $(png_images)
# Index page creation for the HTML output # Index page creation for the HTML output
# # DISABLED: index.rst is now manually maintained for TASKPM customization
index.rst: $(rst_srcs) docinfo #index.rst: $(rst_srcs) docinfo
$P htmlindex $@ # $P htmlindex $@
$Q mkdir -p $(@D) # $Q mkdir -p $(@D)
$Q $(utildir)/doctool htmlindex --info=docinfo $(rst_srcs) > $@ # $Q $(utildir)/doctool htmlindex --info=docinfo $(rst_srcs) > $@
# Implicit rules # Implicit rules

View file

@ -10,7 +10,7 @@
</parent> </parent>
<artifactId>ganttzk</artifactId> <artifactId>ganttzk</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>LibrePlan ZK Components Module</name> <name>TASKPM ZK Components Module</name>
<profiles> <profiles>
<profile> <profile>

View file

@ -21,7 +21,7 @@
package org.zkoss.ganttz; package org.zkoss.ganttz;
import static org.zkoss.ganttz.i18n.I18nHelper._; import static org.zkoss.ganttz.i18n.I18nHelper.tr;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
@ -63,7 +63,7 @@ public class DependencyList extends XulElement implements AfterCompose {
boolean canBeAdded = context.changeType(chosen.getDependency(), type); boolean canBeAdded = context.changeType(chosen.getDependency(), type);
if ( !canBeAdded ) { if ( !canBeAdded ) {
warnUser(_("The specified dependency is not allowed")); warnUser(tr("The specified dependency is not allowed"));
} }
} }
@ -210,7 +210,7 @@ public class DependencyList extends XulElement implements AfterCompose {
MenuBuilder<DependencyComponent> contextMenuBuilder = MenuBuilder<DependencyComponent> contextMenuBuilder =
MenuBuilder.on(getPage(), getDependencyComponents()).item( MenuBuilder.on(getPage(), getDependencyComponents()).item(
_("Erase"), tr("Erase"),
"/common/img/ico_borrar.png", "/common/img/ico_borrar.png",
(chosen, event) -> context.removeDependency(chosen.getDependency())); (chosen, event) -> context.removeDependency(chosen.getDependency()));
@ -225,15 +225,15 @@ public class DependencyList extends XulElement implements AfterCompose {
MenuBuilder<DependencyComponent> contextMenuBuilder = MenuBuilder<DependencyComponent> contextMenuBuilder =
MenuBuilder.on(getPage(), getDependencyComponents()).item( MenuBuilder.on(getPage(), getDependencyComponents()).item(
_("Erase"), tr("Erase"),
"/common/img/ico_borrar.png", "/common/img/ico_borrar.png",
((chosen, event) -> context.removeDependency(chosen.getDependency()))); ((chosen, event) -> context.removeDependency(chosen.getDependency())));
contextMenuBuilder.item(_("Set End-Start"), null, new ChangeTypeAction(DependencyType.END_START)); contextMenuBuilder.item(tr("Set End-Start"), null, new ChangeTypeAction(DependencyType.END_START));
contextMenuBuilder.item(_("Set Start-Start"), null, new ChangeTypeAction(DependencyType.START_START)); contextMenuBuilder.item(tr("Set Start-Start"), null, new ChangeTypeAction(DependencyType.START_START));
contextMenuBuilder.item(_("Set End-End"), null, new ChangeTypeAction(DependencyType.END_END)); contextMenuBuilder.item(tr("Set End-End"), null, new ChangeTypeAction(DependencyType.END_END));
contextMenu = contextMenuBuilder.create(); contextMenu = contextMenuBuilder.create();

View file

@ -57,7 +57,7 @@ import org.zkoss.zul.Hlayout;
import org.zkoss.zul.Label; import org.zkoss.zul.Label;
import org.zkoss.zul.Treerow; import org.zkoss.zul.Treerow;
import static org.zkoss.ganttz.i18n.I18nHelper._; import static org.zkoss.ganttz.i18n.I18nHelper.tr;
/** /**
* Row composer for Tasks details Tree <br /> * Row composer for Tasks details Tree <br />
@ -268,16 +268,16 @@ public class LeftTasksTreeRow extends GenericForwardComposer {
if (dateTimeInTextbox.isAfter(maximum)) { if (dateTimeInTextbox.isAfter(maximum)) {
throw new WrongValueException( throw new WrongValueException(
comp, comp,
_("The date you entered is invalid") + ". " + tr("The date you entered is invalid") + ". " +
_("Please enter date not before") + " " + minimumYear + tr("Please enter date not before") + " " + minimumYear +
" " + _("and no later than") + " " + maximum.getYear()); " " + tr("and no later than") + " " + maximum.getYear());
} }
if (dateTimeInTextbox.isBefore(minimum)) { if (dateTimeInTextbox.isBefore(minimum)) {
throw new WrongValueException( throw new WrongValueException(
comp, comp,
_("The date you entered is invalid") + ". " + tr("The date you entered is invalid") + ". " +
_("Please enter date not before") + " " + minimumYear + tr("Please enter date not before") + " " + minimumYear +
" " + _("and no later than") + " " + maximum.getYear()); " " + tr("and no later than") + " " + maximum.getYear());
} }
} }
}; };

View file

@ -21,7 +21,7 @@
package org.zkoss.ganttz; package org.zkoss.ganttz;
import static org.zkoss.ganttz.i18n.I18nHelper._; import static org.zkoss.ganttz.i18n.I18nHelper.tr;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -323,7 +323,7 @@ public class Planner extends HtmlMacroComponent {
@Override @Override
public String getName() { public String getName() {
return _("increasing zoom"); return tr("increasing zoom");
} }
@Override @Override
@ -341,7 +341,7 @@ public class Planner extends HtmlMacroComponent {
LongOperationFeedback.execute(ganttPanel, new ILongOperation() { LongOperationFeedback.execute(ganttPanel, new ILongOperation() {
@Override @Override
public String getName() { public String getName() {
return _("decreasing zoom"); return tr("decreasing zoom");
} }
@Override @Override
@ -461,7 +461,7 @@ public class Planner extends HtmlMacroComponent {
((South) getFellow("graphics")).setOpen(this.visibleChart); ((South) getFellow("graphics")).setOpen(this.visibleChart);
if (!visibleChart) { if (!visibleChart) {
((South) getFellow("graphics")).setTitle(_("Graphics are disabled")); ((South) getFellow("graphics")).setTitle(tr("Graphics are disabled"));
} }
PROFILING_LOG.debug("it took doing the setup of components and adding them: " PROFILING_LOG.debug("it took doing the setup of components and adding them: "
@ -640,12 +640,12 @@ public class Planner extends HtmlMacroComponent {
context.hideCriticalPath(); context.hideCriticalPath();
diagramGraph.removePostGraphChangeListener(showCriticalPathOnChange); diagramGraph.removePostGraphChangeListener(showCriticalPathOnChange);
showCriticalPathButton.setSclass(PLANNER_COMMAND); showCriticalPathButton.setSclass(PLANNER_COMMAND);
showCriticalPathButton.setTooltiptext(_("Show critical path")); showCriticalPathButton.setTooltiptext(tr("Show critical path"));
} else { } else {
context.showCriticalPath(); context.showCriticalPath();
diagramGraph.addPostGraphChangeListener(showCriticalPathOnChange); diagramGraph.addPostGraphChangeListener(showCriticalPathOnChange);
showCriticalPathButton.setSclass(PLANNER_COMMAND + " clicked"); showCriticalPathButton.setSclass(PLANNER_COMMAND + " clicked");
showCriticalPathButton.setTooltiptext(_("Hide critical path")); showCriticalPathButton.setTooltiptext(tr("Hide critical path"));
} }
isShowingCriticalPath = !isShowingCriticalPath; isShowingCriticalPath = !isShowingCriticalPath;
@ -667,7 +667,7 @@ public class Planner extends HtmlMacroComponent {
context.hideAdvances(); context.hideAdvances();
diagramGraph.removePostGraphChangeListener(showAdvanceOnChange); diagramGraph.removePostGraphChangeListener(showAdvanceOnChange);
showAdvancesButton.setSclass(PLANNER_COMMAND); showAdvancesButton.setSclass(PLANNER_COMMAND);
showAdvancesButton.setTooltiptext(_("Show progress")); showAdvancesButton.setTooltiptext(tr("Show progress"));
if ( progressTypesCombo.getItemCount() > 0 ) { if ( progressTypesCombo.getItemCount() > 0 ) {
progressTypesCombo.setSelectedIndex(0); progressTypesCombo.setSelectedIndex(0);
@ -676,7 +676,7 @@ public class Planner extends HtmlMacroComponent {
context.showAdvances(); context.showAdvances();
diagramGraph.addPostGraphChangeListener(showAdvanceOnChange); diagramGraph.addPostGraphChangeListener(showAdvanceOnChange);
showAdvancesButton.setSclass(PLANNER_COMMAND + " clicked"); showAdvancesButton.setSclass(PLANNER_COMMAND + " clicked");
showAdvancesButton.setTooltiptext(_("Hide progress")); showAdvancesButton.setTooltiptext(tr("Hide progress"));
} }
isShowingAdvances = !isShowingAdvances; isShowingAdvances = !isShowingAdvances;
@ -690,12 +690,12 @@ public class Planner extends HtmlMacroComponent {
context.hideReportedHours(); context.hideReportedHours();
diagramGraph.removePostGraphChangeListener(showReportedHoursOnChange); diagramGraph.removePostGraphChangeListener(showReportedHoursOnChange);
showReportedHoursButton.setSclass(PLANNER_COMMAND); showReportedHoursButton.setSclass(PLANNER_COMMAND);
showReportedHoursButton.setTooltiptext(_("Show reported hours")); showReportedHoursButton.setTooltiptext(tr("Show reported hours"));
} else { } else {
context.showReportedHours(); context.showReportedHours();
diagramGraph.addPostGraphChangeListener(showReportedHoursOnChange); diagramGraph.addPostGraphChangeListener(showReportedHoursOnChange);
showReportedHoursButton.setSclass(PLANNER_COMMAND + " clicked"); showReportedHoursButton.setSclass(PLANNER_COMMAND + " clicked");
showReportedHoursButton.setTooltiptext(_("Hide reported hours")); showReportedHoursButton.setTooltiptext(tr("Hide reported hours"));
} }
isShowingReportedHours = !isShowingReportedHours; isShowingReportedHours = !isShowingReportedHours;
@ -709,12 +709,12 @@ public class Planner extends HtmlMacroComponent {
context.hideMoneyCostBar(); context.hideMoneyCostBar();
diagramGraph.removePostGraphChangeListener(showMoneyCostBarOnChange); diagramGraph.removePostGraphChangeListener(showMoneyCostBarOnChange);
showMoneyCostBarButton.setSclass(PLANNER_COMMAND); showMoneyCostBarButton.setSclass(PLANNER_COMMAND);
showMoneyCostBarButton.setTooltiptext(_("Show money cost bar")); showMoneyCostBarButton.setTooltiptext(tr("Show money cost bar"));
} else { } else {
context.showMoneyCostBar(); context.showMoneyCostBar();
diagramGraph.addPostGraphChangeListener(showMoneyCostBarOnChange); diagramGraph.addPostGraphChangeListener(showMoneyCostBarOnChange);
showMoneyCostBarButton.setSclass(PLANNER_COMMAND + " clicked"); showMoneyCostBarButton.setSclass(PLANNER_COMMAND + " clicked");
showMoneyCostBarButton.setTooltiptext(_("Hide money cost bar")); showMoneyCostBarButton.setTooltiptext(tr("Hide money cost bar"));
} }
isShowingMoneyCostBar = !isShowingMoneyCostBar; isShowingMoneyCostBar = !isShowingMoneyCostBar;

View file

@ -21,7 +21,7 @@
package org.zkoss.ganttz; package org.zkoss.ganttz;
import static org.zkoss.ganttz.i18n.I18nHelper._; import static org.zkoss.ganttz.i18n.I18nHelper.tr;
import org.apache.commons.lang3.math.Fraction; import org.apache.commons.lang3.math.Fraction;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
@ -295,7 +295,7 @@ public class TaskList extends XulElement implements AfterCompose {
if ( disabilityConfiguration.isAddingDependenciesEnabled() ) { if ( disabilityConfiguration.isAddingDependenciesEnabled() ) {
menuBuilder.item( menuBuilder.item(
_("Add Dependency"), "/common/img/ico_dependency.png", tr("Add Dependency"), "/common/img/ico_dependency.png",
(chosen, event) -> chosen.addDependency()); (chosen, event) -> chosen.addDependency());
} }

View file

@ -53,16 +53,16 @@ public class TimeLineRole<T> {
*/ */
public enum TimeLineRoleEnum { public enum TimeLineRoleEnum {
NONE(_("None")), NONE(tr("None")),
WORKER(_("Worker")), WORKER(tr("Worker")),
ORDER(_("Project")), ORDER(tr("Project")),
TASK(_("Task")) { TASK(tr("Task")) {
@Override @Override
public boolean isVisibleScheduled() { public boolean isVisibleScheduled() {
return true; return true;
} }
}, },
CRITERION(_("Criterion")); CRITERION(tr("Criterion"));
private String name; private String name;
@ -73,7 +73,7 @@ public class TimeLineRole<T> {
/** /**
* Forces to mark the string as needing translation. * Forces to mark the string as needing translation.
*/ */
private static String _(String string) { private static String tr(String string) {
return string; return string;
} }
@ -91,7 +91,7 @@ public class TimeLineRole<T> {
@Override @Override
public String toString() { public String toString() {
return _(this.name); return tr(this.name);
} }
public boolean isVisibleScheduled() { public boolean isVisibleScheduled() {

View file

@ -57,27 +57,27 @@ public class I18nHelper {
* @param str * @param str
* @return Text depends on locale * @return Text depends on locale
*/ */
public static String _(String str) { public static String tr(String str) {
return getI18n().tr(str); return getI18n().tr(str);
} }
public static String _(String text, Object o1) { public static String tr(String text, Object o1) {
return getI18n().tr(text, o1); return getI18n().tr(text, o1);
} }
public static String _(String text, Object o1, Object o2) { public static String tr(String text, Object o1, Object o2) {
return getI18n().tr(text, o1, o2); return getI18n().tr(text, o1, o2);
} }
public static String _(String text, Object o1, Object o2, Object o3) { public static String tr(String text, Object o1, Object o2, Object o3) {
return getI18n().tr(text, o1, o2, o3); return getI18n().tr(text, o1, o2, o3);
} }
public static String _(String text, Object o1, Object o2, Object o3, Object o4) { public static String tr(String text, Object o1, Object o2, Object o3, Object o4) {
return getI18n().tr(text, o1, o2, o3, o4); return getI18n().tr(text, o1, o2, o3, o4);
} }
public static String _(String text, Object[] objects) { public static String tr(String text, Object[] objects) {
return getI18n().tr(text, objects); return getI18n().tr(text, objects);
} }

View file

@ -21,7 +21,7 @@
package org.zkoss.ganttz.resourceload; package org.zkoss.ganttz.resourceload;
import static org.zkoss.ganttz.i18n.I18nHelper._; import static org.zkoss.ganttz.i18n.I18nHelper.tr;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -144,7 +144,7 @@ public class ResourceLoadComponent extends XulElement {
MenuBuilder<Div> menuBuilder = MenuBuilder.on(getPage(), divs); MenuBuilder<Div> menuBuilder = MenuBuilder.on(getPage(), divs);
menuBuilder.item( menuBuilder.item(
_("See resource allocation"), tr("See resource allocation"),
"/common/img/ico_allocation.png", "/common/img/ico_allocation.png",
(chosen, event) -> schedule(loadLine)); (chosen, event) -> schedule(loadLine));
@ -181,7 +181,7 @@ public class ResourceLoadComponent extends XulElement {
Div result = new Div(); Div result = new Div();
result.setClass(String.format("taskassignmentinterval %s", loadPeriod.getLoadLevel().getCategory())); result.setClass(String.format("taskassignmentinterval %s", loadPeriod.getLoadLevel().getCategory()));
String load = _("Load: {0}%", loadPeriod.getLoadLevel().getPercentage()) + ", "; String load = tr("Load: {0}%", loadPeriod.getLoadLevel().getPercentage()) + ", ";
if (loadPeriod.getLoadLevel().getPercentage() == Integer.MAX_VALUE) { if (loadPeriod.getLoadLevel().getPercentage() == Integer.MAX_VALUE) {
load = ""; load = "";
@ -189,7 +189,7 @@ public class ResourceLoadComponent extends XulElement {
result.setTooltiptext( result.setTooltiptext(
load + load +
_("available effort: {0}, assigned effort: {1}", tr("available effort: {0}, assigned effort: {1}",
loadPeriod.getAvailableEffort(), loadPeriod.getAvailableEffort(),
loadPeriod.getAssignedEffort())); loadPeriod.getAssignedEffort()));

View file

@ -21,7 +21,7 @@
package org.zkoss.ganttz.resourceload; package org.zkoss.ganttz.resourceload;
import static org.zkoss.ganttz.i18n.I18nHelper._; import static org.zkoss.ganttz.i18n.I18nHelper.tr;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -167,7 +167,7 @@ public class ResourceLoadLeftPane extends HtmlMacroComponent {
buttonPlan.setSclass("icono"); buttonPlan.setSclass("icono");
buttonPlan.setImage("/common/img/ico_planificador1.png"); buttonPlan.setImage("/common/img/ico_planificador1.png");
buttonPlan.setHoverImage("/common/img/ico_planificador.png"); buttonPlan.setHoverImage("/common/img/ico_planificador.png");
buttonPlan.setTooltiptext(_("See scheduling")); buttonPlan.setTooltiptext(tr("See scheduling"));
buttonPlan.addEventListener("onClick", event -> schedule(taskLine)); buttonPlan.addEventListener("onClick", event -> schedule(taskLine));
cell.appendChild(buttonPlan); cell.appendChild(buttonPlan);

View file

@ -21,7 +21,7 @@
package org.zkoss.ganttz.resourceload; package org.zkoss.ganttz.resourceload;
import static org.zkoss.ganttz.i18n.I18nHelper._; import static org.zkoss.ganttz.i18n.I18nHelper.tr;
import java.util.List; import java.util.List;
@ -83,9 +83,9 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
private WeakReferencedListeners<IFilterChangedListener> zoomListeners = WeakReferencedListeners.create(); private WeakReferencedListeners<IFilterChangedListener> zoomListeners = WeakReferencedListeners.create();
private final String FILTER_RESOURCES = _("Resources"); private final String FILTER_RESOURCES = tr("Resources");
private final String FILTER_CRITERIA = _("Generic allocation criteria"); private final String FILTER_CRITERIA = tr("Generic allocation criteria");
private final String FILTER_BY_NAME_COMBO_COMPONENT = "filterByNameCombo"; private final String FILTER_BY_NAME_COMBO_COMPONENT = "filterByNameCombo";
@ -156,10 +156,10 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
public void setFilter(String filterBy) { public void setFilter(String filterBy) {
if ( filterBy.equals(FILTER_RESOURCES) ) { if ( filterBy.equals(FILTER_RESOURCES) ) {
this.filterbyResources = true; this.filterbyResources = true;
this.feedBackMessage = _("showing resources"); this.feedBackMessage = tr("showing resources");
} else { } else {
this.filterbyResources = false; this.filterbyResources = false;
this.feedBackMessage = _("showing criteria"); this.feedBackMessage = tr("showing criteria");
} }
refreshNameFilter = true; refreshNameFilter = true;
@ -395,7 +395,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
((South) getFellow("graphics")).setOpen(this.visibleChart); ((South) getFellow("graphics")).setOpen(this.visibleChart);
if (!visibleChart) { if (!visibleChart) {
((South) getFellow("graphics")).setTitle(_("Graphics are disabled")); ((South) getFellow("graphics")).setTitle(tr("Graphics are disabled"));
} }
savePreviousData(); savePreviousData();
@ -471,8 +471,8 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
} }
Comboitem lastItem = new Comboitem(); Comboitem lastItem = new Comboitem();
lastItem.setLabel(_("All")); lastItem.setLabel(tr("All"));
lastItem.setDescription(_("Show all elements")); lastItem.setDescription(tr("Show all elements"));
lastItem.setValue(-1); lastItem.setValue(-1);
filterByNameCombo.appendChild(lastItem); filterByNameCombo.appendChild(lastItem);
@ -507,7 +507,7 @@ public class ResourcesLoadPanel extends HtmlMacroComponent {
if ( paginationType != PaginationType.NONE ) { if ( paginationType != PaginationType.NONE ) {
this.filterByNamePosition = filterByNamePosition; this.filterByNamePosition = filterByNamePosition;
this.lastSelectedName = comboByName.getSelectedIndex(); this.lastSelectedName = comboByName.getSelectedIndex();
this.feedBackMessage = _("filtering by name"); this.feedBackMessage = tr("filtering by name");
changeNameFilterWithFeedback(); changeNameFilterWithFeedback();
} }

View file

@ -21,7 +21,7 @@
package org.zkoss.ganttz.timetracker; package org.zkoss.ganttz.timetracker;
import static org.zkoss.ganttz.i18n.I18nHelper._; import static org.zkoss.ganttz.i18n.I18nHelper.tr;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
@ -226,7 +226,7 @@ public class TimeTracker {
@Override @Override
public String getName() { public String getName() {
return _("changing zoom"); return tr("changing zoom");
} }
}); });
} }

View file

@ -31,7 +31,7 @@ import org.joda.time.LocalDate;
*/ */
public enum ZoomLevel { public enum ZoomLevel {
DETAIL_ONE(_("Year")) { DETAIL_ONE(tr("Year")) {
@Override @Override
public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) { public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) {
return new DetailOneTimeTrackerState(firstLevel, secondLevel); return new DetailOneTimeTrackerState(firstLevel, secondLevel);
@ -43,7 +43,7 @@ public enum ZoomLevel {
} }
}, },
DETAIL_TWO(_("Quarter")) { DETAIL_TWO(tr("Quarter")) {
@Override @Override
public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) { public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) {
return new DetailTwoTimeTrackerState(firstLevel, secondLevel); return new DetailTwoTimeTrackerState(firstLevel, secondLevel);
@ -55,7 +55,7 @@ public enum ZoomLevel {
} }
}, },
DETAIL_THREE(_("Month")) { DETAIL_THREE(tr("Month")) {
@Override @Override
public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) { public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) {
return new DetailThreeTimeTrackerState(firstLevel, secondLevel); return new DetailThreeTimeTrackerState(firstLevel, secondLevel);
@ -67,7 +67,7 @@ public enum ZoomLevel {
} }
}, },
DETAIL_FOUR(_("Week")) { DETAIL_FOUR(tr("Week")) {
@Override @Override
public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) { public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) {
return new DetailFourTimeTrackerState(firstLevel, secondLevel); return new DetailFourTimeTrackerState(firstLevel, secondLevel);
@ -79,7 +79,7 @@ public enum ZoomLevel {
} }
}, },
DETAIL_FIVE(_("Day")) { DETAIL_FIVE(tr("Day")) {
@Override @Override
public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) { public TimeTrackerState getTimeTrackerState(IDetailItemModifier firstLevel, IDetailItemModifier secondLevel) {
return new DetailFiveTimeTrackerState(firstLevel, secondLevel); return new DetailFiveTimeTrackerState(firstLevel, secondLevel);
@ -100,7 +100,7 @@ public enum ZoomLevel {
/** /**
* Forces to mark the string as needing translation. * Forces to mark the string as needing translation.
*/ */
private static String _(String string) { private static String tr(String string) {
return string; return string;
} }
@ -129,7 +129,7 @@ public enum ZoomLevel {
@Override @Override
public String toString() { public String toString() {
return _(internalName); return tr(internalName);
} }
public static ZoomLevel getFromString(String zoomLevelParameter) { public static ZoomLevel getFromString(String zoomLevelParameter) {

View file

@ -20,7 +20,7 @@
--> -->
<?xel-method prefix="ganttzk_i18n" name="_" class="org.zkoss.ganttz.i18n.I18nHelper" <?xel-method prefix="ganttzk_i18n" name="_" class="org.zkoss.ganttz.i18n.I18nHelper"
signature="java.lang.String _(java.lang.String name)" ?> signature="java.lang.String tr(java.lang.String name)" ?>
<div> <div>
<tree id="tasksTree" fixedLayout="true" sclass="taskTreeCols" hflex="1" > <tree id="tasksTree" fixedLayout="true" sclass="taskTreeCols" hflex="1" >

View file

@ -21,7 +21,7 @@
<zk> <zk>
<?component name="button" extends="button" mold="trendy"?> <?component name="button" extends="button" mold="trendy"?>
<?xel-method prefix="ganttzk_i18n" name="_" class="org.zkoss.ganttz.i18n.I18nHelper" <?xel-method prefix="ganttzk_i18n" name="_" class="org.zkoss.ganttz.i18n.I18nHelper"
signature="java.lang.String _(java.lang.String name)" ?> signature="java.lang.String tr(java.lang.String name)" ?>
<zscript> <zscript>
<![CDATA[ <![CDATA[

View file

@ -20,7 +20,7 @@
--> -->
<?xel-method prefix="ganttzk_i18n" name="_" class="org.zkoss.ganttz.i18n.I18nHelper" <?xel-method prefix="ganttzk_i18n" name="_" class="org.zkoss.ganttz.i18n.I18nHelper"
signature="java.lang.String _(java.lang.String name)" ?> signature="java.lang.String tr(java.lang.String name)" ?>
<zk> <zk>
<zscript> <zscript>

View file

@ -10,7 +10,7 @@
</parent> </parent>
<artifactId>libreplan-business</artifactId> <artifactId>libreplan-business</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>LibrePlan Business Module</name> <name>TASKPM Business Module</name>
<dependencies> <dependencies>
<!-- Gettext commons --> <!-- Gettext commons -->
@ -51,6 +51,12 @@
<version>3.0.0</version> <version>3.0.0</version>
</dependency> </dependency>
<!-- Javax Annotation API (for @PostConstruct, removed from JDK 11+) -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
<!-- Usertype.Core --> <!-- Usertype.Core -->
<dependency> <dependency>
<groupId>org.jadira.usertype</groupId> <groupId>org.jadira.usertype</groupId>

View file

@ -21,7 +21,7 @@
package org.libreplan.business.advance.entities; package org.libreplan.business.advance.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -175,14 +175,14 @@ public class AdvanceType extends BaseEntity implements IHumanIdentifiable{
public String getType() { public String getType() {
if ( isUpdatable() ) { if ( isUpdatable() ) {
return _("User"); return tr("User");
} }
if ( isQualityForm() ) { if ( isQualityForm() ) {
return _("Quality form"); return tr("Quality form");
} }
return _("Predefined"); return tr("Predefined");
} }
public boolean isPrecisionValid(BigDecimal precision) { public boolean isPrecisionValid(BigDecimal precision) {

View file

@ -21,7 +21,7 @@
package org.libreplan.business.calendars.entities; package org.libreplan.business.calendars.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -144,7 +144,7 @@ public class CalendarExceptionType extends IntegrationEntity implements IHumanId
} }
public String getOverAssignableStr() { public String getOverAssignableStr() {
return isOverAssignableWithoutLimit() ? _("Yes") : _("No"); return isOverAssignableWithoutLimit() ? tr("Yes") : tr("No");
} }
public EffortDuration getDuration() { public EffortDuration getDuration() {

View file

@ -19,7 +19,7 @@
package org.libreplan.business.calendars.entities; package org.libreplan.business.calendars.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Enum representing the possible colors to choose for a {@link CalendarExceptionType}. * Enum representing the possible colors to choose for a {@link CalendarExceptionType}.
@ -27,15 +27,15 @@ import static org.libreplan.business.i18n.I18nHelper._;
* @author Manuel Rego Casasnovas <rego@igalia.com> * @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */
public enum CalendarExceptionTypeColor { public enum CalendarExceptionTypeColor {
DEFAULT(_("red (default)"), "#FF3333", "#FF9999"), DEFAULT(tr("red (default)"), "#FF3333", "#FF9999"),
GREEN(_("green"),"#2ee62e", "#8ae68a"), GREEN(tr("green"),"#2ee62e", "#8ae68a"),
BLUE(_("blue"), "#3333FF", "#9999FF"), BLUE(tr("blue"), "#3333FF", "#9999FF"),
CYAN(_("cyan"), "#33FFFF", "#99FFFF"), CYAN(tr("cyan"), "#33FFFF", "#99FFFF"),
MAGENTA(_("magenta"), "#FF33FF", "#FF99FF"), MAGENTA(tr("magenta"), "#FF33FF", "#FF99FF"),
YELLOW(_("yellow"), "#e6e62e", "#e6e6a1"), YELLOW(tr("yellow"), "#e6e62e", "#e6e6a1"),
BLACK(_("black"), "#333333", "#999999"), BLACK(tr("black"), "#333333", "#999999"),
ORANGE(_("orange"), "#ffb733", "#ffdb99"), ORANGE(tr("orange"), "#ffb733", "#ffdb99"),
PURPLE(_("purple"), "#801a80", "#b38eb3"); PURPLE(tr("purple"), "#801a80", "#b38eb3");
private final String name; private final String name;

View file

@ -19,7 +19,7 @@
package org.libreplan.business.calendars.entities; package org.libreplan.business.calendars.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -170,7 +170,7 @@ public class Capacity {
public String getExtraEffortString() { public String getExtraEffortString() {
if (getAllowedExtraEffort() == null) { if (getAllowedExtraEffort() == null) {
return _("unlimited"); return tr("unlimited");
} }
return asString(getAllowedExtraEffort()); return asString(getAllowedExtraEffort());
} }

View file

@ -72,7 +72,7 @@ public class EntitySequenceDAO extends GenericDAOHibernate<EntitySequence, Long>
public void remove(final EntitySequence entitySequence) throws InstanceNotFoundException, IllegalArgumentException { public void remove(final EntitySequence entitySequence) throws InstanceNotFoundException, IllegalArgumentException {
if ( entitySequence.getLastValue() > 0 ) { if ( entitySequence.getLastValue() > 0 ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
I18nHelper._("Entity Sequence cannot be deleted. Entity Sequence already in use")); I18nHelper.tr("Entity Sequence cannot be deleted. Entity Sequence already in use"));
} }
remove(entitySequence.getId()); remove(entitySequence.getId());

View file

@ -19,7 +19,7 @@
package org.libreplan.business.common.entities; package org.libreplan.business.common.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.joda.time.Months; import org.joda.time.Months;
@ -32,7 +32,7 @@ import org.joda.time.Weeks;
*/ */
public enum PersonalTimesheetsPeriodicityEnum { public enum PersonalTimesheetsPeriodicityEnum {
MONTHLY(_("Monthly")) { MONTHLY(tr("Monthly")) {
@Override @Override
public LocalDate getStart(LocalDate date) { public LocalDate getStart(LocalDate date) {
return date.dayOfMonth().withMinimumValue(); return date.dayOfMonth().withMinimumValue();
@ -63,7 +63,7 @@ public enum PersonalTimesheetsPeriodicityEnum {
return getStart(date).plusMonths(1); return getStart(date).plusMonths(1);
} }
}, },
TWICE_MONTHLY(_("Twice-monthly")) { TWICE_MONTHLY(tr("Twice-monthly")) {
@Override @Override
public LocalDate getStart(LocalDate date) { public LocalDate getStart(LocalDate date) {
if (date.getDayOfMonth() <= 15) { if (date.getDayOfMonth() <= 15) {
@ -120,7 +120,7 @@ public enum PersonalTimesheetsPeriodicityEnum {
} }
} }
}, },
WEEKLY(_("Weekly")) { WEEKLY(tr("Weekly")) {
@Override @Override
public LocalDate getStart(LocalDate date) { public LocalDate getStart(LocalDate date) {
return date.dayOfWeek().withMinimumValue(); return date.dayOfWeek().withMinimumValue();

View file

@ -19,7 +19,7 @@
package org.libreplan.business.common.entities; package org.libreplan.business.common.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Simply class to keep constants of {@link ConnectorProperty properties} for LibrePlan {@link Connector connectors}. * Simply class to keep constants of {@link ConnectorProperty properties} for LibrePlan {@link Connector connectors}.
@ -31,20 +31,20 @@ import static org.libreplan.business.i18n.I18nHelper._;
public class PredefinedConnectorProperties { public class PredefinedConnectorProperties {
// Generic // Generic
public static String ACTIVATED = _("Activated"); public static String ACTIVATED = tr("Activated");
public static String SERVER_URL = _("Server URL"); public static String SERVER_URL = tr("Server URL");
public static String USERNAME = _("Username"); public static String USERNAME = tr("Username");
public static String PASSWORD = _("Password"); public static String PASSWORD = tr("Password");
// Specific for Tim // Specific for Tim
public static String TIM_NR_DAYS_TIMESHEET = _("Number of days timesheet to Tim"); public static String TIM_NR_DAYS_TIMESHEET = tr("Number of days timesheet to Tim");
public static String TIM_NR_DAYS_ROSTER = _("Number of days roster from Tim"); public static String TIM_NR_DAYS_ROSTER = tr("Number of days roster from Tim");
public static String TIM_PRODUCTIVITY_FACTOR = _("Productivity factor"); public static String TIM_PRODUCTIVITY_FACTOR = tr("Productivity factor");
public static String TIM_DEPARTAMENTS_IMPORT_ROSTER = _("Department IDs to import toster"); public static String TIM_DEPARTAMENTS_IMPORT_ROSTER = tr("Department IDs to import toster");
// Specific for JIRA // Specific for JIRA
public static String JIRA_LABELS = _("JIRA labels: comma-separated list of labels or URL"); public static String JIRA_LABELS = tr("JIRA labels: comma-separated list of labels or URL");
public static String JIRA_HOURS_TYPE = _("Hours type"); public static String JIRA_HOURS_TYPE = tr("Hours type");
/** /**
* Code prefix for different entities integrated with JIRA. * Code prefix for different entities integrated with JIRA.
@ -52,11 +52,11 @@ public class PredefinedConnectorProperties {
public static final String JIRA_CODE_PREFIX = "JIRA-"; public static final String JIRA_CODE_PREFIX = "JIRA-";
// Specific for E-mail // Specific for E-mail
public static String PROTOCOL = _("Protocol"); public static String PROTOCOL = tr("Protocol");
public static String HOST = _("Host"); public static String HOST = tr("Host");
public static String PORT = _("Port"); public static String PORT = tr("Port");
public static String EMAIL_SENDER = _("From address (no reply)"); public static String EMAIL_SENDER = tr("From address (no reply)");
public static String EMAIL_USERNAME = _("Username (optional)"); public static String EMAIL_USERNAME = tr("Username (optional)");
public static String EMAIL_PASSWORD = _("Password (optional)"); public static String EMAIL_PASSWORD = tr("Password (optional)");
} }

View file

@ -21,7 +21,7 @@
package org.libreplan.business.common.entities; package org.libreplan.business.common.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -33,10 +33,10 @@ import java.util.List;
*/ */
public enum ProgressType { public enum ProgressType {
SPREAD_PROGRESS(_("Spreading progress")), SPREAD_PROGRESS(tr("Spreading progress")),
ALL_NUMHOURS(_("Progress with all tasks by hours")), ALL_NUMHOURS(tr("Progress with all tasks by hours")),
CRITICAL_PATH_NUMHOURS(_("Progress with critical path tasks by hours")), CRITICAL_PATH_NUMHOURS(tr("Progress with critical path tasks by hours")),
CRITICAL_PATH_DURATION(_("Progress with critical path tasks by duration")); CRITICAL_PATH_DURATION(tr("Progress with critical path tasks by duration"));
private String value; private String value;

View file

@ -0,0 +1,21 @@
package org.libreplan.business.common.hibernate;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.service.ServiceRegistry;
import org.jadira.usertype.dateandtime.joda.PersistentDateTime;
import org.jadira.usertype.dateandtime.joda.PersistentLocalDate;
import org.jadira.usertype.dateandtime.joda.PersistentLocalTime;
/**
* Registers Joda-Time types for Hibernate.
*/
public class JodaTypeContributor implements TypeContributor {
@Override
public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
typeContributions.contributeType(new PersistentLocalDate(), "org.joda.time.LocalDate");
typeContributions.contributeType(new PersistentDateTime(), "org.joda.time.DateTime");
typeContributions.contributeType(new PersistentLocalTime(), "org.joda.time.LocalTime");
}
}

View file

@ -0,0 +1,103 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2024 LibrePlan Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/
package org.libreplan.business.common.hibernate;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
import org.joda.time.LocalTime;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
/**
* Hibernate 5.6 UserType for storing Joda LocalTime as milliseconds integer.
* Replaces org.jadira.usertype.dateandtime.joda.PersistentLocalTimeAsMillisInteger
*/
public class LocalTimeAsMillisIntegerType implements UserType {
private static final int[] SQL_TYPES = { Types.INTEGER };
@Override
public int[] sqlTypes() {
return SQL_TYPES;
}
@Override
public Class<?> returnedClass() {
return LocalTime.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == y) return true;
if (x == null || y == null) return false;
return x.equals(y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return x == null ? 0 : x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
throws HibernateException, SQLException {
int millis = rs.getInt(names[0]);
if (rs.wasNull()) {
return null;
}
return LocalTime.fromMillisOfDay(millis);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.INTEGER);
} else {
st.setInt(index, ((LocalTime) value).getMillisOfDay());
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
// LocalTime is immutable
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return value == null ? null : ((LocalTime) value).getMillisOfDay();
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
if (cached == null) {
return null;
}
return LocalTime.fromMillisOfDay((Integer) cached);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}

View file

@ -21,7 +21,7 @@
package org.libreplan.business.costcategories.entities; package org.libreplan.business.costcategories.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
@ -130,7 +130,7 @@ public class CostCategory extends IntegrationEntity implements IHumanIdentifiabl
.getInitDate().compareTo(endDate) <= 0)) { .getInitDate().compareTo(endDate) <= 0)) {
throw ValidationException throw ValidationException
.invalidValueException( .invalidValueException(
_("Two Hour Cost of the same type overlap in time"), tr("Two Hour Cost of the same type overlap in time"),
listElement); listElement);
} else if ((endDate != null && listElement.getEndDate() != null) } else if ((endDate != null && listElement.getEndDate() != null)
&& ((listElement.getEndDate().compareTo(initDate) >= 0 && listElement && ((listElement.getEndDate().compareTo(initDate) >= 0 && listElement
@ -139,7 +139,7 @@ public class CostCategory extends IntegrationEntity implements IHumanIdentifiabl
.getInitDate().compareTo(endDate) <= 0))) { .getInitDate().compareTo(endDate) <= 0))) {
throw ValidationException throw ValidationException
.invalidValueException( .invalidValueException(
_("Two Hour Cost of the same type overlap in time"), tr("Two Hour Cost of the same type overlap in time"),
listElement); listElement);
} }
} }
@ -159,7 +159,7 @@ public class CostCategory extends IntegrationEntity implements IHumanIdentifiabl
if (endDate == null && costCategory.getEndDate() == null) { if (endDate == null && costCategory.getEndDate() == null) {
throw ValidationException throw ValidationException
.invalidValueException( .invalidValueException(
_("Some cost category assignments overlap in time"), tr("Some cost category assignments overlap in time"),
costCategory); costCategory);
} else if ((endDate == null && costCategory.getEndDate() } else if ((endDate == null && costCategory.getEndDate()
.compareTo(initDate) >= 0) .compareTo(initDate) >= 0)
@ -167,7 +167,7 @@ public class CostCategory extends IntegrationEntity implements IHumanIdentifiabl
.getInitDate().compareTo(endDate) <= 0)) { .getInitDate().compareTo(endDate) <= 0)) {
throw ValidationException throw ValidationException
.invalidValueException( .invalidValueException(
_("Some cost category assignments overlap in time"), tr("Some cost category assignments overlap in time"),
costCategory); costCategory);
} else if ((endDate != null && costCategory.getEndDate() != null) } else if ((endDate != null && costCategory.getEndDate() != null)
&& ((costCategory.getEndDate().compareTo(initDate) >= 0 && // (1) && ((costCategory.getEndDate().compareTo(initDate) >= 0 && // (1)
@ -190,7 +190,7 @@ public class CostCategory extends IntegrationEntity implements IHumanIdentifiabl
// endDate] // endDate]
throw ValidationException throw ValidationException
.invalidValueException( .invalidValueException(
_("Some cost category assignments overlap in time"), tr("Some cost category assignments overlap in time"),
costCategory); costCategory);
} }
} }

View file

@ -19,24 +19,24 @@
package org.libreplan.business.email.entities; package org.libreplan.business.email.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Available E-mail templates. * Available E-mail templates.
* *
* TEMPLATE_N(_("Template N")) - for i18n * TEMPLATE_N(tr("Template N")) - for i18n
* TEMPLATE_A("Template A") - for general use (no internationalizing) * TEMPLATE_A("Template A") - for general use (no internationalizing)
* *
* @author Vova Perebykivskyi <vova@libreplan-enterprise.com> * @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
*/ */
public enum EmailTemplateEnum { public enum EmailTemplateEnum {
TEMPLATE_TASK_ASSIGNED_TO_RESOURCE(_("Task assigned to resource")), TEMPLATE_TASK_ASSIGNED_TO_RESOURCE(tr("Task assigned to resource")),
TEMPLATE_RESOURCE_REMOVED_FROM_TASK(_("Resource removed from task")), TEMPLATE_RESOURCE_REMOVED_FROM_TASK(tr("Resource removed from task")),
TEMPLATE_MILESTONE_REACHED(_("Milestone reached")), TEMPLATE_MILESTONE_REACHED(tr("Milestone reached")),
TEMPLATE_TODAY_TASK_SHOULD_START(_("Task should start")), TEMPLATE_TODAY_TASK_SHOULD_START(tr("Task should start")),
TEMPLATE_TODAY_TASK_SHOULD_FINISH(_("Task should finish")), TEMPLATE_TODAY_TASK_SHOULD_FINISH(tr("Task should finish")),
TEMPLATE_ENTER_DATA_IN_TIMESHEET(_("Enter data in timesheet")); TEMPLATE_ENTER_DATA_IN_TIMESHEET(tr("Enter data in timesheet"));
private final String templateType; private final String templateType;

View file

@ -19,7 +19,7 @@
package org.libreplan.business.externalcompanies.entities; package org.libreplan.business.externalcompanies.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Enum for specified the type of {@link CustomerCommunication} * Enum for specified the type of {@link CustomerCommunication}
@ -28,10 +28,10 @@ import static org.libreplan.business.i18n.I18nHelper._;
*/ */
public enum CommunicationType { public enum CommunicationType {
NEW_PROJECT(_("New project")), NEW_PROJECT(tr("New project")),
PROGRESS_UPDATE(_("Progress Update")), PROGRESS_UPDATE(tr("Progress Update")),
UPDATE_DELIVERING_DATE(_("Update Delivering Date")), UPDATE_DELIVERING_DATE(tr("Update Delivering Date")),
END_DATE_UPDATE(_("End date update")); END_DATE_UPDATE(tr("End date update"));
private String description; private String description;

View file

@ -41,7 +41,7 @@ public class I18nHelper {
* @param text * @param text
* @return Text depends on locale * @return Text depends on locale
*/ */
public static String _(String text) { public static String tr(String text) {
return text; return text;
} }

View file

@ -1,6 +1,6 @@
package org.libreplan.business.logs.entities; package org.libreplan.business.logs.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Defines PROBLEM_OR_CONCERN, REQUEST_FOR_CHANGE, OFF_SPECIFICATION enums * Defines PROBLEM_OR_CONCERN, REQUEST_FOR_CHANGE, OFF_SPECIFICATION enums
@ -10,7 +10,7 @@ import static org.libreplan.business.i18n.I18nHelper._;
* @author Misha Gozhda <misha@libreplan-enterprise.com> * @author Misha Gozhda <misha@libreplan-enterprise.com>
*/ */
public enum IssueTypeEnum { public enum IssueTypeEnum {
PROBLEM_OR_CONCERN(_("Problem or concern")), REQUEST_FOR_CHANGE(_("Request for change")), OFF_SPECIFICATION(_("Off specification")); PROBLEM_OR_CONCERN(tr("Problem or concern")), REQUEST_FOR_CHANGE(tr("Request for change")), OFF_SPECIFICATION(tr("Off specification"));
private final String issueTypeEnum; private final String issueTypeEnum;

View file

@ -18,7 +18,7 @@
*/ */
package org.libreplan.business.logs.entities; package org.libreplan.business.logs.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
@ -29,7 +29,7 @@ import static org.libreplan.business.i18n.I18nHelper._;
*/ */
public enum LowMediumHighEnum { public enum LowMediumHighEnum {
LOW(_("Low")), MEDIUM(_("Medium")), HIGH(_("High")); LOW(tr("Low")), MEDIUM(tr("Medium")), HIGH(tr("High"));
private final String lowMediumHighEnum; private final String lowMediumHighEnum;

View file

@ -1,5 +1,5 @@
package org.libreplan.business.logs.entities; package org.libreplan.business.logs.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Defines ZERO, ONE, TWO, THREE, FOUR, SIX, NINE * Defines ZERO, ONE, TWO, THREE, FOUR, SIX, NINE
* to be used as data type in * to be used as data type in
@ -8,7 +8,7 @@ import static org.libreplan.business.i18n.I18nHelper._;
* @author Misha Gozhda <misha@libreplan-enterprise.com> * @author Misha Gozhda <misha@libreplan-enterprise.com>
*/ */
public enum RiskScoreStatesEnum { public enum RiskScoreStatesEnum {
ZERO(_("0")), ONE(_("1")), TWO(_("2")), THREE(_("3")), FOUR(_("4")), SIX(_("6")), NINE(_("9")) ; ZERO(tr("0")), ONE(tr("1")), TWO(tr("2")), THREE(tr("3")), FOUR(tr("4")), SIX(tr("6")), NINE(tr("9")) ;
private final String riskScoreStateEnum; private final String riskScoreStateEnum;

View file

@ -21,7 +21,7 @@
package org.libreplan.business.materials.entities; package org.libreplan.business.materials.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* *
@ -29,11 +29,11 @@ import static org.libreplan.business.i18n.I18nHelper._;
* *
*/ */
public enum MaterialStatusEnum { public enum MaterialStatusEnum {
RECEIVED(_("RECEIVED")), RECEIVED(tr("RECEIVED")),
PENDING(_("PENDING")), PENDING(tr("PENDING")),
ORDERED(_("ORDERED")), ORDERED(tr("ORDERED")),
PROCESSING(_("PROCESSING")), PROCESSING(tr("PROCESSING")),
CANCELED(_("CANCELED")); CANCELED(tr("CANCELED"));
private String description; private String description;

View file

@ -21,7 +21,7 @@
package org.libreplan.business.orders.entities; package org.libreplan.business.orders.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -536,7 +536,7 @@ public abstract class CriterionRequirementHandler<T, S, R> {
newRequirement); newRequirement);
} else { } else {
throw new IllegalStateException( throw new IllegalStateException(
_("The criterion already exists into another task")); tr("The criterion already exists into another task"));
} }
} }

View file

@ -20,7 +20,7 @@
*/ */
package org.libreplan.business.orders.entities; package org.libreplan.business.orders.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Collection; import java.util.Collection;
@ -206,7 +206,7 @@ public class HoursGroup extends IntegrationEntity implements Cloneable, ICriteri
if ( !isPercentageValidForParent() ) { if ( !isPercentageValidForParent() ) {
this.percentage = oldPercentage; this.percentage = oldPercentage;
throw new IllegalArgumentException(_("Total percentage should be less than 100%")); throw new IllegalArgumentException(tr("Total percentage should be less than 100%"));
} }
} }

View file

@ -21,7 +21,7 @@
package org.libreplan.business.orders.entities; package org.libreplan.business.orders.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
@ -749,7 +749,7 @@ public abstract class OrderElement extends IntegrationEntity implements ICriteri
for (DirectAdvanceAssignment directAdvanceAssignment : directAdvanceAssignments) { for (DirectAdvanceAssignment directAdvanceAssignment : directAdvanceAssignments) {
if ( directAdvanceAssignment.getReportGlobalAdvance() ) { if ( directAdvanceAssignment.getReportGlobalAdvance() ) {
throw new DuplicateValueTrueReportGlobalAdvanceException( throw new DuplicateValueTrueReportGlobalAdvanceException(
_("Cannot spread two progress in the same task"), this, OrderElement.class); tr("Cannot spread two progress in the same task"), this, OrderElement.class);
} }
} }
} }
@ -771,7 +771,7 @@ public abstract class OrderElement extends IntegrationEntity implements ICriteri
directAdvanceAssignment.getAdvanceType(), newAdvanceAssignment.getAdvanceType()) ) { directAdvanceAssignment.getAdvanceType(), newAdvanceAssignment.getAdvanceType()) ) {
throw new DuplicateAdvanceAssignmentForOrderElementException( throw new DuplicateAdvanceAssignmentForOrderElementException(
_("Duplicate Progress Assignment For Task"), this, OrderElement.class); tr("Duplicate Progress Assignment For Task"), this, OrderElement.class);
} }
} }
if (orderElement.getParent() != null) { if (orderElement.getParent() != null) {
@ -792,7 +792,7 @@ public abstract class OrderElement extends IntegrationEntity implements ICriteri
if (orderElement.existsDirectAdvanceAssignmentWithTheSameType(newAdvanceAssignment.getAdvanceType())) { if (orderElement.existsDirectAdvanceAssignmentWithTheSameType(newAdvanceAssignment.getAdvanceType())) {
throw new DuplicateAdvanceAssignmentForOrderElementException( throw new DuplicateAdvanceAssignmentForOrderElementException(
_("Duplicate Progress Assignment For Task"), tr("Duplicate Progress Assignment For Task"),
this, this,
OrderElement.class); OrderElement.class);
} }
@ -1101,7 +1101,7 @@ public abstract class OrderElement extends IntegrationEntity implements ICriteri
if ( qualityForm.equals(taskQualityForm.getQualityForm()) ) { if ( qualityForm.equals(taskQualityForm.getQualityForm()) ) {
throw new ValidationException(ValidationException.invalidValue( throw new ValidationException(ValidationException.invalidValue(
_("Quality form already exists"), tr("Quality form already exists"),
"name", "name",
qualityForm.getName(), qualityForm.getName(),
qualityForm)); qualityForm));

View file

@ -21,7 +21,7 @@
package org.libreplan.business.orders.entities; package org.libreplan.business.orders.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
@ -969,7 +969,7 @@ public class OrderLineGroup extends OrderElement implements ITreeParentNode<Orde
for (AdvanceAssignment advanceAssignment : advanceAssignments) { for (AdvanceAssignment advanceAssignment : advanceAssignments) {
if ( advanceAssignment.getReportGlobalAdvance() ) { if ( advanceAssignment.getReportGlobalAdvance() ) {
throw new DuplicateValueTrueReportGlobalAdvanceException( throw new DuplicateValueTrueReportGlobalAdvanceException(
_("Cannot spread two progress in the same task"), tr("Cannot spread two progress in the same task"),
this, OrderElement.class); this, OrderElement.class);
} }
} }

View file

@ -21,7 +21,7 @@
package org.libreplan.business.orders.entities; package org.libreplan.business.orders.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.EnumSet; import java.util.EnumSet;
@ -33,15 +33,15 @@ import java.util.EnumSet;
*/ */
public enum OrderStatusEnum { public enum OrderStatusEnum {
PRE_SALES(_("PRE-SALES"), 0), PRE_SALES(tr("PRE-SALES"), 0),
OFFERED(_("OFFERED"), 1), OFFERED(tr("OFFERED"), 1),
OUTSOURCED(_("OUTSOURCED"), 2), OUTSOURCED(tr("OUTSOURCED"), 2),
ACCEPTED(_("ACCEPTED"), 3), ACCEPTED(tr("ACCEPTED"), 3),
STARTED(_("STARTED"), 4), STARTED(tr("STARTED"), 4),
ON_HOLD(_("ON HOLD"), 5), ON_HOLD(tr("ON HOLD"), 5),
FINISHED(_("FINISHED"), 6), FINISHED(tr("FINISHED"), 6),
CANCELLED(_("CANCELLED"), 7), CANCELLED(tr("CANCELLED"), 7),
STORED(_("ARCHIVED"), 8); STORED(tr("ARCHIVED"), 8);
private String description; private String description;

View file

@ -20,7 +20,7 @@
*/ */
package org.libreplan.business.orders.entities; package org.libreplan.business.orders.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -363,21 +363,21 @@ public class SchedulingState {
public String getStateName() { public String getStateName() {
if (isCompletelyScheduled()) { if (isCompletelyScheduled()) {
return _("Fully scheduled"); return tr("Fully scheduled");
} else if (isPartiallyScheduled()) { } else if (isPartiallyScheduled()) {
return _("Partially scheduled"); return tr("Partially scheduled");
} else { } else {
return _("Unscheduled"); return tr("Unscheduled");
} }
} }
public String getStateAbbreviation() { public String getStateAbbreviation() {
if (isCompletelyScheduled()) { if (isCompletelyScheduled()) {
return _("F"); return tr("F");
} else if (isPartiallyScheduled()) { } else if (isPartiallyScheduled()) {
return _("P"); return tr("P");
} else { } else {
return _("U"); return tr("U");
} }
} }

View file

@ -21,7 +21,7 @@
package org.libreplan.business.planner.entities; package org.libreplan.business.planner.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.List; import java.util.List;
@ -70,11 +70,11 @@ public abstract class AssignmentFunction extends BaseEntity {
public abstract boolean isManual(); public abstract boolean isManual();
public enum AssignmentFunctionName { public enum AssignmentFunctionName {
FLAT(_("Flat")), FLAT(tr("Flat")),
MANUAL(_("Manual")), MANUAL(tr("Manual")),
STRETCHES(_("Stretches")), STRETCHES(tr("Stretches")),
INTERPOLATION(_("Interpolation")), INTERPOLATION(tr("Interpolation")),
SIGMOID(_("Sigmoid")); SIGMOID(tr("Sigmoid"));
private String name; private String name;

View file

@ -310,7 +310,7 @@ public class EffortDistributor {
public List<ResourceWithAssignedDuration> distributeForDay(PartialDay day, EffortDuration totalDuration) { public List<ResourceWithAssignedDuration> distributeForDay(PartialDay day, EffortDuration totalDuration) {
return withCaptureOfResourcesPicked(distributeForDay_(day, totalDuration)); return withCaptureOfResourcesPicked(distributeForDaytr(day, totalDuration));
} }
private List<ResourceWithAssignedDuration> withCaptureOfResourcesPicked(List<ResourceWithAssignedDuration> result) { private List<ResourceWithAssignedDuration> withCaptureOfResourcesPicked(List<ResourceWithAssignedDuration> result) {
@ -318,7 +318,7 @@ public class EffortDistributor {
return result; return result;
} }
private List<ResourceWithAssignedDuration> distributeForDay_(PartialDay day, EffortDuration totalDuration) { private List<ResourceWithAssignedDuration> distributeForDaytr(PartialDay day, EffortDuration totalDuration) {
List<ResourceWithDerivedData> resourcesAssignable = resourcesAssignableAt(day.getDate()); List<ResourceWithDerivedData> resourcesAssignable = resourcesAssignableAt(day.getDate());
List<ResourceWithAssignedDuration> withoutOvertime = List<ResourceWithAssignedDuration> withoutOvertime =

View file

@ -28,21 +28,21 @@ import org.libreplan.business.orders.entities.Order.SchedulingMode;
* @author Óscar González Fernández <ogonzalez@igalia.com> * @author Óscar González Fernández <ogonzalez@igalia.com>
*/ */
public enum PositionConstraintType { public enum PositionConstraintType {
AS_SOON_AS_POSSIBLE(false, _("as soon as possible")) { AS_SOON_AS_POSSIBLE(false, tr("as soon as possible")) {
@Override @Override
public boolean appliesToTheStart() { public boolean appliesToTheStart() {
return true; return true;
} }
}, },
START_NOT_EARLIER_THAN(true, _("start not earlier than")) { START_NOT_EARLIER_THAN(true, tr("start not earlier than")) {
@Override @Override
public boolean appliesToTheStart() { public boolean appliesToTheStart() {
return true; return true;
} }
}, },
START_IN_FIXED_DATE(true, _("start in fixed date")) { START_IN_FIXED_DATE(true, tr("start in fixed date")) {
@Override @Override
public PositionConstraintType newTypeAfterMoved(SchedulingMode mode) { public PositionConstraintType newTypeAfterMoved(SchedulingMode mode) {
@ -54,14 +54,14 @@ public enum PositionConstraintType {
return true; return true;
} }
}, },
AS_LATE_AS_POSSIBLE(false, _("as late as possible")) { AS_LATE_AS_POSSIBLE(false, tr("as late as possible")) {
@Override @Override
public boolean appliesToTheStart() { public boolean appliesToTheStart() {
return false; return false;
} }
}, },
FINISH_NOT_LATER_THAN(true, _("finish not later than")) { FINISH_NOT_LATER_THAN(true, tr("finish not later than")) {
@Override @Override
public boolean appliesToTheStart() { public boolean appliesToTheStart() {
@ -72,7 +72,7 @@ public enum PositionConstraintType {
/** /**
* Forces to mark the string as needing translation * Forces to mark the string as needing translation
*/ */
private static String _(String string) { private static String tr(String string) {
return string; return string;
} }

View file

@ -22,7 +22,7 @@
package org.libreplan.business.planner.entities; package org.libreplan.business.planner.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
@ -423,7 +423,7 @@ public class StretchesFunction extends AssignmentFunction {
BigDecimal left = calculateLeftFor(sumOfProportions); BigDecimal left = calculateLeftFor(sumOfProportions);
if ( !left.equals(BigDecimal.ZERO) ) { if ( !left.equals(BigDecimal.ZERO) ) {
throw new IllegalStateException(_("Stretches must sum 100%")); throw new IllegalStateException(tr("Stretches must sum 100%"));
} }
} }

View file

@ -21,7 +21,7 @@
package org.libreplan.business.planner.entities; package org.libreplan.business.planner.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Possible states of a {@link SubcontractedTaskData}. * Possible states of a {@link SubcontractedTaskData}.
@ -29,10 +29,10 @@ import static org.libreplan.business.i18n.I18nHelper._;
* @author Manuel Rego Casasnovas <mrego@igalia.com> * @author Manuel Rego Casasnovas <mrego@igalia.com>
*/ */
public enum SubcontractState { public enum SubcontractState {
PENDING_INITIAL_SEND(_("Pending initial send"), true), PENDING_UPDATE_DELIVERING_DATE( PENDING_INITIAL_SEND(tr("Pending initial send"), true), PENDING_UPDATE_DELIVERING_DATE(
_("Pending update delivering date"), true), FAILED_SENT( tr("Pending update delivering date"), true), FAILED_SENT(
_("Failed sent"), true), FAILED_UPDATE(_("Failed update"), true), SUCCESS_SENT( tr("Failed sent"), true), FAILED_UPDATE(tr("Failed update"), true), SUCCESS_SENT(
_("Success sent"), false); tr("Success sent"), false);
private String name; private String name;
private boolean sendable; private boolean sendable;

View file

@ -19,7 +19,7 @@
package org.libreplan.business.planner.entities; package org.libreplan.business.planner.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Enumerate of {@link Task} deadline violation statuses. * Enumerate of {@link Task} deadline violation statuses.
@ -31,9 +31,9 @@ import static org.libreplan.business.i18n.I18nHelper._;
* @author Nacho Barrientos <nacho@igalia.com> * @author Nacho Barrientos <nacho@igalia.com>
*/ */
public enum TaskDeadlineViolationStatusEnum { public enum TaskDeadlineViolationStatusEnum {
NO_DEADLINE(_("No deadline")), NO_DEADLINE(tr("No deadline")),
DEADLINE_VIOLATED(_("Deadline violated")), DEADLINE_VIOLATED(tr("Deadline violated")),
ON_SCHEDULE(_("On schedule")); ON_SCHEDULE(tr("On schedule"));
private String value; private String value;

View file

@ -21,15 +21,15 @@
package org.libreplan.business.planner.entities; package org.libreplan.business.planner.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
public enum TaskStatusEnum { public enum TaskStatusEnum {
ALL(_("All")), ALL(tr("All")),
FINISHED(_("Finished")), FINISHED(tr("Finished")),
IN_PROGRESS(_("In progress")), IN_PROGRESS(tr("In progress")),
PENDING(_("Pending")), PENDING(tr("Pending")),
BLOCKED(_("Blocked")), BLOCKED(tr("Blocked")),
READY_TO_START(_("Ready to start")); READY_TO_START(tr("Ready to start"));
private String value; private String value;

View file

@ -21,7 +21,7 @@
package org.libreplan.business.planner.entities.allocationalgorithms; package org.libreplan.business.planner.entities.allocationalgorithms;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import static org.libreplan.business.workingday.EffortDuration.min; import static org.libreplan.business.workingday.EffortDuration.min;
import java.util.ArrayList; import java.util.ArrayList;
@ -92,15 +92,15 @@ public abstract class ResourcesPerDayModification extends
@Override @Override
public String getNoValidPeriodsMessage() { public String getNoValidPeriodsMessage() {
String firstLine = _("There are no days available due to not satisfying the criteria."); String firstLine = tr("There are no days available due to not satisfying the criteria.");
String secondLine = _("Another possibility is that the resources do not have days available due to their calendars."); String secondLine = tr("Another possibility is that the resources do not have days available due to their calendars.");
return firstLine + "\n" + secondLine; return firstLine + "\n" + secondLine;
} }
@Override @Override
public String getNoValidPeriodsMessageDueToIntersectionMessage() { public String getNoValidPeriodsMessageDueToIntersectionMessage() {
String firstLine = _("There are no days available in the days marked available by the task calendar."); String firstLine = tr("There are no days available in the days marked available by the task calendar.");
String secondLine = _("Maybe the criteria are not satisfied in those days."); String secondLine = tr("Maybe the criteria are not satisfied in those days.");
return firstLine + "\n" + secondLine; return firstLine + "\n" + secondLine;
} }
@ -172,12 +172,12 @@ public abstract class ResourcesPerDayModification extends
@Override @Override
public String getNoValidPeriodsMessage() { public String getNoValidPeriodsMessage() {
return _("Resource is not available from task's start"); return tr("Resource is not available from task's start");
} }
@Override @Override
public String getNoValidPeriodsMessageDueToIntersectionMessage() { public String getNoValidPeriodsMessageDueToIntersectionMessage() {
return _("Resource is not available according to task's calendar"); return tr("Resource is not available according to task's calendar");
} }
private Resource getAssociatedResource() { private Resource getAssociatedResource() {

View file

@ -20,7 +20,7 @@
*/ */
package org.libreplan.business.planner.limiting.entities; package org.libreplan.business.planner.limiting.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.EnumMap; import java.util.EnumMap;
@ -167,7 +167,7 @@ public class LimitingResourceQueueDependency extends BaseEntity {
Validate.notNull(origin); Validate.notNull(origin);
Validate.notNull(destiny); Validate.notNull(destiny);
Validate.notNull(ganttDependency); Validate.notNull(ganttDependency);
Validate.isTrue(!origin.equals(destiny), _("A queue dependency has to " + Validate.isTrue(!origin.equals(destiny), tr("A queue dependency has to " +
"have an origin different from destiny")); "have an origin different from destiny"));
this.hasAsOrigin = origin; this.hasAsOrigin = origin;
this.hasAsDestiny = destiny; this.hasAsDestiny = destiny;

View file

@ -21,7 +21,7 @@
package org.libreplan.business.planner.limiting.entities; package org.libreplan.business.planner.limiting.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
@ -50,7 +50,7 @@ public class QueuePosition {
} }
public void setHour(int hour) { public void setHour(int hour) {
Validate.isTrue(hour >= 0 && hour <= 23, _("Hour should be between 0 and 23")); Validate.isTrue(hour >= 0 && hour <= 23, tr("Hour should be between 0 and 23"));
this.hour = hour; this.hour = hour;
} }

View file

@ -26,12 +26,12 @@ package org.libreplan.business.qualityforms.entities;
public enum QualityFormType { public enum QualityFormType {
BY_PERCENTAGE(_("by percentage")), BY_ITEMS(_("by items")); BY_PERCENTAGE(tr("by percentage")), BY_ITEMS(tr("by items"));
/** /**
* Forces to mark the string as needing translation * Forces to mark the string as needing translation
*/ */
private static String _(String string) { private static String tr(String string) {
return string; return string;
} }

View file

@ -21,7 +21,7 @@
package org.libreplan.business.resources.entities; package org.libreplan.business.resources.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -195,11 +195,11 @@ public class Criterion extends IntegrationEntity implements ICriterion, Comparab
} }
private static String allWorkersCaption() { private static String allWorkersCaption() {
return _("[generic all workers]"); return tr("[generic all workers]");
} }
private static String allMachinesCaption() { private static String allMachinesCaption() {
return _("[generic all machines]"); return tr("[generic all machines]");
} }
public void updateUnvalidated(String name, Boolean active) { public void updateUnvalidated(String name, Boolean active) {

View file

@ -26,8 +26,8 @@ package org.libreplan.business.resources.entities;
*/ */
public enum ResourceEnum { public enum ResourceEnum {
WORKER(Worker.class, _("WORKER")), WORKER(Worker.class, tr("WORKER")),
MACHINE(Machine.class, _("MACHINE")); MACHINE(Machine.class, tr("MACHINE"));
private Class<? extends Resource> klass; private Class<? extends Resource> klass;
@ -41,7 +41,7 @@ public enum ResourceEnum {
/** /**
* Forces to mark the string as needing translation. * Forces to mark the string as needing translation.
*/ */
private static String _(String string) { private static String tr(String string) {
return string; return string;
} }

View file

@ -19,7 +19,7 @@
package org.libreplan.business.resources.entities; package org.libreplan.business.resources.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Enumerate with the three basic types of resource: non-limiting, limiting and strategic. * Enumerate with the three basic types of resource: non-limiting, limiting and strategic.
@ -27,8 +27,8 @@ import static org.libreplan.business.i18n.I18nHelper._;
*/ */
public enum ResourceType { public enum ResourceType {
NON_LIMITING_RESOURCE(_("Normal resource")), NON_LIMITING_RESOURCE(tr("Normal resource")),
LIMITING_RESOURCE(_("Queue-based resource")); LIMITING_RESOURCE(tr("Queue-based resource"));
private String option; private String option;

View file

@ -20,7 +20,7 @@
package org.libreplan.business.settings.entities; package org.libreplan.business.settings.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.Locale; import java.util.Locale;
@ -33,7 +33,7 @@ import java.util.Locale;
*/ */
public enum Language { public enum Language {
BROWSER_LANGUAGE(_("Use browser language configuration"), null), BROWSER_LANGUAGE(tr("Use browser language configuration"), null),
GALICIAN_LANGUAGE("Galego", new Locale("gl")), GALICIAN_LANGUAGE("Galego", new Locale("gl")),
SPANISH_LANGUAGE("Español", new Locale("es")), SPANISH_LANGUAGE("Español", new Locale("es")),
ENGLISH_LANGUAGE("English", Locale.ENGLISH), ENGLISH_LANGUAGE("English", Locale.ENGLISH),

View file

@ -270,7 +270,7 @@ public class OrderLineGroupTemplate extends OrderElementTemplate implements
@Override @Override
public String getType() { public String getType() {
return I18nHelper._("Group"); return I18nHelper.tr("Group");
} }
@Override @Override

View file

@ -20,7 +20,7 @@
*/ */
package org.libreplan.business.templates.entities; package org.libreplan.business.templates.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
@ -163,7 +163,7 @@ public class OrderLineTemplate extends OrderElementTemplate {
@Override @Override
public String getType() { public String getType() {
return _("Line"); return tr("Line");
} }
public Integer getWorkHours() { public Integer getWorkHours() {

View file

@ -20,7 +20,7 @@
*/ */
package org.libreplan.business.templates.entities; package org.libreplan.business.templates.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import org.libreplan.business.calendars.entities.BaseCalendar; import org.libreplan.business.calendars.entities.BaseCalendar;
@ -62,7 +62,7 @@ public class OrderTemplate extends OrderLineGroupTemplate {
@Override @Override
public String getType() { public String getType() {
return _("Project"); return tr("Project");
} }
public void setCalendar(BaseCalendar calendar) { public void setCalendar(BaseCalendar calendar) {

View file

@ -21,7 +21,7 @@
package org.libreplan.business.users.entities; package org.libreplan.business.users.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Available types of {@link OrderAuthorization}. * Available types of {@link OrderAuthorization}.
@ -30,8 +30,8 @@ import static org.libreplan.business.i18n.I18nHelper._;
*/ */
public enum OrderAuthorizationType { public enum OrderAuthorizationType {
READ_AUTHORIZATION(_("Read authorization")), READ_AUTHORIZATION(tr("Read authorization")),
WRITE_AUTHORIZATION(_("Write authorization")); WRITE_AUTHORIZATION(tr("Write authorization"));
private final String displayName; private final String displayName;

View file

@ -21,7 +21,7 @@
package org.libreplan.business.users.entities; package org.libreplan.business.users.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -370,8 +370,8 @@ public class User extends BaseEntity implements IHumanIdentifiable{
public enum UserAuthenticationType { public enum UserAuthenticationType {
DATABASE(_("Database")), DATABASE(tr("Database")),
LDAP(_("LDAP")); LDAP(tr("LDAP"));
private String name; private String name;

View file

@ -21,7 +21,7 @@
package org.libreplan.business.users.entities; package org.libreplan.business.users.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* Available user roles. * Available user roles.
@ -33,70 +33,70 @@ import static org.libreplan.business.i18n.I18nHelper._;
public enum UserRole { public enum UserRole {
// Access to all pages // Access to all pages
ROLE_SUPERUSER(_("Superuser")), ROLE_SUPERUSER(tr("Superuser")),
// Web services roles // Web services roles
ROLE_WS_READER(_("Web service reader")), ROLE_WS_READER(tr("Web service reader")),
ROLE_WS_WRITER(_("Web service writer")), ROLE_WS_WRITER(tr("Web service writer")),
ROLE_WS_SUBCONTRACTING(_("Web service subcontractor operations")), ROLE_WS_SUBCONTRACTING(tr("Web service subcontractor operations")),
// Project operations roles // Project operations roles
ROLE_READ_ALL_PROJECTS(_("Read all projects")), ROLE_READ_ALL_PROJECTS(tr("Read all projects")),
ROLE_EDIT_ALL_PROJECTS(_("Edit all projects")), ROLE_EDIT_ALL_PROJECTS(tr("Edit all projects")),
ROLE_CREATE_PROJECTS(_("Create projects")), ROLE_CREATE_PROJECTS(tr("Create projects")),
// Special role for bound users // Special role for bound users
ROLE_BOUND_USER(_("Bound user")), ROLE_BOUND_USER(tr("Bound user")),
// Page roles // Page roles
ROLE_PLANNING(_("Planning")), ROLE_PLANNING(tr("Planning")),
ROLE_TEMPLATES(_("Templates")), ROLE_TEMPLATES(tr("Templates")),
ROLE_IMPORT_PROJECTS(_("Import projects")), ROLE_IMPORT_PROJECTS(tr("Import projects")),
ROLE_WORKERS(_("Workers")), ROLE_WORKERS(tr("Workers")),
ROLE_MACHINES(_("Machines")), ROLE_MACHINES(tr("Machines")),
ROLE_VIRTUAL_WORKERS(_("Virtual Workers")), ROLE_VIRTUAL_WORKERS(tr("Virtual Workers")),
ROLE_CALENDARS(_("Calendars")), ROLE_CALENDARS(tr("Calendars")),
ROLE_CALENDAR_EXCEPTION_DAYS(_("Calendar Exception Days")), ROLE_CALENDAR_EXCEPTION_DAYS(tr("Calendar Exception Days")),
ROLE_CRITERIA(_("Criteria")), ROLE_CRITERIA(tr("Criteria")),
ROLE_PROGRESS_TYPES(_("Progress Types")), ROLE_PROGRESS_TYPES(tr("Progress Types")),
ROLE_LABELS(_("Labels")), ROLE_LABELS(tr("Labels")),
ROLE_MATERIALS(_("Materials")), ROLE_MATERIALS(tr("Materials")),
ROLE_MATERIAL_UNITS(_("Material Units")), ROLE_MATERIAL_UNITS(tr("Material Units")),
ROLE_QUALITY_FORMS(_("Quality Forms")), ROLE_QUALITY_FORMS(tr("Quality Forms")),
ROLE_TIMESHEETS(_("Timesheets")), ROLE_TIMESHEETS(tr("Timesheets")),
ROLE_TIMESHEETS_TEMPLATES(_("Timesheets Templates")), ROLE_TIMESHEETS_TEMPLATES(tr("Timesheets Templates")),
ROLE_EXPENSES(_("Expenses")), ROLE_EXPENSES(tr("Expenses")),
ROLE_COST_CATEGORIES(_("Cost Categories")), ROLE_COST_CATEGORIES(tr("Cost Categories")),
ROLE_HOURS_TYPES(_("Hours Types")), ROLE_HOURS_TYPES(tr("Hours Types")),
ROLE_MAIN_SETTINGS(_("Main Settings")), ROLE_MAIN_SETTINGS(tr("Main Settings")),
ROLE_USER_ACCOUNTS(_("User Accounts")), ROLE_USER_ACCOUNTS(tr("User Accounts")),
ROLE_PROFILES(_("Profiles")), ROLE_PROFILES(tr("Profiles")),
ROLE_JOB_SCHEDULING(_("Job Scheduling")), ROLE_JOB_SCHEDULING(tr("Job Scheduling")),
ROLE_COMPANIES(_("Companies")), ROLE_COMPANIES(tr("Companies")),
ROLE_SEND_TO_SUBCONTRACTORS(_("Send To Subcontractors")), ROLE_SEND_TO_SUBCONTRACTORS(tr("Send To Subcontractors")),
ROLE_RECEIVED_FROM_SUBCONTRACTORS(_("Received From Subcontractors")), ROLE_RECEIVED_FROM_SUBCONTRACTORS(tr("Received From Subcontractors")),
ROLE_SEND_TO_CUSTOMERS(_("Send To Customers")), ROLE_SEND_TO_CUSTOMERS(tr("Send To Customers")),
ROLE_RECEIVED_FROM_CUSTOMERS(_("Received From Customers")), ROLE_RECEIVED_FROM_CUSTOMERS(tr("Received From Customers")),
ROLE_TIMESHEET_LINES_LIST(_("Timesheet Lines List")), ROLE_TIMESHEET_LINES_LIST(tr("Timesheet Lines List")),
ROLE_HOURS_WORKED_PER_RESOURCE_REPORT(_("Hours Worked Per Resource Report")), ROLE_HOURS_WORKED_PER_RESOURCE_REPORT(tr("Hours Worked Per Resource Report")),
ROLE_TOTAL_WORKED_HOURS_BY_RESOURCE_IN_A_MONTH_REPORT(_("Total Worked Hours By Resource In A Month Report")), ROLE_TOTAL_WORKED_HOURS_BY_RESOURCE_IN_A_MONTH_REPORT(tr("Total Worked Hours By Resource In A Month Report")),
ROLE_WORK_AND_PROGRESS_PER_PROJECT_REPORT(_("Work And Progress Per Project Report")), ROLE_WORK_AND_PROGRESS_PER_PROJECT_REPORT(tr("Work And Progress Per Project Report")),
ROLE_WORK_AND_PROGRESS_PER_TASK_REPORT(_("Work And Progress Per Task Report")), ROLE_WORK_AND_PROGRESS_PER_TASK_REPORT(tr("Work And Progress Per Task Report")),
ROLE_ESTIMATED_PLANNED_HOURS_PER_TASK_REPORT(_("Estimated/Planned Hours Per Task Report")), ROLE_ESTIMATED_PLANNED_HOURS_PER_TASK_REPORT(tr("Estimated/Planned Hours Per Task Report")),
ROLE_PROJECT_COSTS_REPORT(_("Project Costs Report")), ROLE_PROJECT_COSTS_REPORT(tr("Project Costs Report")),
ROLE_TASK_SCHEDULING_STATUS_IN_PROJECT_REPORT(_("Task Scheduling Status In Project Report")), ROLE_TASK_SCHEDULING_STATUS_IN_PROJECT_REPORT(tr("Task Scheduling Status In Project Report")),
ROLE_MATERIALS_NEED_AT_DATE_REPORT(_("Materials Needed At Date Report")), ROLE_MATERIALS_NEED_AT_DATE_REPORT(tr("Materials Needed At Date Report")),
ROLE_PROJECT_STATUS_REPORT(_("Project Status Report")), ROLE_PROJECT_STATUS_REPORT(tr("Project Status Report")),
ROLE_EDIT_EMAIL_TEMPLATES(_("Edit E-mail Templates")), ROLE_EDIT_EMAIL_TEMPLATES(tr("Edit E-mail Templates")),
ROLE_USE_FILES(_("Use files for order")), ROLE_USE_FILES(tr("Use files for order")),
ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE(_("Email: task assigned to resource")), ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE(tr("Email: task assigned to resource")),
ROLE_EMAIL_RESOURCE_REMOVED_FROM_TASK(_("Email: resource removed from task")), ROLE_EMAIL_RESOURCE_REMOVED_FROM_TASK(tr("Email: resource removed from task")),
ROLE_EMAIL_MILESTONE_REACHED(_("Email: milestone reached")), ROLE_EMAIL_MILESTONE_REACHED(tr("Email: milestone reached")),
ROLE_EMAIL_TASK_SHOULD_FINISH(_("Email: task should finish")), ROLE_EMAIL_TASK_SHOULD_FINISH(tr("Email: task should finish")),
ROLE_EMAIL_TASK_SHOULD_START(_("Email: task should start")), ROLE_EMAIL_TASK_SHOULD_START(tr("Email: task should start")),
ROLE_EMAIL_TIMESHEET_DATA_MISSING(_("Email: timesheet data missing")); ROLE_EMAIL_TIMESHEET_DATA_MISSING(tr("Email: timesheet data missing"));
private final String displayName; private final String displayName;

View file

@ -28,7 +28,7 @@ import java.sql.Types;
import java.util.Objects; import java.util.Objects;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.usertype.UserType; import org.hibernate.usertype.UserType;
import org.libreplan.business.workingday.EffortDuration; import org.libreplan.business.workingday.EffortDuration;
@ -60,10 +60,9 @@ public class EffortDurationType implements UserType {
@Override @Override
public Object nullSafeGet(ResultSet rs, String[] names, public Object nullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner) SharedSessionContractImplementor session, Object owner)
throws HibernateException, SQLException { throws HibernateException, SQLException {
Integer seconds = StandardBasicTypes.INTEGER.nullSafeGet(rs, names[0], Integer seconds = (Integer) rs.getObject(names[0]);
session);
if (seconds == null) { if (seconds == null) {
return null; return null;
} }
@ -72,10 +71,13 @@ public class EffortDurationType implements UserType {
@Override @Override
public void nullSafeSet(PreparedStatement st, Object value, int index, public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException { SharedSessionContractImplementor session) throws HibernateException, SQLException {
EffortDuration duration = (EffortDuration) value; EffortDuration duration = (EffortDuration) value;
Integer seconds = duration != null ? duration.getSeconds() : null; if (duration == null) {
StandardBasicTypes.INTEGER.nullSafeSet(st, seconds, index, session); st.setNull(index, Types.INTEGER);
} else {
st.setInt(index, duration.getSeconds());
}
} }
@Override @Override

View file

@ -29,8 +29,7 @@ import java.sql.SQLException;
import java.sql.Types; import java.sql.Types;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.usertype.UserType; import org.hibernate.usertype.UserType;
import org.libreplan.business.workingday.ResourcesPerDay; import org.libreplan.business.workingday.ResourcesPerDay;
@ -87,11 +86,10 @@ public class ResourcesPerDayType implements UserType {
@Override @Override
public Object nullSafeGet(ResultSet rs, String[] names, public Object nullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner) SharedSessionContractImplementor session, Object owner)
throws HibernateException, SQLException { throws HibernateException, SQLException {
BigDecimal bigDecimal = (BigDecimal) StandardBasicTypes.BIG_DECIMAL BigDecimal bigDecimal = rs.getBigDecimal(names[0]);
.nullSafeGet(rs, names[0], session); if (rs.wasNull() || bigDecimal == null) {
if (bigDecimal == null) {
return null; return null;
} }
return ResourcesPerDay.amount(bigDecimal); return ResourcesPerDay.amount(bigDecimal);
@ -99,13 +97,12 @@ public class ResourcesPerDayType implements UserType {
@Override @Override
public void nullSafeSet(PreparedStatement st, Object value, int index, public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException { SharedSessionContractImplementor session) throws HibernateException, SQLException {
BigDecimal amount = null; if (value == null) {
if (value != null) { st.setNull(index, Types.NUMERIC);
amount = ((ResourcesPerDay) value).getAmount(); } else {
st.setBigDecimal(index, ((ResourcesPerDay) value).getAmount());
} }
StandardBasicTypes.BIG_DECIMAL.nullSafeSet(st, amount, index, session);
} }
@Override @Override

View file

@ -24,13 +24,13 @@
*/ */
package org.libreplan.business.workreports.entities; package org.libreplan.business.workreports.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
public enum HoursManagementEnum { public enum HoursManagementEnum {
NUMBER_OF_HOURS(_("Number of assigned hours")), NUMBER_OF_HOURS(tr("Number of assigned hours")),
HOURS_CALCULATED_BY_CLOCK(_("Number of hours calculated by clock")), HOURS_CALCULATED_BY_CLOCK(tr("Number of hours calculated by clock")),
NUMBER_OF_HOURS_AND_CLOCK(_("Number of assigned hours and time")); NUMBER_OF_HOURS_AND_CLOCK(tr("Number of assigned hours and time"));
private String description; private String description;

View file

@ -24,14 +24,14 @@
*/ */
package org.libreplan.business.workreports.entities; package org.libreplan.business.workreports.entities;
import static org.libreplan.business.i18n.I18nHelper._; import static org.libreplan.business.i18n.I18nHelper.tr;
/** /**
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com> * @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/ */
public enum PositionInWorkReportEnum { public enum PositionInWorkReportEnum {
HEADING(_("heading")), LINE(_("line")); HEADING(tr("heading")), LINE(tr("line"));
private String displayName; private String displayName;

View file

@ -0,0 +1 @@
org.libreplan.business.common.hibernate.JodaTypeContributor

View file

@ -20,7 +20,7 @@
--> -->
<property name="javax.persistence.validation.mode">none</property> <property name="javax.persistence.validation.mode">none</property>
<property name="jadira.usertype.autoRegisterUserTypes">true</property> <property name="jadira.usertype.autoRegisterUserTypes">false</property>
<property name="jadira.usertype.databaseZone">jvm</property> <property name="jadira.usertype.databaseZone">jvm</property>
<property name="jadira.usertype.javaZone">jvm</property> <property name="jadira.usertype.javaZone">jvm</property>

View file

@ -7,10 +7,10 @@
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<aop:aspectj-autoproxy/> <aop:aspectj-autoproxy/>

View file

@ -10,7 +10,7 @@
</parent> </parent>
<artifactId>libreplan-webapp</artifactId> <artifactId>libreplan-webapp</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
<name>LibrePlan Web Client Module</name> <name>TASKPM Web Client Module</name>
<profiles> <profiles>
@ -395,7 +395,7 @@
<dependency> <dependency>
<groupId>${jdbcDriver.groupId}</groupId> <groupId>${jdbcDriver.groupId}</groupId>
<artifactId>${jdbcDriver.artifactId}</artifactId> <artifactId>${jdbcDriver.artifactId}</artifactId>
<scope>test</scope> <scope>runtime</scope>
</dependency> </dependency>
<!-- Easymock --> <!-- Easymock -->

View file

@ -20,7 +20,7 @@
package org.libreplan.importers; package org.libreplan.importers;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper.tr;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
@ -337,7 +337,7 @@ public class CalendarImporterMPXJ implements ICalendarImporter {
if (calendars.isEmpty()) { if (calendars.isEmpty()) {
return name; return name;
} else { } else {
throw new ValidationException(_("Calendar name already in use")); throw new ValidationException(tr("Calendar name already in use"));
} }
} }

View file

@ -19,7 +19,7 @@
package org.libreplan.importers; package org.libreplan.importers;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper.tr;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -89,21 +89,21 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
public List<SynchronizationInfo> exportTimesheets() throws ConnectorException { public List<SynchronizationInfo> exportTimesheets() throws ConnectorException {
Connector connector = getTimConnector(); Connector connector = getTimConnector();
if (connector == null) { if (connector == null) {
throw new ConnectorException(_("Tim connector not found")); throw new ConnectorException(tr("Tim connector not found"));
} }
if (!connector.areConnectionValuesValid()) { if (!connector.areConnectionValuesValid()) {
throw new ConnectorException( throw new ConnectorException(
_("Connection values of Tim connector are invalid")); tr("Connection values of Tim connector are invalid"));
} }
synchronizationInfo = new SynchronizationInfo(_("Export")); synchronizationInfo = new SynchronizationInfo(tr("Export"));
List<SynchronizationInfo> syncInfos = new ArrayList<SynchronizationInfo>(); List<SynchronizationInfo> syncInfos = new ArrayList<SynchronizationInfo>();
List<OrderSyncInfo> orderSyncInfos = orderSyncInfoDAO.findByConnectorName(PredefinedConnectors.TIM.getName()); List<OrderSyncInfo> orderSyncInfos = orderSyncInfoDAO.findByConnectorName(PredefinedConnectors.TIM.getName());
if (orderSyncInfos == null || orderSyncInfos.isEmpty()) { if (orderSyncInfos == null || orderSyncInfos.isEmpty()) {
LOG.warn("No items found in 'OrderSyncInfo' to export to Tim"); LOG.warn("No items found in 'OrderSyncInfo' to export to Tim");
synchronizationInfo.addFailedReason(_("No items found in 'OrderSyncInfo' to export to Tim")); synchronizationInfo.addFailedReason(tr("No items found in 'OrderSyncInfo' to export to Tim"));
syncInfos.add(synchronizationInfo); syncInfos.add(synchronizationInfo);
return syncInfos; return syncInfos;
} }
@ -124,20 +124,20 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
public void exportTimesheets(String productCode, Order order) public void exportTimesheets(String productCode, Order order)
throws ConnectorException { throws ConnectorException {
if (productCode == null || productCode.isEmpty()) { if (productCode == null || productCode.isEmpty()) {
throw new ConnectorException(_("Product code should not be empty")); throw new ConnectorException(tr("Product code should not be empty"));
} }
if (order == null) { if (order == null) {
throw new ConnectorException(_("Order should not be empty")); throw new ConnectorException(tr("Order should not be empty"));
} }
Connector connector = getTimConnector(); Connector connector = getTimConnector();
if (connector == null) { if (connector == null) {
throw new ConnectorException(_("Tim connector not found")); throw new ConnectorException(tr("Tim connector not found"));
} }
if (!connector.areConnectionValuesValid()) { if (!connector.areConnectionValuesValid()) {
throw new ConnectorException( throw new ConnectorException(
_("Connection values of Tim connector are invalid")); tr("Connection values of Tim connector are invalid"));
} }
exportTimesheets(productCode, order, connector); exportTimesheets(productCode, order, connector);
@ -158,7 +158,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
private void exportTimesheets(String productCode, Order order, private void exportTimesheets(String productCode, Order order,
Connector connector) { Connector connector) {
synchronizationInfo = new SynchronizationInfo(_( synchronizationInfo = new SynchronizationInfo(tr(
"Export product code {0}, project {1}", productCode, "Export product code {0}, project {1}", productCode,
order.getName())); order.getName()));
@ -181,7 +181,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
if (workReportLines == null || workReportLines.isEmpty()) { if (workReportLines == null || workReportLines.isEmpty()) {
LOG.warn("No work reportlines are found for order: '" LOG.warn("No work reportlines are found for order: '"
+ order.getName() + "'"); + order.getName() + "'");
synchronizationInfo.addFailedReason(_( synchronizationInfo.addFailedReason(tr(
"No work reportlines are found for order: \"{0}\"", "No work reportlines are found for order: \"{0}\"",
order.getName())); order.getName()));
return; return;
@ -200,7 +200,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
if (timeRegistrationDTOs.isEmpty()) { if (timeRegistrationDTOs.isEmpty()) {
LOG.warn("Unable to crate timeregistration for request"); LOG.warn("Unable to crate timeregistration for request");
synchronizationInfo synchronizationInfo
.addFailedReason(_("Unable to crate time registration for request")); .addFailedReason(tr("Unable to crate time registration for request"));
return; return;
} }
@ -214,14 +214,14 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
if (timeRegistrationResponseDTO == null) { if (timeRegistrationResponseDTO == null) {
LOG.error("No response or exception in response"); LOG.error("No response or exception in response");
synchronizationInfo synchronizationInfo
.addFailedReason(_("No response or exception in response")); .addFailedReason(tr("No response or exception in response"));
return; return;
} }
if (isRefsListEmpty(timeRegistrationResponseDTO.getRefs())) { if (isRefsListEmpty(timeRegistrationResponseDTO.getRefs())) {
LOG.warn("Registration response with empty refs"); LOG.warn("Registration response with empty refs");
synchronizationInfo synchronizationInfo
.addFailedReason(_("Registration response with empty refs")); .addFailedReason(tr("Registration response with empty refs"));
return; return;
} }
saveSyncInfoOnAnotherTransaction(productCode, order); saveSyncInfoOnAnotherTransaction(productCode, order);
@ -288,7 +288,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
worker = workerDAO.findByCode(workerCode); worker = workerDAO.findByCode(workerCode);
} catch (InstanceNotFoundException e) { } catch (InstanceNotFoundException e) {
LOG.warn("Worker '" + workerCode + "' not found"); LOG.warn("Worker '" + workerCode + "' not found");
synchronizationInfo.addFailedReason(_("Worker \"{0}\" not found", synchronizationInfo.addFailedReason(tr("Worker \"{0}\" not found",
workerCode)); workerCode));
return null; return null;
} }

View file

@ -19,7 +19,7 @@
package org.libreplan.importers; package org.libreplan.importers;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper.tr;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -121,12 +121,12 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
Connector connector = connectorDAO Connector connector = connectorDAO
.findUniqueByName(PredefinedConnectors.TIM.getName()); .findUniqueByName(PredefinedConnectors.TIM.getName());
if (connector == null) { if (connector == null) {
throw new ConnectorException(_("Tim connector not found")); throw new ConnectorException(tr("Tim connector not found"));
} }
if (!connector.areConnectionValuesValid()) { if (!connector.areConnectionValuesValid()) {
throw new ConnectorException( throw new ConnectorException(
_("Connection values of Tim connector are invalid")); tr("Connection values of Tim connector are invalid"));
} }
Map<String, String> properties = connector.getPropertiesAsMap(); Map<String, String> properties = connector.getPropertiesAsMap();
@ -150,7 +150,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
if (StringUtils.isBlank(departmentIds)) { if (StringUtils.isBlank(departmentIds)) {
LOG.warn("No departments configured"); LOG.warn("No departments configured");
throw new ConnectorException(_("No departments configured")); throw new ConnectorException(tr("No departments configured"));
} }
String[] departmentIdsArray = StringUtils.stripAll(StringUtils.split( String[] departmentIdsArray = StringUtils.stripAll(StringUtils.split(
@ -161,7 +161,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
for (String department : departmentIdsArray) { for (String department : departmentIdsArray) {
LOG.info("Department: " + department); LOG.info("Department: " + department);
synchronizationInfo = new SynchronizationInfo(_( synchronizationInfo = new SynchronizationInfo(tr(
"Import roster for department {0}", department)); "Import roster for department {0}", department));
RosterRequestDTO rosterRequestDTO = createRosterRequest(department, RosterRequestDTO rosterRequestDTO = createRosterRequest(department,
@ -178,7 +178,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
} }
} else { } else {
LOG.error("No valid response for department " + department); LOG.error("No valid response for department " + department);
synchronizationInfo.addFailedReason(_( synchronizationInfo.addFailedReason(tr(
"No valid response for department \"{0}\"", "No valid response for department \"{0}\"",
department)); department));
syncInfos.add(synchronizationInfo); syncInfos.add(synchronizationInfo);
@ -207,7 +207,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
} else { } else {
LOG.info("No roster-exceptions found in the response"); LOG.info("No roster-exceptions found in the response");
synchronizationInfo synchronizationInfo
.addFailedReason(_("No roster-exceptions found in the response")); .addFailedReason(tr("No roster-exceptions found in the response"));
} }
return null; return null;
} }
@ -235,7 +235,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
worker = workerDAO.findUniqueByNif(workerCode); worker = workerDAO.findUniqueByNif(workerCode);
} catch (InstanceNotFoundException e) { } catch (InstanceNotFoundException e) {
LOG.warn("Worker '" + workerCode + "' not found"); LOG.warn("Worker '" + workerCode + "' not found");
synchronizationInfo.addFailedReason(_( synchronizationInfo.addFailedReason(tr(
"Worker \"{0}\" not found", "Worker \"{0}\" not found",
workerCode)); workerCode));
} }
@ -353,7 +353,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
if (name == null || name.isEmpty()) { if (name == null || name.isEmpty()) {
LOG.error("Exception name should not be empty"); LOG.error("Exception name should not be empty");
synchronizationInfo synchronizationInfo
.addFailedReason(_("Exception name should not be empty")); .addFailedReason(tr("Exception name should not be empty"));
return null; return null;
} }
try { try {
@ -369,7 +369,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
} catch (InstanceNotFoundException e) { } catch (InstanceNotFoundException e) {
LOG.error("Calendar exceptionType not found", e); LOG.error("Calendar exceptionType not found", e);
synchronizationInfo synchronizationInfo
.addFailedReason(_("Calendar exception day not found")); .addFailedReason(tr("Calendar exception day not found"));
} }
return null; return null;
} }

View file

@ -19,7 +19,7 @@
package org.libreplan.importers; package org.libreplan.importers;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper.tr;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
@ -102,7 +102,7 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
public List<String> getAllJiraLabels() throws ConnectorException { public List<String> getAllJiraLabels() throws ConnectorException {
Connector connector = getJiraConnector(); Connector connector = getJiraConnector();
if (connector == null) { if (connector == null) {
throw new ConnectorException(_("JIRA connector not found")); throw new ConnectorException(tr("JIRA connector not found"));
} }
String jiraLabels = connector.getPropertiesAsMap().get( String jiraLabels = connector.getPropertiesAsMap().get(
@ -124,12 +124,12 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
Connector connector = getJiraConnector(); Connector connector = getJiraConnector();
if (connector == null) { if (connector == null) {
throw new ConnectorException(_("JIRA connector not found")); throw new ConnectorException(tr("JIRA connector not found"));
} }
if (!connector.areConnectionValuesValid()) { if (!connector.areConnectionValuesValid()) {
throw new ConnectorException( throw new ConnectorException(
_("Connection values of JIRA connector are invalid")); tr("Connection values of JIRA connector are invalid"));
} }
return getJiraIssues(label, connector); return getJiraIssues(label, connector);
@ -167,7 +167,7 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
@Transactional(readOnly = true) @Transactional(readOnly = true)
public void syncOrderElementsWithJiraIssues(List<IssueDTO> issues, Order order) { public void syncOrderElementsWithJiraIssues(List<IssueDTO> issues, Order order) {
synchronizationInfo = new SynchronizationInfo(_( synchronizationInfo = new SynchronizationInfo(tr(
"Synchronization order {0}", order.getName())); "Synchronization order {0}", order.getName()));
for (IssueDTO issue : issues) { for (IssueDTO issue : issues) {
@ -178,7 +178,7 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
OrderLine orderLine = syncOrderLine(order, code, name); OrderLine orderLine = syncOrderLine(order, code, name);
if (orderLine == null) { if (orderLine == null) {
synchronizationInfo.addFailedReason(_( synchronizationInfo.addFailedReason(tr(
"Order-element for \"{0}\" issue not found", "Order-element for \"{0}\" issue not found",
issue.getKey())); issue.getKey()));
continue; continue;
@ -190,7 +190,7 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
.getTimetracking(), loggedHours); .getTimetracking(), loggedHours);
if (estimatedHours.isZero()) { if (estimatedHours.isZero()) {
synchronizationInfo.addFailedReason(_( synchronizationInfo.addFailedReason(tr(
"Estimated time for \"{0}\" issue is 0", "Estimated time for \"{0}\" issue is 0",
issue.getKey())); issue.getKey()));
continue; continue;
@ -279,14 +279,14 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
WorkLogDTO workLog = issue.getFields().getWorklog(); WorkLogDTO workLog = issue.getFields().getWorklog();
if (workLog == null) { if (workLog == null) {
synchronizationInfo.addFailedReason(_( synchronizationInfo.addFailedReason(tr(
"No worklogs found for \"{0}\" issue", issue.getKey())); "No worklogs found for \"{0}\" issue", issue.getKey()));
return; return;
} }
List<WorkLogItemDTO> workLogItems = workLog.getWorklogs(); List<WorkLogItemDTO> workLogItems = workLog.getWorklogs();
if (workLogItems.isEmpty()) { if (workLogItems.isEmpty()) {
synchronizationInfo.addFailedReason(_( synchronizationInfo.addFailedReason(tr(
"No worklog items found for \"{0}\" issue", "No worklog items found for \"{0}\" issue",
issue.getKey())); issue.getKey()));
return; return;
@ -398,7 +398,7 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
// This could happen if a parent or child of the current // This could happen if a parent or child of the current
// OrderElement has an advance of type PERCENTAGE // OrderElement has an advance of type PERCENTAGE
synchronizationInfo synchronizationInfo
.addFailedReason(_( .addFailedReason(tr(
"Duplicate value AdvanceAssignment for order element of \"{0}\"", "Duplicate value AdvanceAssignment for order element of \"{0}\"",
orderElement.getCode())); orderElement.getCode()));
return; return;
@ -504,24 +504,24 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
public List<SynchronizationInfo> syncOrderElementsWithJiraIssues() throws ConnectorException { public List<SynchronizationInfo> syncOrderElementsWithJiraIssues() throws ConnectorException {
Connector connector = getJiraConnector(); Connector connector = getJiraConnector();
if (connector == null) { if (connector == null) {
throw new ConnectorException(_("JIRA connector not found")); throw new ConnectorException(tr("JIRA connector not found"));
} }
if (!connector.areConnectionValuesValid()) { if (!connector.areConnectionValuesValid()) {
throw new ConnectorException( throw new ConnectorException(
_("Connection values of JIRA connector are invalid")); tr("Connection values of JIRA connector are invalid"));
} }
List<OrderSyncInfo> orderSyncInfos = orderSyncInfoDAO List<OrderSyncInfo> orderSyncInfos = orderSyncInfoDAO
.findByConnectorName(PredefinedConnectors.JIRA.getName()); .findByConnectorName(PredefinedConnectors.JIRA.getName());
synchronizationInfo = new SynchronizationInfo(_("Synchronization")); synchronizationInfo = new SynchronizationInfo(tr("Synchronization"));
List<SynchronizationInfo> syncInfos = new ArrayList<SynchronizationInfo>(); List<SynchronizationInfo> syncInfos = new ArrayList<SynchronizationInfo>();
if (orderSyncInfos == null || orderSyncInfos.isEmpty()) { if (orderSyncInfos == null || orderSyncInfos.isEmpty()) {
LOG.warn("No items found in 'OrderSyncInfo' to synchronize with JIRA issues"); LOG.warn("No items found in 'OrderSyncInfo' to synchronize with JIRA issues");
synchronizationInfo synchronizationInfo
.addFailedReason(_("No items found in 'OrderSyncInfo' to synchronize with JIRA issues")); .addFailedReason(tr("No items found in 'OrderSyncInfo' to synchronize with JIRA issues"));
syncInfos.add(synchronizationInfo); syncInfos.add(synchronizationInfo);
return syncInfos; return syncInfos;
} }
@ -529,7 +529,7 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
for (OrderSyncInfo orderSyncInfo : orderSyncInfos) { for (OrderSyncInfo orderSyncInfo : orderSyncInfos) {
Order order = orderSyncInfo.getOrder(); Order order = orderSyncInfo.getOrder();
LOG.info("Synchronizing '" + order.getName() + "'"); LOG.info("Synchronizing '" + order.getName() + "'");
synchronizationInfo = new SynchronizationInfo(_( synchronizationInfo = new SynchronizationInfo(tr(
"Synchronization order {0}", order.getName())); "Synchronization order {0}", order.getName()));
List<IssueDTO> issueDTOs = getJiraIssues(orderSyncInfo.getKey(), List<IssueDTO> issueDTOs = getJiraIssues(orderSyncInfo.getKey(),
@ -537,7 +537,7 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
if (issueDTOs == null || issueDTOs.isEmpty()) { if (issueDTOs == null || issueDTOs.isEmpty()) {
LOG.warn("No JIRA issues found for '" + orderSyncInfo.getKey() LOG.warn("No JIRA issues found for '" + orderSyncInfo.getKey()
+ "'"); + "'");
synchronizationInfo.addFailedReason(_( synchronizationInfo.addFailedReason(tr(
"No JIRA issues found for key {0}", "No JIRA issues found for key {0}",
orderSyncInfo.getKey())); orderSyncInfo.getKey()));
syncInfos.add(synchronizationInfo); syncInfos.add(synchronizationInfo);

View file

@ -19,7 +19,7 @@
package org.libreplan.importers; package org.libreplan.importers;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper.tr;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -101,14 +101,14 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
@Override @Override
@Transactional @Transactional
public void syncJiraTimesheetWithJiraIssues(List<IssueDTO> issues, Order order) throws ConnectorException { public void syncJiraTimesheetWithJiraIssues(List<IssueDTO> issues, Order order) throws ConnectorException {
synchronizationInfo = new SynchronizationInfo(_("Synchronization")); synchronizationInfo = new SynchronizationInfo(tr("Synchronization"));
workReportType = getJiraTimesheetsWorkReportType(); workReportType = getJiraTimesheetsWorkReportType();
typeOfWorkHours = getTypeOfWorkHours(); typeOfWorkHours = getTypeOfWorkHours();
workers = getWorkers(); workers = getWorkers();
if (workers == null && workers.isEmpty()) { if (workers == null && workers.isEmpty()) {
synchronizationInfo.addFailedReason(_("No workers found")); synchronizationInfo.addFailedReason(tr("No workers found"));
return; return;
} }
@ -117,11 +117,11 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
if (orderSyncInfo == null) { if (orderSyncInfo == null) {
synchronizationInfo.addFailedReason( synchronizationInfo.addFailedReason(
_("Order \"{0}\" not found. Order probalbly not synchronized", order.getName())); tr("Order \"{0}\" not found. Order probalbly not synchronized", order.getName()));
return; return;
} }
if (StringUtils.isBlank(orderSyncInfo.getKey())) { if (StringUtils.isBlank(orderSyncInfo.getKey())) {
synchronizationInfo.addFailedReason(_("Key for Order \"{0}\" is empty", order.getName())); synchronizationInfo.addFailedReason(tr("Key for Order \"{0}\" is empty", order.getName()));
return; return;
} }
@ -132,11 +132,11 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
for (IssueDTO issue : issues) { for (IssueDTO issue : issues) {
WorkLogDTO workLog = issue.getFields().getWorklog(); WorkLogDTO workLog = issue.getFields().getWorklog();
if (workLog == null) { if (workLog == null) {
synchronizationInfo.addFailedReason(_("No worklogs found for \"{0}\" key", issue.getKey())); synchronizationInfo.addFailedReason(tr("No worklogs found for \"{0}\" key", issue.getKey()));
} else { } else {
List<WorkLogItemDTO> workLogItems = workLog.getWorklogs(); List<WorkLogItemDTO> workLogItems = workLog.getWorklogs();
if (workLogItems == null || workLogItems.isEmpty()) { if (workLogItems == null || workLogItems.isEmpty()) {
synchronizationInfo.addFailedReason(_("No worklog items found for \"{0}\" issue", issue.getKey())); synchronizationInfo.addFailedReason(tr("No worklog items found for \"{0}\" issue", issue.getKey()));
} else { } else {
String codeOrderElement = String codeOrderElement =
@ -145,7 +145,7 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
OrderElement orderElement = order.getOrderElement(codeOrderElement); OrderElement orderElement = order.getOrderElement(codeOrderElement);
if (orderElement == null) { if (orderElement == null) {
synchronizationInfo.addFailedReason(_("Order element \"{0}\" not found", code)); synchronizationInfo.addFailedReason(tr("Order element \"{0}\" not found", code));
} else { } else {
updateOrCreateWorkReportLineAndAddToWorkReport(workReport, orderElement, workLogItems); updateOrCreateWorkReportLineAndAddToWorkReport(workReport, orderElement, workLogItems);
} }
@ -297,14 +297,14 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
private TypeOfWorkHours getTypeOfWorkHours() throws ConnectorException { private TypeOfWorkHours getTypeOfWorkHours() throws ConnectorException {
Connector connector = connectorDAO.findUniqueByName(PredefinedConnectors.JIRA.getName()); Connector connector = connectorDAO.findUniqueByName(PredefinedConnectors.JIRA.getName());
if (connector == null) { if (connector == null) {
throw new ConnectorException(_("JIRA connector not found")); throw new ConnectorException(tr("JIRA connector not found"));
} }
TypeOfWorkHours typeOfWorkHours; TypeOfWorkHours typeOfWorkHours;
String name = connector.getPropertiesAsMap().get(PredefinedConnectorProperties.JIRA_HOURS_TYPE); String name = connector.getPropertiesAsMap().get(PredefinedConnectorProperties.JIRA_HOURS_TYPE);
if (StringUtils.isBlank(name)) { if (StringUtils.isBlank(name)) {
throw new ConnectorException(_("Hours type should not be empty to synchronine timesheets")); throw new ConnectorException(tr("Hours type should not be empty to synchronine timesheets"));
} }
try { try {
@ -354,7 +354,7 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
return worker; return worker;
} }
} }
synchronizationInfo.addFailedReason(_("Worker \"{0}\" not found", nif)); synchronizationInfo.addFailedReason(tr("Worker \"{0}\" not found", nif));
return null; return null;
} }

View file

@ -19,7 +19,7 @@
package org.libreplan.importers; package org.libreplan.importers;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper.tr;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
@ -605,6 +605,6 @@ public class OrderImporterMPXJ implements IOrderImporter {
} }
} }
throw new ValidationException(_("Linked calendar not found")); throw new ValidationException(tr("Linked calendar not found"));
} }
} }

Some files were not shown because too many files have changed in this diff Show more