Compare commits
38 Commits
v2.0.2
...
feature/pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f20353674 | ||
|
|
bef69da0d1 | ||
|
|
f80ec9797e | ||
|
|
fbbd820512 | ||
|
|
5d0777f67c | ||
|
|
f1d504f985 | ||
|
|
6a4d77d904 | ||
|
|
c35d53266a | ||
|
|
dc096f5e12 | ||
|
|
a681aadcfa | ||
|
|
f15f3f5110 | ||
|
|
07ae71fd23 | ||
|
|
26270b2842 | ||
|
|
0d0596b767 | ||
|
|
eca7af2d6f | ||
|
|
3ace14fcdb | ||
|
|
99bec6c7f9 | ||
|
|
ef299f1f4a | ||
|
|
66b0709e6e | ||
|
|
a2ed33214d | ||
|
|
a3dccd690d | ||
|
|
69313fba34 | ||
|
|
1889c58598 | ||
|
|
e9f0162439 | ||
|
|
323b17185c | ||
|
|
09f44a5685 | ||
|
|
f4ab7841fb | ||
|
|
3de4f69a62 | ||
|
|
102be2c24a | ||
|
|
3a39b25e64 | ||
|
|
32248f8424 | ||
|
|
a1f8776743 | ||
|
|
7e431d645a | ||
|
|
cef4bffd69 | ||
|
|
51767ebbdb | ||
|
|
ad91148616 | ||
|
|
38df66044d | ||
|
|
75391641fd |
35
README.md
35
README.md
@@ -1,6 +1,6 @@
|
||||
<h1 align="center">
|
||||
<a href="https://worklenz.com" target="_blank" rel="noopener noreferrer">
|
||||
<img src="https://app.worklenz.com/assets/icons/icon-144x144.png" alt="Worklenz Logo" width="75">
|
||||
<img src="https://s3.us-west-2.amazonaws.com/worklenz.com/assets/icon-144x144.png" alt="Worklenz Logo" width="75">
|
||||
</a>
|
||||
<br>
|
||||
Worklenz
|
||||
@@ -69,8 +69,7 @@ cd worklenz
|
||||
2. Set up environment variables
|
||||
- Copy the example environment files
|
||||
```bash
|
||||
cp .env.example .env
|
||||
cp worklenz-backend/.env.example worklenz-backend/.env
|
||||
cp worklenz-backend/.env.template worklenz-backend/.env
|
||||
```
|
||||
- Update the environment variables with your configuration
|
||||
|
||||
@@ -192,6 +191,27 @@ Email [info@worklenz.com](mailto:info@worklenz.com) to disclose any security vul
|
||||
|
||||
This project is licensed under the [MIT License](LICENSE).
|
||||
|
||||
## Analytics
|
||||
|
||||
Worklenz uses Google Analytics to understand how the application is being used. This helps us improve the application and make better decisions about future development.
|
||||
|
||||
### What We Track
|
||||
- Anonymous usage statistics
|
||||
- Page views and navigation patterns
|
||||
- Feature usage
|
||||
- Browser and device information
|
||||
|
||||
### Privacy
|
||||
- Analytics is opt-in only
|
||||
- No personal information is collected
|
||||
- Users can opt-out at any time
|
||||
- Data is stored according to Google's privacy policy
|
||||
|
||||
### How to Opt-Out
|
||||
If you've previously opted in and want to opt-out:
|
||||
1. Clear your browser's local storage for the Worklenz domain
|
||||
2. Or click the "Decline" button in the analytics notice if it appears
|
||||
|
||||
## Screenshots
|
||||
|
||||
<p align="center">
|
||||
@@ -315,6 +335,7 @@ docker-compose up -d
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
|
||||
## MinIO Integration
|
||||
|
||||
The project uses MinIO as an S3-compatible object storage service, which provides an open-source alternative to AWS S3 for development and production.
|
||||
@@ -403,6 +424,10 @@ This script generates properly configured environment files for both development
|
||||
- Frontend: http://localhost:5000
|
||||
- Backend API: http://localhost:3000 (or https://localhost:3000 with SSL)
|
||||
|
||||
4. Video Guide
|
||||
|
||||
For a visual walkthrough of the local Docker deployment process, check out our [step-by-step video guide](https://www.youtube.com/watch?v=AfwAKxJbqLg).
|
||||
|
||||
### Remote Server Deployment
|
||||
|
||||
When deploying to a remote server:
|
||||
@@ -428,6 +453,10 @@ When deploying to a remote server:
|
||||
- Frontend: http://your-server-hostname:5000
|
||||
- Backend API: http://your-server-hostname:3000
|
||||
|
||||
4. Video Guide
|
||||
|
||||
For a complete walkthrough of deploying Worklenz to a remote server, check out our [deployment video guide](https://www.youtube.com/watch?v=CAZGu2iOXQs&t=10s).
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
The Docker setup uses environment variables to configure the services:
|
||||
|
||||
@@ -7,15 +7,17 @@ services:
|
||||
ports:
|
||||
- "5000:5000"
|
||||
depends_on:
|
||||
backend:
|
||||
condition: service_started
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- ./worklenz-frontend/.env.production
|
||||
networks:
|
||||
- worklenz
|
||||
|
||||
backend:
|
||||
image: docker.io/chamikajaycey/worklenz-backend:latest
|
||||
build:
|
||||
context: ./worklenz-backend
|
||||
dockerfile: Dockerfile
|
||||
container_name: worklenz_backend
|
||||
ports:
|
||||
- "3000:3000"
|
||||
@@ -24,6 +26,7 @@ services:
|
||||
condition: service_healthy
|
||||
minio:
|
||||
condition: service_started
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- ./worklenz-backend/.env
|
||||
networks:
|
||||
@@ -35,6 +38,7 @@ services:
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${S3_ACCESS_KEY_ID:-minioadmin}
|
||||
MINIO_ROOT_PASSWORD: ${S3_SECRET_ACCESS_KEY:-minioadmin}
|
||||
@@ -50,29 +54,27 @@ services:
|
||||
container_name: worklenz_createbuckets
|
||||
depends_on:
|
||||
- minio
|
||||
restart: on-failure
|
||||
entrypoint: >
|
||||
/bin/sh -c "
|
||||
# Wait for MinIO to be available
|
||||
echo 'Waiting for MinIO to start...'
|
||||
sleep 15;
|
||||
# Retry up to 5 times
|
||||
for i in 1 2 3 4 5; do
|
||||
echo \"Attempt $$i to connect to MinIO...\"
|
||||
if /usr/bin/mc config host add myminio http://minio:9000 minioadmin minioadmin; then
|
||||
echo \"Successfully connected to MinIO!\"
|
||||
/usr/bin/mc mb --ignore-existing myminio/worklenz-bucket;
|
||||
/usr/bin/mc policy set public myminio/worklenz-bucket;
|
||||
exit 0;
|
||||
fi
|
||||
echo \"Connection failed, retrying in 5 seconds...\"
|
||||
sleep 5;
|
||||
done
|
||||
echo \"Failed to connect to MinIO after 5 attempts\"
|
||||
exit 1;
|
||||
"
|
||||
/bin/sh -c '
|
||||
echo "Waiting for MinIO to start...";
|
||||
sleep 15;
|
||||
for i in 1 2 3 4 5; do
|
||||
echo "Attempt $i to connect to MinIO...";
|
||||
if /usr/bin/mc alias set myminio http://minio:9000 minioadmin minioadmin; then
|
||||
echo "Successfully connected to MinIO!";
|
||||
/usr/bin/mc mb --ignore-existing myminio/worklenz-bucket;
|
||||
/usr/bin/mc policy set public myminio/worklenz-bucket;
|
||||
exit 0;
|
||||
fi
|
||||
echo "Connection failed, retrying in 5 seconds...";
|
||||
sleep 5;
|
||||
done;
|
||||
echo "Failed to connect to MinIO after 5 attempts";
|
||||
exit 1;
|
||||
'
|
||||
networks:
|
||||
- worklenz
|
||||
|
||||
db:
|
||||
image: postgres:15
|
||||
container_name: worklenz_db
|
||||
@@ -85,6 +87,7 @@ services:
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- worklenz
|
||||
volumes:
|
||||
@@ -94,22 +97,19 @@ services:
|
||||
target: /docker-entrypoint-initdb.d
|
||||
consistency: cached
|
||||
command: >
|
||||
bash -c '
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
bash -c ' if command -v apt-get >/dev/null 2>&1; then
|
||||
apt-get update && apt-get install -y dos2unix
|
||||
elif command -v apk >/dev/null 2>&1; then
|
||||
apk add --no-cache dos2unix
|
||||
fi &&
|
||||
find /docker-entrypoint-initdb.d -type f -name "*.sh" -exec sh -c '\''
|
||||
fi && find /docker-entrypoint-initdb.d -type f -name "*.sh" -exec sh -c '\''
|
||||
dos2unix "{}" 2>/dev/null || true
|
||||
chmod +x "{}"
|
||||
'\'' \; &&
|
||||
exec docker-entrypoint.sh postgres
|
||||
'
|
||||
'\'' \; && exec docker-entrypoint.sh postgres '
|
||||
|
||||
volumes:
|
||||
worklenz_postgres_data:
|
||||
worklenz_minio_data:
|
||||
|
||||
|
||||
networks:
|
||||
worklenz:
|
||||
|
||||
@@ -73,13 +73,21 @@ cat > worklenz-backend/.env << EOL
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
SESSION_NAME=worklenz.sid
|
||||
SESSION_SECRET=change_me_in_production
|
||||
COOKIE_SECRET=change_me_in_production
|
||||
SESSION_SECRET=$(openssl rand -base64 48)
|
||||
COOKIE_SECRET=$(openssl rand -base64 48)
|
||||
|
||||
# CORS
|
||||
SOCKET_IO_CORS=${FRONTEND_URL}
|
||||
SERVER_CORS=${FRONTEND_URL}
|
||||
|
||||
|
||||
# Google Login
|
||||
GOOGLE_CLIENT_ID="your_google_client_id"
|
||||
GOOGLE_CLIENT_SECRET="your_google_client_secret"
|
||||
GOOGLE_CALLBACK_URL="${FRONTEND_URL}/secure/google/verify"
|
||||
LOGIN_FAILURE_REDIRECT="${FRONTEND_URL}/auth/authenticating"
|
||||
LOGIN_SUCCESS_REDIRECT="${FRONTEND_URL}/auth/authenticating"
|
||||
|
||||
# Database
|
||||
DB_HOST=db
|
||||
DB_PORT=5432
|
||||
@@ -115,7 +123,7 @@ SLACK_WEBHOOK=
|
||||
COMMIT_BUILD_IMMEDIATELY=true
|
||||
|
||||
# JWT Secret
|
||||
JWT_SECRET=change_me_in_production
|
||||
JWT_SECRET=$(openssl rand -base64 48)
|
||||
EOL
|
||||
|
||||
echo "Environment configuration updated for ${HOSTNAME} with" $([ "$USE_SSL" = "true" ] && echo "HTTPS/WSS" || echo "HTTP/WS")
|
||||
@@ -130,4 +138,4 @@ echo "Frontend URL: ${FRONTEND_URL}"
|
||||
echo "API URL: ${HTTP_PREFIX}${HOSTNAME}:3000"
|
||||
echo "Socket URL: ${WS_PREFIX}${HOSTNAME}:3000"
|
||||
echo "MinIO Dashboard URL: ${MINIO_DASHBOARD_URL}"
|
||||
echo "CORS is configured to allow requests from: ${FRONTEND_URL}"
|
||||
echo "CORS is configured to allow requests from: ${FRONTEND_URL}"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
build
|
||||
.scannerwork
|
||||
coverage
|
||||
.dockerignore
|
||||
.git
|
||||
*.md
|
||||
tests
|
||||
|
||||
|
||||
@@ -1,26 +1,39 @@
|
||||
# Use the official Node.js 20 image as a base
|
||||
FROM node:20
|
||||
# --- Stage 1: Build ---
|
||||
FROM node:20-slim AS builder
|
||||
|
||||
ARG RELEASE_VERSION
|
||||
RUN apt-get update && apt-get install -y \
|
||||
python3 \
|
||||
make \
|
||||
g++ \
|
||||
curl \
|
||||
postgresql-server-dev-all \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Create and set the working directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Install global dependencies
|
||||
RUN npm install -g ts-node typescript grunt grunt-cli
|
||||
|
||||
# Copy package.json and package-lock.json (if available)
|
||||
COPY package*.json ./
|
||||
|
||||
# Install app dependencies
|
||||
RUN npm ci
|
||||
|
||||
# Copy the rest of the application code
|
||||
COPY . .
|
||||
|
||||
# Run the build script to compile TypeScript to JavaScript
|
||||
RUN npm run build
|
||||
|
||||
# Expose the port the app runs on
|
||||
EXPOSE 3000
|
||||
RUN echo "$RELEASE_VERSION" > release
|
||||
|
||||
# --- Stage 2: Production Image ---
|
||||
FROM node:20-slim
|
||||
|
||||
RUN apt-get update && apt-get install -y libpq5 && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /usr/src/app/package*.json ./
|
||||
COPY --from=builder /usr/src/app/build ./build
|
||||
COPY --from=builder /usr/src/app/node_modules ./node_modules
|
||||
COPY --from=builder /usr/src/app/release ./release
|
||||
COPY --from=builder /usr/src/app/worklenz-email-templates ./worklenz-email-templates
|
||||
|
||||
|
||||
EXPOSE 3000
|
||||
CMD ["node", "build/bin/www"]
|
||||
|
||||
# Start the application
|
||||
CMD ["npm", "start"]
|
||||
@@ -12,7 +12,7 @@ CREATE TYPE DEPENDENCY_TYPE AS ENUM ('blocked_by');
|
||||
|
||||
CREATE TYPE SCHEDULE_TYPE AS ENUM ('daily', 'weekly', 'yearly', 'monthly', 'every_x_days', 'every_x_weeks', 'every_x_months');
|
||||
|
||||
CREATE TYPE LANGUAGE_TYPE AS ENUM ('en', 'es', 'pt');
|
||||
CREATE TYPE LANGUAGE_TYPE AS ENUM ('en', 'es', 'pt', 'alb', 'de');
|
||||
|
||||
-- START: Users
|
||||
CREATE SEQUENCE IF NOT EXISTS users_user_no_seq START 1;
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import moment from "moment";
|
||||
import {IWorkLenzRequest} from "../interfaces/worklenz-request";
|
||||
import {IWorkLenzResponse} from "../interfaces/worklenz-response";
|
||||
|
||||
import Excel from "exceljs";
|
||||
import { IWorkLenzRequest } from "../interfaces/worklenz-request";
|
||||
import { IWorkLenzResponse } from "../interfaces/worklenz-response";
|
||||
import db from "../config/db";
|
||||
|
||||
import {ServerResponse} from "../models/server-response";
|
||||
import { ServerResponse } from "../models/server-response";
|
||||
import WorklenzControllerBase from "./worklenz-controller-base";
|
||||
import HandleExceptions from "../decorators/handle-exceptions";
|
||||
import {formatDuration, formatLogText, getColor} from "../shared/utils";
|
||||
import { formatDuration, formatLogText, getColor } from "../shared/utils";
|
||||
|
||||
export default class ActivitylogsController extends WorklenzControllerBase {
|
||||
@HandleExceptions()
|
||||
public static async get(req: IWorkLenzRequest, res: IWorkLenzResponse): Promise<IWorkLenzResponse> {
|
||||
const {id} = req.params;
|
||||
const { id } = req.params;
|
||||
const q = `SELECT get_activity_logs_by_task($1) AS activity_logs;`;
|
||||
const result = await db.query(q, [id]);
|
||||
const [data] = result.rows;
|
||||
@@ -31,4 +30,196 @@ export default class ActivitylogsController extends WorklenzControllerBase {
|
||||
|
||||
return res.status(200).send(new ServerResponse(true, data.activity_logs));
|
||||
}
|
||||
}
|
||||
|
||||
@HandleExceptions()
|
||||
public static async getByProjectId(req: IWorkLenzRequest, res: IWorkLenzResponse): Promise<IWorkLenzResponse> {
|
||||
try {
|
||||
console.log("Received request for project activity logs:", req.params, req.query);
|
||||
const projectId = req.params.id;
|
||||
const page = parseInt(req.query.page as string) || 1;
|
||||
const size = parseInt(req.query.size as string) || 20;
|
||||
const offset = (page - 1) * size;
|
||||
const filterType = req.query.filter as string || "all";
|
||||
|
||||
// Add filter conditions
|
||||
let filterClause = "";
|
||||
const filterParams = [projectId];
|
||||
let paramIndex = 2;
|
||||
|
||||
if (filterType && filterType !== "all") {
|
||||
filterClause = ` AND tal.attribute_type = $${paramIndex}`;
|
||||
filterParams.push(filterType);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
// Defensive UUID regex for safe casting
|
||||
const uuidRegex = "'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'";
|
||||
|
||||
const q = `
|
||||
SELECT
|
||||
tal.id,
|
||||
tal.task_id,
|
||||
tal.attribute_type,
|
||||
tal.log_type,
|
||||
tal.old_value,
|
||||
tal.new_value,
|
||||
tal.prev_string,
|
||||
tal.next_string,
|
||||
tal.created_at,
|
||||
|
||||
-- Task details
|
||||
(SELECT name FROM tasks WHERE id = tal.task_id) AS task_name,
|
||||
(SELECT task_no FROM tasks WHERE id = tal.task_id) AS task_no,
|
||||
CONCAT((SELECT key FROM projects WHERE id = $1), '-', (SELECT task_no FROM tasks WHERE id = tal.task_id)) AS task_key,
|
||||
|
||||
-- User details
|
||||
(SELECT ROW_TO_JSON(user_data) FROM (
|
||||
SELECT
|
||||
u.id,
|
||||
u.name,
|
||||
u.avatar_url,
|
||||
u.email
|
||||
FROM users u
|
||||
WHERE u.id = tal.user_id
|
||||
) user_data) AS done_by,
|
||||
|
||||
-- Status details for status changes (safe UUID cast)
|
||||
CASE
|
||||
WHEN tal.attribute_type = 'status' AND tal.old_value ~ ${uuidRegex} THEN
|
||||
(SELECT ROW_TO_JSON(status_data) FROM (
|
||||
SELECT
|
||||
ts.name
|
||||
FROM task_statuses ts
|
||||
WHERE ts.id = tal.old_value::UUID
|
||||
) status_data)
|
||||
ELSE NULL
|
||||
END AS previous_status,
|
||||
|
||||
CASE
|
||||
WHEN tal.attribute_type = 'status' AND tal.new_value ~ ${uuidRegex} THEN
|
||||
(SELECT ROW_TO_JSON(status_data) FROM (
|
||||
SELECT
|
||||
ts.name
|
||||
FROM task_statuses ts
|
||||
WHERE ts.id = tal.new_value::UUID
|
||||
) status_data)
|
||||
ELSE NULL
|
||||
END AS next_status,
|
||||
|
||||
-- Priority details for priority changes (safe UUID cast)
|
||||
CASE
|
||||
WHEN tal.attribute_type = 'priority' AND tal.old_value ~ ${uuidRegex} THEN
|
||||
(SELECT ROW_TO_JSON(priority_data) FROM (
|
||||
SELECT
|
||||
tp.name
|
||||
FROM task_priorities tp
|
||||
WHERE tp.id = tal.old_value::UUID
|
||||
) priority_data)
|
||||
ELSE NULL
|
||||
END AS previous_priority,
|
||||
|
||||
CASE
|
||||
WHEN tal.attribute_type = 'priority' AND tal.new_value ~ ${uuidRegex} THEN
|
||||
(SELECT ROW_TO_JSON(priority_data) FROM (
|
||||
SELECT
|
||||
tp.name
|
||||
FROM task_priorities tp
|
||||
WHERE tp.id = tal.new_value::UUID
|
||||
) priority_data)
|
||||
ELSE NULL
|
||||
END AS next_priority,
|
||||
|
||||
-- Assigned user details for assignee changes (safe UUID cast)
|
||||
CASE
|
||||
WHEN tal.attribute_type = 'assignee' AND tal.new_value ~ ${uuidRegex} THEN
|
||||
(SELECT ROW_TO_JSON(user_data) FROM (
|
||||
SELECT
|
||||
u.id,
|
||||
u.name,
|
||||
u.avatar_url,
|
||||
u.email
|
||||
FROM users u
|
||||
WHERE u.id = tal.new_value::UUID
|
||||
) user_data)
|
||||
ELSE NULL
|
||||
END AS assigned_user
|
||||
|
||||
FROM task_activity_logs tal
|
||||
WHERE tal.project_id = $1${filterClause}
|
||||
ORDER BY tal.created_at DESC
|
||||
LIMIT $${paramIndex} OFFSET $${paramIndex + 1}
|
||||
`;
|
||||
|
||||
const countQuery = `
|
||||
SELECT COUNT(*) as total
|
||||
FROM task_activity_logs
|
||||
WHERE project_id = $1${filterClause}
|
||||
`;
|
||||
|
||||
const [result, countResult] = await Promise.all([
|
||||
db.query(q, [...filterParams, size, offset]),
|
||||
db.query(countQuery, filterType && filterType !== "all" ? [projectId, filterType] : [projectId])
|
||||
]);
|
||||
|
||||
const total = parseInt(countResult.rows[0]?.total || "0");
|
||||
|
||||
// Format the logs
|
||||
for (const log of result.rows) {
|
||||
if (log.attribute_type === "estimation") {
|
||||
log.previous = formatDuration(moment.duration(log.old_value, "minutes"));
|
||||
log.current = formatDuration(moment.duration(log.new_value, "minutes"));
|
||||
} else {
|
||||
log.previous = log.old_value;
|
||||
log.current = log.new_value;
|
||||
}
|
||||
|
||||
// Add color to users
|
||||
if (log.assigned_user) {
|
||||
log.assigned_user.color_code = getColor(log.assigned_user.name);
|
||||
}
|
||||
|
||||
if (log.done_by) {
|
||||
log.done_by.color_code = getColor(log.done_by.name);
|
||||
}
|
||||
|
||||
// Add default colors for status and priority since table doesn't have color_code
|
||||
if (log.previous_status) {
|
||||
log.previous_status.color_code = "#d9d9d9"; // Default gray color
|
||||
}
|
||||
if (log.next_status) {
|
||||
log.next_status.color_code = "#1890ff"; // Default blue color
|
||||
}
|
||||
if (log.previous_priority) {
|
||||
log.previous_priority.color_code = "#d9d9d9"; // Default gray color
|
||||
}
|
||||
if (log.next_priority) {
|
||||
log.next_priority.color_code = "#ff4d4f"; // Default red color for priority
|
||||
}
|
||||
|
||||
// Generate log text
|
||||
log.log_text = await formatLogText(log);
|
||||
log.attribute_type = log.attribute_type?.replace(/_/g, " ");
|
||||
}
|
||||
|
||||
const response = {
|
||||
logs: result.rows,
|
||||
pagination: {
|
||||
current: page,
|
||||
pageSize: size,
|
||||
total,
|
||||
totalPages: Math.ceil(total / size)
|
||||
}
|
||||
};
|
||||
|
||||
return res.status(200).send(new ServerResponse(true, response));
|
||||
} catch (error: any) {
|
||||
console.error("❌ Error in getByProjectId:", error);
|
||||
return res.status(500).send(new ServerResponse(false, null, `Internal server error: ${error.message}`));
|
||||
}
|
||||
}
|
||||
|
||||
@HandleExceptions()
|
||||
public static async exportProjectActivityLogs(req: IWorkLenzRequest, res: IWorkLenzResponse): Promise<void> {
|
||||
// ...keep your export logic as is...
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
import { IWorkLenzRequest } from "../interfaces/worklenz-request";
|
||||
import { IWorkLenzResponse } from "../interfaces/worklenz-response";
|
||||
import moment from "moment";
|
||||
import db from "../config/db";
|
||||
import { ServerResponse } from "../models/server-response";
|
||||
import WorklenzControllerBase from "./worklenz-controller-base";
|
||||
import HandleExceptions from "../decorators/handle-exceptions";
|
||||
|
||||
// --- Helpers -------------------------------------------------------------
|
||||
|
||||
function formatDuration(duration: moment.Duration | null): string {
|
||||
if (!duration) return "0m";
|
||||
const hours = Math.floor(duration.asHours());
|
||||
const minutes = duration.minutes();
|
||||
return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;
|
||||
}
|
||||
|
||||
function generateLogText(attributeType: string): string {
|
||||
const map: Record<string,string> = {
|
||||
name: "updated task name",
|
||||
status: "changed status",
|
||||
priority: "changed priority",
|
||||
assignee: "updated assignee",
|
||||
end_date: "changed due date",
|
||||
start_date: "changed start date",
|
||||
estimation: "updated time estimation",
|
||||
description: "updated description",
|
||||
phase: "changed phase",
|
||||
labels: "updated labels",
|
||||
};
|
||||
return map[attributeType] || "made changes to";
|
||||
}
|
||||
|
||||
function isValidUuid(id?: string): boolean {
|
||||
return !!id && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
|
||||
}
|
||||
|
||||
// Get a consistent color for a user based on their name
|
||||
function getColorFromName(name: string): string {
|
||||
if (!name) return "#1890ff";
|
||||
|
||||
const colors = [
|
||||
"#f56a00", "#7265e6", "#ffbf00", "#00a2ae",
|
||||
"#1890ff", "#52c41a", "#eb2f96", "#faad14",
|
||||
"#722ed1", "#13c2c2", "#fa8c16", "#a0d911"
|
||||
];
|
||||
|
||||
let hash = 0;
|
||||
for (let i = 0; i < name.length; i++) {
|
||||
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
||||
}
|
||||
|
||||
return colors[Math.abs(hash) % colors.length];
|
||||
}
|
||||
|
||||
// --- Controller ----------------------------------------------------------
|
||||
|
||||
export default class ProjectActivityLogsController extends WorklenzControllerBase {
|
||||
@HandleExceptions()
|
||||
public static async getByProjectId(
|
||||
req: IWorkLenzRequest,
|
||||
res: IWorkLenzResponse
|
||||
): Promise<IWorkLenzResponse> {
|
||||
// 1) Extract & validate inputs
|
||||
const projectId = req.params.id;
|
||||
if (!isValidUuid(projectId)) {
|
||||
return res
|
||||
.status(400)
|
||||
.json({ done: false, body: null, error: "Invalid project ID." });
|
||||
}
|
||||
|
||||
const page = parseInt(req.query.page as string, 10) || 1;
|
||||
const size = parseInt(req.query.size as string, 10) || 20;
|
||||
const offset = (page - 1) * size;
|
||||
const filterType = (req.query.filter as string) || "all";
|
||||
const allowedFilters = [
|
||||
"all","name","status","priority","assignee",
|
||||
"end_date","start_date","estimation","description","phase"
|
||||
];
|
||||
if (!allowedFilters.includes(filterType)) {
|
||||
return res
|
||||
.status(400)
|
||||
.json({ done: false, body: null, error: "Invalid filter type." });
|
||||
}
|
||||
|
||||
// 2) Build parameterized SQL
|
||||
let mainQuery = `
|
||||
SELECT
|
||||
tal.id,
|
||||
tal.task_id,
|
||||
tal.user_id,
|
||||
tal.attribute_type,
|
||||
tal.log_type,
|
||||
tal.old_value,
|
||||
tal.new_value,
|
||||
tal.prev_string,
|
||||
tal.next_string,
|
||||
tal.created_at,
|
||||
t.name AS task_name,
|
||||
t.task_no AS task_no,
|
||||
p.key AS project_key,
|
||||
|
||||
-- Include user details directly
|
||||
u.id AS user_id,
|
||||
u.name AS user_name,
|
||||
u.email AS user_email,
|
||||
u.avatar_url AS user_avatar_url
|
||||
FROM task_activity_logs tal
|
||||
LEFT JOIN tasks t ON tal.task_id = t.id
|
||||
LEFT JOIN projects p ON tal.project_id = p.id
|
||||
LEFT JOIN users u ON tal.user_id = u.id
|
||||
WHERE tal.project_id = $1
|
||||
`;
|
||||
|
||||
const queryParams: any[] = [projectId];
|
||||
if (filterType !== "all") {
|
||||
mainQuery += ` AND tal.attribute_type = $2`;
|
||||
queryParams.push(filterType);
|
||||
}
|
||||
mainQuery += ` ORDER BY tal.created_at DESC`;
|
||||
// placeholders for LIMIT / OFFSET
|
||||
const limitIdx = queryParams.length + 1;
|
||||
const offsetIdx = queryParams.length + 2;
|
||||
mainQuery += ` LIMIT $${limitIdx} OFFSET $${offsetIdx}`;
|
||||
queryParams.push(size, offset);
|
||||
|
||||
// Count query
|
||||
const countQuery = `
|
||||
SELECT COUNT(*) AS total
|
||||
FROM task_activity_logs tal
|
||||
WHERE tal.project_id = $1
|
||||
`;
|
||||
const countParams = filterType !== "all"
|
||||
? [projectId, filterType]
|
||||
: [projectId];
|
||||
|
||||
try {
|
||||
// 3) Execute SQL
|
||||
const [dataResult, countResult] = await Promise.all([
|
||||
db.query(mainQuery, queryParams),
|
||||
db.query(
|
||||
countQuery + (filterType !== "all" ? ` AND tal.attribute_type = $2` : ""),
|
||||
countParams
|
||||
),
|
||||
]);
|
||||
|
||||
const total = parseInt(countResult.rows[0]?.total || "0", 10);
|
||||
|
||||
// 4) Transform rows
|
||||
const rows = dataResult.rows;
|
||||
const logs = await Promise.all(rows.map(async (r: any) => {
|
||||
const log: any = { ...r };
|
||||
// Correctly structure user information
|
||||
log.done_by = {
|
||||
id: r.user_id || "",
|
||||
name: r.user_name || "Unknown User",
|
||||
avatar_url: r.user_avatar_url,
|
||||
email: r.user_email || "",
|
||||
color_code: r.user_name ? getColorFromName(r.user_name) : "#1890ff"
|
||||
};
|
||||
// task key
|
||||
log.task_key = r.project_key && r.task_no ?
|
||||
`${r.project_key}-${r.task_no}` :
|
||||
`TASK-${r.task_id?.substring(0, 8) || "unknown"}`;
|
||||
|
||||
// duration / estimation formatting
|
||||
if (log.attribute_type === "estimation") {
|
||||
const oldMin = parseInt(log.old_value, 10);
|
||||
const newMin = parseInt(log.new_value, 10);
|
||||
log.previous = !isNaN(oldMin)
|
||||
? formatDuration(moment.duration(oldMin, "minutes"))
|
||||
: log.old_value;
|
||||
log.current = !isNaN(newMin)
|
||||
? formatDuration(moment.duration(newMin, "minutes"))
|
||||
: log.new_value;
|
||||
} else {
|
||||
log.previous = log.old_value;
|
||||
log.current = log.new_value;
|
||||
}
|
||||
// human‐friendly action
|
||||
log.log_text = generateLogText(r.attribute_type);
|
||||
|
||||
// Handle status changes
|
||||
if (log.attribute_type === "status" && log.old_value && isValidUuid(log.old_value)) {
|
||||
try {
|
||||
const prevStatus = await db.query(
|
||||
`SELECT name, color_code FROM task_statuses WHERE id = $1`,
|
||||
[log.old_value]
|
||||
);
|
||||
if (prevStatus.rows.length > 0) {
|
||||
log.previous_status = {
|
||||
name: prevStatus.rows[0].name,
|
||||
color_code: prevStatus.rows[0].color_code || "#d9d9d9"
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error fetching previous status:", err);
|
||||
}
|
||||
}
|
||||
|
||||
if (log.attribute_type === "status" && log.new_value && isValidUuid(log.new_value)) {
|
||||
try {
|
||||
const nextStatus = await db.query(
|
||||
`SELECT name, color_code FROM task_statuses WHERE id = $1`,
|
||||
[log.new_value]
|
||||
);
|
||||
if (nextStatus.rows.length > 0) {
|
||||
log.next_status = {
|
||||
name: nextStatus.rows[0].name,
|
||||
color_code: nextStatus.rows[0].color_code || "#1890ff"
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error fetching next status:", err);
|
||||
}
|
||||
}
|
||||
// Handle priority changes
|
||||
if (log.attribute_type === "priority" && log.old_value && isValidUuid(log.old_value)) {
|
||||
try {
|
||||
const prevPriority = await db.query(
|
||||
`SELECT name, color_code FROM task_priorities WHERE id = $1`,
|
||||
[log.old_value]
|
||||
);
|
||||
if (prevPriority.rows.length > 0) {
|
||||
log.previous_priority = {
|
||||
name: prevPriority.rows[0].name,
|
||||
color_code: prevPriority.rows[0].color_code || "#d9d9d9"
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error fetching previous priority:", err);
|
||||
}
|
||||
}
|
||||
|
||||
if (log.attribute_type === "priority" && log.new_value && isValidUuid(log.new_value)) {
|
||||
try {
|
||||
const nextPriority = await db.query(
|
||||
`SELECT name, color_code FROM task_priorities WHERE id = $1`,
|
||||
[log.new_value]
|
||||
);
|
||||
if (nextPriority.rows.length > 0) {
|
||||
log.next_priority = {
|
||||
name: nextPriority.rows[0].name,
|
||||
color_code: nextPriority.rows[0].color_code || "#ff4d4f"
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error fetching next priority:", err);
|
||||
}
|
||||
}
|
||||
// Handle assignee changes
|
||||
if (log.attribute_type === "assignee" && log.new_value && isValidUuid(log.new_value)) {
|
||||
try {
|
||||
const assignedUser = await db.query(
|
||||
`SELECT id, name, avatar_url, email FROM users WHERE id = $1`,
|
||||
[log.new_value]
|
||||
);
|
||||
if (assignedUser.rows.length > 0) {
|
||||
log.assigned_user = {
|
||||
...assignedUser.rows[0],
|
||||
color_code: getColorFromName(assignedUser.rows[0].name)
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Error fetching assigned user:", err);
|
||||
}
|
||||
}
|
||||
|
||||
return log;
|
||||
}));
|
||||
|
||||
// 5) Send back a clean response
|
||||
const response = {
|
||||
logs,
|
||||
pagination: {
|
||||
current: page,
|
||||
pageSize: size,
|
||||
total,
|
||||
totalPages: Math.ceil(total / size),
|
||||
}
|
||||
};
|
||||
|
||||
return res.status(200).send(new ServerResponse(true, response));
|
||||
} catch (err) {
|
||||
console.error("🔥 getByProjectId error:", err);
|
||||
return res.status(500).send(
|
||||
new ServerResponse(false, null, "Internal server error fetching logs.")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,5 +7,7 @@ import safeControllerFunction from "../../shared/safe-controller-function";
|
||||
const activityLogsApiRouter = express.Router();
|
||||
|
||||
activityLogsApiRouter.get("/:id", idParamValidator, safeControllerFunction(ActivitylogsController.get));
|
||||
activityLogsApiRouter.get("/project/:id", idParamValidator, safeControllerFunction(ActivitylogsController.getByProjectId));
|
||||
activityLogsApiRouter.get("/project/:id/export", safeControllerFunction(ActivitylogsController.exportProjectActivityLogs));
|
||||
|
||||
export default activityLogsApiRouter;
|
||||
|
||||
@@ -1,120 +1,126 @@
|
||||
import express from "express";
|
||||
|
||||
import AccessControlsController from "../../controllers/access-controls-controller";
|
||||
import AuthController from "../../controllers/auth-controller";
|
||||
import LogsController from "../../controllers/logs-controller";
|
||||
import OverviewController from "../../controllers/overview-controller";
|
||||
import TaskPrioritiesController from "../../controllers/task-priorities-controller";
|
||||
|
||||
import attachmentsApiRouter from "./attachments-api-router";
|
||||
import clientsApiRouter from "./clients-api-router";
|
||||
import jobTitlesApiRouter from "./job-titles-api-router";
|
||||
import notificationsApiRouter from "./notifications-api-router";
|
||||
import personalOverviewApiRouter from "./personal-overview-api-router";
|
||||
import projectMembersApiRouter from "./project-members-api-router";
|
||||
import projectsApiRouter from "./projects-api-router";
|
||||
import settingsApiRouter from "./settings-api-router";
|
||||
import statusesApiRouter from "./statuses-api-router";
|
||||
import subTasksApiRouter from "./sub-tasks-api-router";
|
||||
import taskCommentsApiRouter from "./task-comments-api-router";
|
||||
import taskWorkLogApiRouter from "./task-work-log-api-router";
|
||||
import tasksApiRouter from "./tasks-api-router";
|
||||
import teamMembersApiRouter from "./team-members-api-router";
|
||||
import teamsApiRouter from "./teams-api-router";
|
||||
import timezonesApiRouter from "./timezones-api-router";
|
||||
import todoListApiRouter from "./todo-list-api-router";
|
||||
import projectStatusesApiRouter from "./project-statuses-api-router";
|
||||
import labelsApiRouter from "./labels-api-router";
|
||||
import sharedProjectsApiRouter from "./shared-projects-api-router";
|
||||
import resourceAllocationApiRouter from "./resource-allocation-api-router";
|
||||
import taskTemplatesApiRouter from "./task-templates-api-router";
|
||||
import projectInsightsApiRouter from "./project-insights-api-router";
|
||||
import passwordValidator from "../../middlewares/validators/password-validator";
|
||||
import adminCenterApiRouter from "./admin-center-api-router";
|
||||
import reportingApiRouter from "./reporting-api-router";
|
||||
import activityLogsApiRouter from "./activity-logs-api-router";
|
||||
import safeControllerFunction from "../../shared/safe-controller-function";
|
||||
import projectFoldersApiRouter from "./project-folders-api-router";
|
||||
import taskPhasesApiRouter from "./task-phases-api-router";
|
||||
import projectCategoriesApiRouter from "./project-categories-api-router";
|
||||
import homePageApiRouter from "./home-page-api-router";
|
||||
import ganttApiRouter from "./gantt-api-router";
|
||||
import projectCommentsApiRouter from "./project-comments-api-router";
|
||||
import reportingExportApiRouter from "./reporting-export-api-router";
|
||||
import projectHealthsApiRouter from "./project-healths-api-router";
|
||||
import ptTasksApiRouter from "./pt-tasks-api-router";
|
||||
import projectTemplatesApiRouter from "./project-templates-api";
|
||||
import ptTaskPhasesApiRouter from "./pt_task-phases-api-router";
|
||||
import ptStatusesApiRouter from "./pt-statuses-api-router";
|
||||
import workloadApiRouter from "./gannt-apis/workload-api-router";
|
||||
import roadmapApiRouter from "./gannt-apis/roadmap-api-router";
|
||||
import scheduleApiRouter from "./gannt-apis/schedule-api-router";
|
||||
import scheduleApiV2Router from "./gannt-apis/schedule-api-v2-router";
|
||||
import projectManagerApiRouter from "./project-managers-api-router";
|
||||
|
||||
import billingApiRouter from "./billing-api-router";
|
||||
import taskDependenciesApiRouter from "./task-dependencies-api-router";
|
||||
|
||||
import taskRecurringApiRouter from "./task-recurring-api-router";
|
||||
|
||||
import express from "express";
|
||||
|
||||
import AccessControlsController from "../../controllers/access-controls-controller";
|
||||
import AuthController from "../../controllers/auth-controller";
|
||||
import LogsController from "../../controllers/logs-controller";
|
||||
import OverviewController from "../../controllers/overview-controller";
|
||||
import TaskPrioritiesController from "../../controllers/task-priorities-controller";
|
||||
|
||||
import attachmentsApiRouter from "./attachments-api-router";
|
||||
import clientsApiRouter from "./clients-api-router";
|
||||
import jobTitlesApiRouter from "./job-titles-api-router";
|
||||
import notificationsApiRouter from "./notifications-api-router";
|
||||
import personalOverviewApiRouter from "./personal-overview-api-router";
|
||||
import projectMembersApiRouter from "./project-members-api-router";
|
||||
import projectsApiRouter from "./projects-api-router";
|
||||
import settingsApiRouter from "./settings-api-router";
|
||||
import statusesApiRouter from "./statuses-api-router";
|
||||
import subTasksApiRouter from "./sub-tasks-api-router";
|
||||
import taskCommentsApiRouter from "./task-comments-api-router";
|
||||
import taskWorkLogApiRouter from "./task-work-log-api-router";
|
||||
import tasksApiRouter from "./tasks-api-router";
|
||||
import teamMembersApiRouter from "./team-members-api-router";
|
||||
import teamsApiRouter from "./teams-api-router";
|
||||
import timezonesApiRouter from "./timezones-api-router";
|
||||
import todoListApiRouter from "./todo-list-api-router";
|
||||
import projectStatusesApiRouter from "./project-statuses-api-router";
|
||||
import labelsApiRouter from "./labels-api-router";
|
||||
import sharedProjectsApiRouter from "./shared-projects-api-router";
|
||||
import resourceAllocationApiRouter from "./resource-allocation-api-router";
|
||||
import taskTemplatesApiRouter from "./task-templates-api-router";
|
||||
import projectInsightsApiRouter from "./project-insights-api-router";
|
||||
import passwordValidator from "../../middlewares/validators/password-validator";
|
||||
import adminCenterApiRouter from "./admin-center-api-router";
|
||||
import reportingApiRouter from "./reporting-api-router";
|
||||
import activityLogsApiRouter from "./activity-logs-api-router";
|
||||
import safeControllerFunction from "../../shared/safe-controller-function";
|
||||
import projectFoldersApiRouter from "./project-folders-api-router";
|
||||
import taskPhasesApiRouter from "./task-phases-api-router";
|
||||
import projectCategoriesApiRouter from "./project-categories-api-router";
|
||||
import homePageApiRouter from "./home-page-api-router";
|
||||
import ganttApiRouter from "./gantt-api-router";
|
||||
import projectCommentsApiRouter from "./project-comments-api-router";
|
||||
import reportingExportApiRouter from "./reporting-export-api-router";
|
||||
import projectHealthsApiRouter from "./project-healths-api-router";
|
||||
import ptTasksApiRouter from "./pt-tasks-api-router";
|
||||
import projectTemplatesApiRouter from "./project-templates-api";
|
||||
import ptTaskPhasesApiRouter from "./pt_task-phases-api-router";
|
||||
import ptStatusesApiRouter from "./pt-statuses-api-router";
|
||||
import workloadApiRouter from "./gannt-apis/workload-api-router";
|
||||
import roadmapApiRouter from "./gannt-apis/roadmap-api-router";
|
||||
import scheduleApiRouter from "./gannt-apis/schedule-api-router";
|
||||
import scheduleApiV2Router from "./gannt-apis/schedule-api-v2-router";
|
||||
import projectManagerApiRouter from "./project-managers-api-router";
|
||||
|
||||
import billingApiRouter from "./billing-api-router";
|
||||
import taskDependenciesApiRouter from "./task-dependencies-api-router";
|
||||
|
||||
import taskRecurringApiRouter from "./task-recurring-api-router";
|
||||
|
||||
import customColumnsApiRouter from "./custom-columns-api-router";
|
||||
|
||||
import projectActivityLogsApiRouter from "./project-activity-logs-api-router";
|
||||
|
||||
const api = express.Router();
|
||||
|
||||
api.use("/projects", projectsApiRouter);
|
||||
api.use("/team-members", teamMembersApiRouter);
|
||||
api.use("/job-titles", jobTitlesApiRouter);
|
||||
api.use("/clients", clientsApiRouter);
|
||||
api.use("/teams", teamsApiRouter);
|
||||
api.use("/tasks", tasksApiRouter);
|
||||
api.use("/settings", settingsApiRouter);
|
||||
api.use("/personal-overview", personalOverviewApiRouter);
|
||||
api.use("/statuses", statusesApiRouter);
|
||||
api.use("/todo-list", todoListApiRouter);
|
||||
api.use("/notifications", notificationsApiRouter);
|
||||
api.use("/attachments", attachmentsApiRouter);
|
||||
api.use("/sub-tasks", subTasksApiRouter);
|
||||
api.use("/project-members", projectMembersApiRouter);
|
||||
api.use("/task-time-log", taskWorkLogApiRouter);
|
||||
api.use("/task-comments", taskCommentsApiRouter);
|
||||
api.use("/timezones", timezonesApiRouter);
|
||||
api.use("/project-statuses", projectStatusesApiRouter);
|
||||
api.use("/labels", labelsApiRouter);
|
||||
api.use("/resource-allocation", resourceAllocationApiRouter);
|
||||
api.use("/shared/projects", sharedProjectsApiRouter);
|
||||
api.use("/task-templates", taskTemplatesApiRouter);
|
||||
api.use("/project-insights", projectInsightsApiRouter);
|
||||
api.use("/admin-center", adminCenterApiRouter);
|
||||
api.use("/reporting", reportingApiRouter);
|
||||
api.use("/activity-logs", activityLogsApiRouter);
|
||||
api.use("/projects-folders", projectFoldersApiRouter);
|
||||
api.use("/task-phases", taskPhasesApiRouter);
|
||||
api.use("/project-categories", projectCategoriesApiRouter);
|
||||
api.use("/home", homePageApiRouter);
|
||||
api.use("/gantt", ganttApiRouter);
|
||||
api.use("/project-comments", projectCommentsApiRouter);
|
||||
api.use("/reporting-export", reportingExportApiRouter);
|
||||
api.use("/project-healths", projectHealthsApiRouter);
|
||||
api.use("/project-templates", projectTemplatesApiRouter);
|
||||
api.use("/pt-tasks", ptTasksApiRouter);
|
||||
api.use("/pt-task-phases", ptTaskPhasesApiRouter);
|
||||
api.use("/pt-statuses", ptStatusesApiRouter);
|
||||
api.use("/workload-gannt", workloadApiRouter);
|
||||
api.use("/roadmap-gannt", roadmapApiRouter);
|
||||
api.use("/schedule-gannt", scheduleApiRouter);
|
||||
api.use("/schedule-gannt-v2", scheduleApiV2Router);
|
||||
api.use("/project-managers", projectManagerApiRouter);
|
||||
|
||||
api.get("/overview/:id", safeControllerFunction(OverviewController.getById));
|
||||
api.get("/task-priorities", safeControllerFunction(TaskPrioritiesController.get));
|
||||
api.post("/change-password", passwordValidator, safeControllerFunction(AuthController.changePassword));
|
||||
api.get("/access-controls/roles", safeControllerFunction(AccessControlsController.getRoles));
|
||||
api.get("/logs/my-dashboard", safeControllerFunction(LogsController.getActivityLog));
|
||||
|
||||
api.use("/billing", billingApiRouter);
|
||||
api.use("/task-dependencies", taskDependenciesApiRouter);
|
||||
|
||||
api.use("/task-recurring", taskRecurringApiRouter);
|
||||
|
||||
|
||||
const api = express.Router();
|
||||
|
||||
api.use("/projects", projectsApiRouter);
|
||||
api.use("/team-members", teamMembersApiRouter);
|
||||
api.use("/job-titles", jobTitlesApiRouter);
|
||||
api.use("/clients", clientsApiRouter);
|
||||
api.use("/teams", teamsApiRouter);
|
||||
api.use("/tasks", tasksApiRouter);
|
||||
api.use("/settings", settingsApiRouter);
|
||||
api.use("/personal-overview", personalOverviewApiRouter);
|
||||
api.use("/statuses", statusesApiRouter);
|
||||
api.use("/todo-list", todoListApiRouter);
|
||||
api.use("/notifications", notificationsApiRouter);
|
||||
api.use("/attachments", attachmentsApiRouter);
|
||||
api.use("/sub-tasks", subTasksApiRouter);
|
||||
api.use("/project-members", projectMembersApiRouter);
|
||||
api.use("/task-time-log", taskWorkLogApiRouter);
|
||||
api.use("/task-comments", taskCommentsApiRouter);
|
||||
api.use("/timezones", timezonesApiRouter);
|
||||
api.use("/project-statuses", projectStatusesApiRouter);
|
||||
api.use("/labels", labelsApiRouter);
|
||||
api.use("/resource-allocation", resourceAllocationApiRouter);
|
||||
api.use("/shared/projects", sharedProjectsApiRouter);
|
||||
api.use("/task-templates", taskTemplatesApiRouter);
|
||||
api.use("/project-insights", projectInsightsApiRouter);
|
||||
api.use("/admin-center", adminCenterApiRouter);
|
||||
api.use("/reporting", reportingApiRouter);
|
||||
api.use("/activity-logs", activityLogsApiRouter);
|
||||
api.use("/projects-folders", projectFoldersApiRouter);
|
||||
api.use("/task-phases", taskPhasesApiRouter);
|
||||
api.use("/project-categories", projectCategoriesApiRouter);
|
||||
api.use("/home", homePageApiRouter);
|
||||
api.use("/gantt", ganttApiRouter);
|
||||
api.use("/project-comments", projectCommentsApiRouter);
|
||||
api.use("/reporting-export", reportingExportApiRouter);
|
||||
api.use("/project-healths", projectHealthsApiRouter);
|
||||
api.use("/project-templates", projectTemplatesApiRouter);
|
||||
api.use("/pt-tasks", ptTasksApiRouter);
|
||||
api.use("/pt-task-phases", ptTaskPhasesApiRouter);
|
||||
api.use("/pt-statuses", ptStatusesApiRouter);
|
||||
api.use("/workload-gannt", workloadApiRouter);
|
||||
api.use("/roadmap-gannt", roadmapApiRouter);
|
||||
api.use("/schedule-gannt", scheduleApiRouter);
|
||||
api.use("/schedule-gannt-v2", scheduleApiV2Router);
|
||||
api.use("/project-managers", projectManagerApiRouter);
|
||||
|
||||
api.get("/overview/:id", safeControllerFunction(OverviewController.getById));
|
||||
api.get("/task-priorities", safeControllerFunction(TaskPrioritiesController.get));
|
||||
api.post("/change-password", passwordValidator, safeControllerFunction(AuthController.changePassword));
|
||||
api.get("/access-controls/roles", safeControllerFunction(AccessControlsController.getRoles));
|
||||
api.get("/logs/my-dashboard", safeControllerFunction(LogsController.getActivityLog));
|
||||
|
||||
api.use("/billing", billingApiRouter);
|
||||
api.use("/task-dependencies", taskDependenciesApiRouter);
|
||||
|
||||
api.use("/task-recurring", taskRecurringApiRouter);
|
||||
api.use("/custom-columns", customColumnsApiRouter);
|
||||
api.use("/activity-logs", activityLogsApiRouter);
|
||||
|
||||
|
||||
api.use("/project-activity-logs", projectActivityLogsApiRouter);
|
||||
|
||||
export default api;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import express from "express";
|
||||
import idParamValidator from "../../middlewares/validators/id-param-validator";
|
||||
import safeControllerFunction from "../../shared/safe-controller-function";
|
||||
import ProjectActivityLogsController from "../../controllers/project-activity-logs-controller";
|
||||
|
||||
const projectActivityLogsApiRouter = express.Router();
|
||||
|
||||
// Match the client URL (/project/:projectId) and ensure param name lines up
|
||||
projectActivityLogsApiRouter.get(
|
||||
"/project/:id",
|
||||
// Validate that id is a proper UUID
|
||||
idParamValidator,
|
||||
// Wrap the controller to catch and forward errors
|
||||
safeControllerFunction(ProjectActivityLogsController.getByProjectId)
|
||||
);
|
||||
|
||||
// Optional health‐check endpoint
|
||||
projectActivityLogsApiRouter.get("/test", (req, res) => {
|
||||
res.json({ message: "Project activity logs router is working!" });
|
||||
});
|
||||
|
||||
export default projectActivityLogsApiRouter;
|
||||
6
worklenz-frontend/.dockerignore
Normal file
6
worklenz-frontend/.dockerignore
Normal file
@@ -0,0 +1,6 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
.git
|
||||
.gitignore
|
||||
.dockerignore
|
||||
README.md
|
||||
@@ -12,7 +12,7 @@ COPY . .
|
||||
RUN echo "window.VITE_API_URL='${VITE_API_URL:-http://backend:3000}';" > ./public/env-config.js && \
|
||||
echo "window.VITE_SOCKET_URL='${VITE_SOCKET_URL:-ws://backend:3000}';" >> ./public/env-config.js
|
||||
|
||||
RUN npm run build
|
||||
RUN NODE_OPTIONS="--max-old-space-size=4096" npm run build
|
||||
|
||||
FROM node:22-alpine AS production
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ Worklenz is a project management application built with React, TypeScript, and A
|
||||
- [Project Structure](#project-structure)
|
||||
- [Contributing](#contributing)
|
||||
- [Learn More](#learn-more)
|
||||
- [License](#license)
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -93,3 +94,7 @@ To learn more about the technologies used in this project:
|
||||
- [TypeScript Documentation](https://www.typescriptlang.org/docs/)
|
||||
- [Ant Design Documentation](https://ant.design/docs/react/introduce)
|
||||
- [Vite Documentation](https://vitejs.dev/guide/)
|
||||
|
||||
## License
|
||||
|
||||
Worklenz is open source and released under the [GNU Affero General Public License Version 3 (AGPLv3)](LICENSE).
|
||||
|
||||
@@ -14,6 +14,81 @@
|
||||
<title>Worklenz</title>
|
||||
<!-- Environment configuration -->
|
||||
<script src="/env-config.js"></script>
|
||||
<!-- Google Analytics -->
|
||||
<script>
|
||||
// Function to initialize Google Analytics
|
||||
function initGoogleAnalytics() {
|
||||
// Load the Google Analytics script
|
||||
const script = document.createElement('script');
|
||||
script.async = true;
|
||||
|
||||
// Determine which tracking ID to use based on the environment
|
||||
const isProduction = window.location.hostname === 'worklenz.com' ||
|
||||
window.location.hostname === 'app.worklenz.com';
|
||||
|
||||
const trackingId = isProduction
|
||||
? 'G-XXXXXXXXXX'
|
||||
: 'G-3LM2HGWEXG'; // Open source tracking ID
|
||||
|
||||
script.src = `https://www.googletagmanager.com/gtag/js?id=${trackingId}`;
|
||||
document.head.appendChild(script);
|
||||
|
||||
// Initialize Google Analytics
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', trackingId);
|
||||
}
|
||||
|
||||
// Initialize analytics
|
||||
initGoogleAnalytics();
|
||||
|
||||
// Function to show privacy notice
|
||||
function showPrivacyNotice() {
|
||||
const notice = document.createElement('div');
|
||||
notice.style.cssText = `
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
background: #222;
|
||||
color: #f5f5f5;
|
||||
padding: 12px 16px 10px 16px;
|
||||
border-radius: 7px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.18);
|
||||
z-index: 1000;
|
||||
max-width: 320px;
|
||||
font-family: Inter, sans-serif;
|
||||
border: 1px solid #333;
|
||||
font-size: 0.95rem;
|
||||
`;
|
||||
notice.innerHTML = `
|
||||
<div style="margin-bottom: 6px; font-weight: 600; color: #fff; font-size: 1rem;">Analytics Notice</div>
|
||||
<div style="margin-bottom: 8px; color: #f5f5f5;">This app uses Google Analytics for anonymous usage stats. No personal data is tracked.</div>
|
||||
<button id="analytics-notice-btn" style="padding: 5px 14px; background: #1890ff; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 0.95rem;">Got it</button>
|
||||
`;
|
||||
document.body.appendChild(notice);
|
||||
// Add event listener to button
|
||||
const btn = notice.querySelector('#analytics-notice-btn');
|
||||
btn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
localStorage.setItem('privacyNoticeShown', 'true');
|
||||
notice.remove();
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for DOM to be ready
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Check if we should show the notice
|
||||
const isProduction = window.location.hostname === 'worklenz.com' ||
|
||||
window.location.hostname === 'app.worklenz.com';
|
||||
const noticeShown = localStorage.getItem('privacyNoticeShown') === 'true';
|
||||
|
||||
// Show notice if not in production and not shown before
|
||||
if (!isProduction && !noticeShown) {
|
||||
showPrivacyNotice();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
22
worklenz-frontend/package-lock.json
generated
22
worklenz-frontend/package-lock.json
generated
@@ -63,6 +63,7 @@
|
||||
"@types/node": "^20.8.4",
|
||||
"@types/react": "19.0.0",
|
||||
"@types/react-dom": "19.0.0",
|
||||
"@types/react-window-infinite-loader": "^1.0.9",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.5.2",
|
||||
@@ -2449,6 +2450,27 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-window": {
|
||||
"version": "1.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz",
|
||||
"integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-window-infinite-loader": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-window-infinite-loader/-/react-window-infinite-loader-1.0.9.tgz",
|
||||
"integrity": "sha512-gEInTjQwURCnDOFyIEK2+fWB5gTjqwx30O62QfxA9stE5aiB6EWkGj4UMhc0axq7/FV++Gs/TGW8FtgEx0S6Tw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-window": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
"@types/node": "^20.8.4",
|
||||
"@types/react": "19.0.0",
|
||||
"@types/react-dom": "19.0.0",
|
||||
"@types/react-window-infinite-loader": "^1.0.9",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.5.2",
|
||||
|
||||
4
worklenz-frontend/public/locales/alb/404-page.json
Normal file
4
worklenz-frontend/public/locales/alb/404-page.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"doesNotExistText": "Na vjen keq, faqja që kërkoni nuk ekziston.",
|
||||
"backHomeButton": "Kthehu në Faqen Kryesore"
|
||||
}
|
||||
31
worklenz-frontend/public/locales/alb/account-setup.json
Normal file
31
worklenz-frontend/public/locales/alb/account-setup.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"continue": "Vazhdo",
|
||||
|
||||
"setupYourAccount": "Konfiguro Llogarinë Tënde në Worklenz.",
|
||||
"organizationStepTitle": "Emërtoni Organizatën Tuaj",
|
||||
"organizationStepLabel": "Zgjidhni një emër për llogarinë tuaj në Worklenz.",
|
||||
|
||||
"projectStepTitle": "Krijoni projektin tuaj të parë",
|
||||
"projectStepLabel": "Në cilin projekt po punoni aktualisht?",
|
||||
"projectStepPlaceholder": "p.sh. Plani i Marketingut",
|
||||
|
||||
"tasksStepTitle": "Krijoni detyrat tuaja të para",
|
||||
"tasksStepLabel": "Shkruani disa detyra që do të kryeni në",
|
||||
"tasksStepAddAnother": "Shto një tjetër",
|
||||
|
||||
"emailPlaceholder": "Adresa email",
|
||||
"invalidEmail": "Ju lutemi vendosni një adresë email të vlefshme",
|
||||
"or": "ose",
|
||||
"templateButton": "Importo nga shablloni",
|
||||
"goBack": "Kthehu Mbrapa",
|
||||
"cancel": "Anulo",
|
||||
"create": "Krijo",
|
||||
"templateDrawerTitle": "Zgjidh nga shabllonet",
|
||||
"step3InputLabel": "Fto me email",
|
||||
"addAnother": "Shto një tjetër",
|
||||
"skipForNow": "Kalo tani për tani",
|
||||
"formTitle": "Krijoni detyrën tuaj të parë.",
|
||||
"step3Title": "Fto ekipin tënd të punojë me",
|
||||
"maxMembers": " (Mund të ftoni deri në 5 anëtarë)",
|
||||
"maxTasks": " (Mund të krijoni deri në 5 detyra)"
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"title": "Faturimet",
|
||||
"currentBill": "Fatura Aktuale",
|
||||
"configuration": "Konfigurimi",
|
||||
"currentPlanDetails": "Detajet e Planit Aktual",
|
||||
"upgradePlan": "Përmirëso Planin",
|
||||
"cardBodyText01": "Provë falas",
|
||||
"cardBodyText02": "(Plani juaj i provës skadon në 1 muaj 19 ditë)",
|
||||
"redeemCode": "Kodi i Zbritjes",
|
||||
"accountStorage": "Depozita e Llogarisë",
|
||||
"used": "Përdorur:",
|
||||
"remaining": "E mbetur:",
|
||||
"charges": "Tarifat",
|
||||
"tooltip": "Tarifat për ciklin aktual të faturimit",
|
||||
"description": "Përshkrimi",
|
||||
"billingPeriod": "Periudha e Faturimit",
|
||||
"billStatus": "Statusi i Faturës",
|
||||
"perUserValue": "Vlera për Përdorues",
|
||||
"users": "Përdoruesit",
|
||||
|
||||
"amount": "Shuma",
|
||||
"invoices": "Faturat",
|
||||
"transactionId": "ID e Transaksionit",
|
||||
"transactionDate": "Data e Transaksionit",
|
||||
"paymentMethod": "Metoda e Pagesës",
|
||||
"status": "Statusi",
|
||||
"ltdUsers": "Mund të shtoni deri në {{ltd_users}} përdorues.",
|
||||
|
||||
"totalSeats": "Vende totale",
|
||||
"availableSeats": "Vende të disponueshme",
|
||||
"addMoreSeats": "Shto më shumë vende",
|
||||
|
||||
"drawerTitle": "Kodi i Zbritjes",
|
||||
"label": "Kodi i Zbritjes",
|
||||
"drawerPlaceholder": "Vendosni kodin tuaj të zbritjes",
|
||||
"redeemSubmit": "Paraqit",
|
||||
|
||||
"modalTitle": "Zgjidhni planin më të mirë për ekipin tuaj",
|
||||
"seatLabel": "Numri i vendeve",
|
||||
"freePlan": "Plan Falas",
|
||||
"startup": "Startup",
|
||||
"business": "Biznes",
|
||||
"tag": "Më i Popullarizuar",
|
||||
"enterprise": "Ndërmarrje",
|
||||
|
||||
"freeSubtitle": "falas përgjithmonë",
|
||||
"freeUsers": "Më e mira për përdorim personal",
|
||||
"freeText01": "100MB depozitë",
|
||||
"freeText02": "3 projekte",
|
||||
"freeText03": "5 anëtarë të ekipit",
|
||||
|
||||
"startupSubtitle": "ÇMIM I RASTËSISHËM / muaj",
|
||||
"startupUsers": "Deri në 15 përdorues",
|
||||
"startupText01": "25GB depozitë",
|
||||
"startupText02": "Projekte të pakufizuara aktive",
|
||||
"startupText03": "Orar",
|
||||
"startupText04": "Raportim",
|
||||
"startupText05": "Abonohu në projekte",
|
||||
|
||||
"businessSubtitle": "përdorues / muaj",
|
||||
"businessUsers": "16 - 200 përdorues",
|
||||
|
||||
"enterpriseUsers": "200 - 500+ përdorues",
|
||||
|
||||
"footerTitle": "Ju lutemi na jepni një numër kontakti që mund të përdorim për t'ju kontaktuar.",
|
||||
"footerLabel": "Numri i Kontaktit",
|
||||
"footerButton": "Na kontaktoni",
|
||||
|
||||
"redeemCodePlaceHolder": "Vendosni kodin tuaj të zbritjes",
|
||||
"submit": "Paraqit",
|
||||
|
||||
"trialPlan": "Provë Falas",
|
||||
"trialExpireDate": "E vlefshme deri më {{trial_expire_date}}",
|
||||
"trialExpired": "Provat tuaja falas skaduan {{trial_expire_string}}",
|
||||
"trialInProgress": "Provat tuaja falas skadojnë {{trial_expire_string}}",
|
||||
|
||||
"required": "Kjo fushë është e detyrueshme",
|
||||
"invalidCode": "Kod i pavlefshëm",
|
||||
|
||||
"selectPlan": "Zgjidhni planin më të mirë për ekipin tuaj",
|
||||
"changeSubscriptionPlan": "Ndryshoni planin tuaj të abonimit",
|
||||
"noOfSeats": "Numri i vendeve",
|
||||
"annualPlan": "Pro - Vjetor",
|
||||
"monthlyPlan": "Pro - Mujor",
|
||||
"freeForever": "Falas Përgjithmonë",
|
||||
"bestForPersonalUse": "Më e mira për përdorim personal",
|
||||
"storage": "Depozitë",
|
||||
"projects": "Projekte",
|
||||
"teamMembers": "Anëtarët e Ekipit",
|
||||
"unlimitedTeamMembers": "Anëtarë të pakufizuar të ekipit",
|
||||
"unlimitedActiveProjects": "Projekte të pakufizuara aktive",
|
||||
"schedule": "Orar",
|
||||
"reporting": "Raportim",
|
||||
"subscribeToProjects": "Abonohu në projekte",
|
||||
"billedAnnually": "Faturuar çdo vit",
|
||||
"billedMonthly": "Faturuar çdo muaj",
|
||||
|
||||
"pausePlan": "Pauzë Planin",
|
||||
"resumePlan": "Rifillo Planin",
|
||||
"changePlan": "Ndrysho Planin",
|
||||
"cancelPlan": "Anulo Planin",
|
||||
|
||||
"perMonthPerUser": "për përdorues/muaj",
|
||||
"viewInvoice": "Shiko Faturën",
|
||||
"switchToFreePlan": "Kalo në Planin Falas",
|
||||
|
||||
"expirestoday": "sot",
|
||||
"expirestomorrow": "nesër",
|
||||
"expiredDaysAgo": "{{days}} ditë më parë",
|
||||
|
||||
"continueWith": "Vazhdo me {{plan}}",
|
||||
"changeToPlan": "Ndrysho në {{plan}}"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"overview": "Përmbledhje",
|
||||
"name": "Emri i Organizatës",
|
||||
"owner": "Pronari i Organizatës",
|
||||
"admins": "Administruesit e Organizatës",
|
||||
"contactNumber": "Shto Numrin e Kontaktit",
|
||||
"edit": "Redakto"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"membersCount": "Numri i Anëtarëve",
|
||||
"createdAt": "Krijuar më",
|
||||
"projectName": "Emri i Projektit",
|
||||
"teamName": "Emri i Ekipit",
|
||||
"refreshProjects": "Rifresko Projektet",
|
||||
"searchPlaceholder": "Kërkoni sipas emrit të projektit",
|
||||
"deleteProject": "Jeni i sigurt që dëshironi të fshini këtë projekt?",
|
||||
"confirm": "Konfirmo",
|
||||
"cancel": "Anulo",
|
||||
"delete": "Fshi Projektin"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"overview": "Përmbledhje",
|
||||
"users": "Përdoruesit",
|
||||
"teams": "Ekipet",
|
||||
"billing": "Faturimi",
|
||||
"projects": "Projektet",
|
||||
"adminCenter": "Qendra Administrative"
|
||||
}
|
||||
33
worklenz-frontend/public/locales/alb/admin-center/teams.json
Normal file
33
worklenz-frontend/public/locales/alb/admin-center/teams.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"title": "Ekipet",
|
||||
"subtitle": "ekipet",
|
||||
"tooltip": "Rifresko ekipet",
|
||||
"placeholder": "Kërko sipas emrit",
|
||||
"addTeam": "Shto Ekip",
|
||||
"team": "Ekipi",
|
||||
"membersCount": "Numri i Anëtarëve",
|
||||
"members": "Anëtarët",
|
||||
"drawerTitle": "Krijo Ekip të Ri",
|
||||
"label": "Emri i Ekipit",
|
||||
"drawerPlaceholder": "Emri",
|
||||
"create": "Krijo",
|
||||
"delete": "Fshi",
|
||||
"settings": "Cilësimet",
|
||||
"popTitle": "Jeni i sigurt?",
|
||||
"message": "Ju lutemi shkruani një Emër",
|
||||
"teamSettings": "Cilësimet e Ekipit",
|
||||
"teamName": "Emri i Ekipit",
|
||||
"teamDescription": "Përshkrimi i Ekipit",
|
||||
"teamMembers": "Anëtarët e Ekipit",
|
||||
"teamMembersCount": "Numri i Anëtarëve të Ekipit",
|
||||
"teamMembersPlaceholder": "Kërko sipas emrit",
|
||||
"addMember": "Shto Anëtar",
|
||||
"add": "Shto",
|
||||
"update": "Përditëso",
|
||||
"teamNamePlaceholder": "Emri i ekipit",
|
||||
"user": "Përdoruesi",
|
||||
"role": "Roli",
|
||||
"owner": "Pronari",
|
||||
"admin": "Administruesi",
|
||||
"member": "Anëtari"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "Përdoruesit",
|
||||
"subTitle": "përdoruesit",
|
||||
"placeholder": "Kërko sipas emrit",
|
||||
"user": "Përdoruesi",
|
||||
"email": "Email",
|
||||
"lastActivity": "Aktiviteti i Fundit",
|
||||
"refresh": "Rifresko përdoruesit"
|
||||
}
|
||||
23
worklenz-frontend/public/locales/alb/all-project-list.json
Normal file
23
worklenz-frontend/public/locales/alb/all-project-list.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "Emri",
|
||||
"client": "Klienti",
|
||||
"category": "Kategoria",
|
||||
"status": "Statusi",
|
||||
"tasksProgress": "Progresi i Detyrave",
|
||||
"updated_at": "Përditësuar Së Fundi",
|
||||
"members": "Anëtarët",
|
||||
"setting": "Cilësimet",
|
||||
"projects": "Projektet",
|
||||
"refreshProjects": "Rifresko projektet",
|
||||
"all": "Të Gjitha",
|
||||
"favorites": "Të Preferuarat",
|
||||
"archived": "Të Arkivuara",
|
||||
"placeholder": "Kërko sipas emrit",
|
||||
"archive": "Arkivo",
|
||||
"unarchive": "Ç'arkivo",
|
||||
"archiveConfirm": "Jeni i sigurt që doni ta arkivoni këtë projekt?",
|
||||
"unarchiveConfirm": "Jeni i sigurt që doni ta çarkivoni këtë projekt?",
|
||||
"clickToFilter": "Klikoni për të filtruar sipas",
|
||||
"noProjects": "Nuk u gjetën projekte",
|
||||
"addToFavourites": "Shto në të preferuarat"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"loggingOut": "Po dilni...",
|
||||
"authenticating": "Po autentikoheni...",
|
||||
"gettingThingsReady": "Po përgatiten gjërat për ju..."
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"headerDescription": "Rivendosni fjalëkalimin tuaj",
|
||||
"emailLabel": "Email",
|
||||
"emailPlaceholder": "Vendosni email-in tuaj",
|
||||
"emailRequired": "Ju lutemi vendosni Email-in tuaj!",
|
||||
"resetPasswordButton": "Rivendos Fjalëkalimin",
|
||||
"returnToLoginButton": "Kthehu te Hyrja",
|
||||
"passwordResetSuccessMessage": "Një lidhje për rivendosjen e fjalëkalimit është dërguar në email-in tuaj.",
|
||||
"orText": "OSE",
|
||||
"successTitle": "U dërguan udhëzimet për rivendosje!",
|
||||
"successMessage": "Informacioni për rivendosje është dërguar në email-in tuaj. Ju lutemi kontrolloni email-in."
|
||||
}
|
||||
27
worklenz-frontend/public/locales/alb/auth/login.json
Normal file
27
worklenz-frontend/public/locales/alb/auth/login.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"headerDescription": "Hyni në llogarinë tuaj",
|
||||
"emailLabel": "Email",
|
||||
"emailPlaceholder": "Vendosni email-in tuaj",
|
||||
"emailRequired": "Ju lutemi vendosni Email-in tuaj!",
|
||||
"passwordLabel": "Fjalëkalimi",
|
||||
"passwordPlaceholder": "Vendosni fjalëkalimin",
|
||||
"passwordRequired": "Ju lutemi vendosni Fjalëkalimin!",
|
||||
"rememberMe": "Më mbaj mend",
|
||||
"loginButton": "Hyr",
|
||||
"signupButton": "Regjistrohu",
|
||||
"forgotPasswordButton": "Keni harruar fjalëkalimin?",
|
||||
"signInWithGoogleButton": "Hyr me Google",
|
||||
"dontHaveAccountText": "Nuk keni llogari?",
|
||||
"orText": "OSE",
|
||||
"successMessage": "Jeni futur me sukses!",
|
||||
"loginError": "Hyrja dështoi",
|
||||
"googleLoginError": "Hyrja përmes Google dështoi",
|
||||
"validationMessages": {
|
||||
"email": "Ju lutemi vendosni një adresë email të vlefshme",
|
||||
"password": "Fjalëkalimi duhet të jetë së paku 8 karaktere"
|
||||
},
|
||||
"errorMessages": {
|
||||
"loginErrorTitle": "Hyrja dështoi",
|
||||
"loginErrorMessage": "Ju lutemi kontrolloni email-in dhe fjalëkalimin dhe provoni përsëri"
|
||||
}
|
||||
}
|
||||
29
worklenz-frontend/public/locales/alb/auth/signup.json
Normal file
29
worklenz-frontend/public/locales/alb/auth/signup.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"headerDescription": "Regjistrohuni për të filluar",
|
||||
"nameLabel": "Emri i Plotë",
|
||||
"namePlaceholder": "Shkruani emrin tuaj të plotë",
|
||||
"nameRequired": "Ju lutemi shkruani emrin tuaj të plotë!",
|
||||
"nameMinCharacterRequired": "Emri duhet të jetë së paku 4 karaktere!",
|
||||
"emailLabel": "Email",
|
||||
"emailPlaceholder": "Shkruani email-in tuaj",
|
||||
"emailRequired": "Ju lutemi shkruani Email-in tuaj!",
|
||||
"passwordLabel": "Fjalëkalimi",
|
||||
"passwordPlaceholder": "Krijoni një fjalëkalim",
|
||||
"passwordRequired": "Ju lutemi krijoni një Fjalëkalim!",
|
||||
"passwordMinCharacterRequired": "Fjalëkalimi duhet të jetë së paku 8 karaktere!",
|
||||
"passwordPatternRequired": "Fjalëkalimi nuk plotëson kërkesat!",
|
||||
"strongPasswordPlaceholder": "Vendosni një fjalëkalim më të fortë",
|
||||
"passwordValidationAltText": "Fjalëkalimi duhet të përmbajë së paku 8 karaktere me shkronja të mëdha dhe të vogla, një numër dhe një simbol.",
|
||||
"signupSuccessMessage": "Jeni regjistruar me sukses!",
|
||||
"privacyPolicyLink": "Politika e Privatësisë",
|
||||
"termsOfUseLink": "Kushtet e Përdorimit",
|
||||
"bySigningUpText": "Duke u regjistruar, ju pranoni",
|
||||
"andText": "dhe",
|
||||
"signupButton": "Regjistrohu",
|
||||
"signInWithGoogleButton": "Hyr me Google",
|
||||
"alreadyHaveAccountText": "Keni tashmë një llogari?",
|
||||
"loginButton": "Hyr",
|
||||
"orText": "OSE",
|
||||
"reCAPTCHAVerificationError": "Gabim në Verifikimin e reCAPTCHA",
|
||||
"reCAPTCHAVerificationErrorMessage": "Nuk mundëm të verifikojmë reCAPTCHA-n tuaj. Ju lutemi provoni përsëri."
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"title": "Verifikoni Email-in për Rivendosje",
|
||||
"description": "Vendosni fjalëkalimin tuaj të ri",
|
||||
"placeholder": "Vendosni fjalëkalimin tuaj të ri",
|
||||
"confirmPasswordPlaceholder": "Konfirmoni fjalëkalimin e ri",
|
||||
"passwordHint": "Të paktën 8 karaktere, me shkronja të mëdha dhe të vogla, një numër dhe një simbol.",
|
||||
"resetPasswordButton": "Rivendos fjalëkalimin",
|
||||
"orText": "Ose",
|
||||
"resendResetEmail": "Dërgo përsëri email-in e rivendosjes",
|
||||
"passwordRequired": "Ju lutemi vendosni fjalëkalimin e ri",
|
||||
"returnToLoginButton": "Kthehu te Hyrja",
|
||||
"confirmPasswordRequired": "Ju lutemi konfirmoni fjalëkalimin e ri",
|
||||
"passwordMismatch": "Fjalëkalimet nuk përputhen"
|
||||
}
|
||||
9
worklenz-frontend/public/locales/alb/common.json
Normal file
9
worklenz-frontend/public/locales/alb/common.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"login-success": "Hyrja u krye me sukses!",
|
||||
"login-failed": "Hyrja dështoi. Ju lutemi kontrolloni kredencialet dhe provoni përsëri.",
|
||||
"signup-success": "Regjistrimi u krye me sukses! Mirë se erdhët.",
|
||||
"signup-failed": "Regjistrimi dështoi. Ju lutemi sigurohuni që të gjitha fushat e nevojshme janë plotësuar dhe provoni përsëri.",
|
||||
"reconnecting": "Jeni shkëputur nga serveri.",
|
||||
"connection-lost": "Lidhja me serverin dështoi. Ju lutemi kontrolloni lidhjen tuaj me internet.",
|
||||
"connection-restored": "U lidhët me serverin me sukses"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"formTitle": "Krijoni projektin tuaj të parë",
|
||||
"inputLabel": "Në cilin projekt po punoni aktualisht?",
|
||||
"or": "ose",
|
||||
"templateButton": "Importo nga shablloni",
|
||||
"createFromTemplate": "Krijo nga shablloni",
|
||||
"goBack": "Kthehu Mbrapa",
|
||||
"continue": "Vazhdo",
|
||||
"cancel": "Anulo",
|
||||
"create": "Krijo",
|
||||
"templateDrawerTitle": "Zgjidh nga shabllonet",
|
||||
"createProject": "Krijo Projekt"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"formTitle": "Krijo detyrën tënde të parë.",
|
||||
"inputLabel": "Shkruaj disa detyra që do të kryesh në",
|
||||
"addAnother": "Shto një tjetër",
|
||||
"goBack": "Kthehu mbrapa",
|
||||
"continue": "Vazhdo"
|
||||
}
|
||||
46
worklenz-frontend/public/locales/alb/home.json
Normal file
46
worklenz-frontend/public/locales/alb/home.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"todoList": {
|
||||
"title": "Lista e Detyrave",
|
||||
"refreshTasks": "Rifresko detyrat",
|
||||
"addTask": "+ Shto Detyrë",
|
||||
"noTasks": "Asnjë detyrë",
|
||||
"pressEnter": "Shtyp",
|
||||
"toCreate": "për të krijuar.",
|
||||
"markAsDone": "Shëno si të përfunduar"
|
||||
},
|
||||
"projects": {
|
||||
"title": "Projektet",
|
||||
"refreshProjects": "Rifresko projektet",
|
||||
"noRecentProjects": "Aktualisht nuk jeni caktuar në asnjë projekt.",
|
||||
"noFavouriteProjects": "Asnjë projekt i shënuar si i preferuar.",
|
||||
"recent": "Të Fundit",
|
||||
"favourites": "Të Preferuarat"
|
||||
},
|
||||
"tasks": {
|
||||
"assignedToMe": "Më janë caktuar",
|
||||
"assignedByMe": "I kam caktuar",
|
||||
"all": "Të Gjitha",
|
||||
"today": "Sot",
|
||||
"upcoming": "Ardhj",
|
||||
"overdue": "Të vonuara",
|
||||
"noDueDate": "Pa afat",
|
||||
"noTasks": "Asnjë detyrë për të shfaqur.",
|
||||
"addTask": "+ Shto detyrë",
|
||||
"name": "Emri",
|
||||
"project": "Projekti",
|
||||
"status": "Statusi",
|
||||
"dueDate": "Afati",
|
||||
"dueDatePlaceholder": "Cakto Afatin",
|
||||
"tomorrow": "Nesër",
|
||||
"nextWeek": "Javën e Ardhshme",
|
||||
"nextMonth": "Muajin e Ardhshëm",
|
||||
"projectRequired": "Ju lutemi zgjidhni një projekt",
|
||||
"pressTabToSelectDueDateAndProject": "Shtyp Tab për të zgjedhur afatin dhe projektin",
|
||||
"dueOn": "Detyrat me afat më",
|
||||
"taskRequired": "Ju lutemi shtoni një detyrë",
|
||||
"list": "Listë",
|
||||
"calendar": "Kalendar",
|
||||
"tasks": "Detyrat",
|
||||
"refresh": "Rifresko"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"formTitle": "Fto ekipin tënd të punojë me",
|
||||
"inputLabel": "Fto me email",
|
||||
"addAnother": "Shto një tjetër",
|
||||
"goBack": "Kthehu mbrapa",
|
||||
"continue": "Vazhdo",
|
||||
"skipForNow": "Anashkalo tani për tani"
|
||||
}
|
||||
23
worklenz-frontend/public/locales/alb/kanban-board.json
Normal file
23
worklenz-frontend/public/locales/alb/kanban-board.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"rename": "Riemërto",
|
||||
"delete": "Fshi",
|
||||
"addTask": "Shto Detyrë",
|
||||
"addSectionButton": "Shto Seksion",
|
||||
"changeCategory": "Ndrysho kategorinë",
|
||||
|
||||
"deleteTooltip": "Fshi",
|
||||
"deleteConfirmationTitle": "Jeni i sigurt?",
|
||||
"deleteConfirmationOk": "Po",
|
||||
"deleteConfirmationCancel": "Anulo",
|
||||
|
||||
"dueDate": "Data e përfundimit",
|
||||
"cancel": "Anulo",
|
||||
|
||||
"today": "Sot",
|
||||
"tomorrow": "Nesër",
|
||||
"assignToMe": "Cakto mua",
|
||||
"archive": "Arkivo",
|
||||
|
||||
"newTaskNamePlaceholder": "Shkruaj emrin e detyrës",
|
||||
"newSubtaskNamePlaceholder": "Shkruaj emrin e nëndetyrës"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"title": "Prova juaj e Worklenz ka skaduar!",
|
||||
"subtitle": "Ju lutemi përmirësoni tani.",
|
||||
"button": "Përmirëso tani",
|
||||
"checking": "Po kontrollohet statusi i abonimit..."
|
||||
}
|
||||
31
worklenz-frontend/public/locales/alb/navbar.json
Normal file
31
worklenz-frontend/public/locales/alb/navbar.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"logoAlt": "Logoja e Worklenz",
|
||||
"home": "Kryefaqja",
|
||||
"projects": "Projektet",
|
||||
"schedule": "Orari",
|
||||
"reporting": "Raportimi",
|
||||
"clients": "Klientët",
|
||||
"teams": "Ekipet",
|
||||
"labels": "Etiketa",
|
||||
"jobTitles": "Tituj Pune",
|
||||
"upgradePlan": "Përmirëso Abonimin",
|
||||
"upgradePlanTooltip": "Përmirëso abonimin",
|
||||
"invite": "Fto",
|
||||
"inviteTooltip": "Fto anëtarë të ekipit të bashkohen",
|
||||
"switchTeamTooltip": "Ndrysho ekipin",
|
||||
"help": "Ndihmë",
|
||||
"notificationTooltip": "Shiko njoftimet",
|
||||
"profileTooltip": "Shiko profilin",
|
||||
"adminCenter": "Qendra Administrative",
|
||||
"settings": "Cilësimet",
|
||||
"logOut": "Dil",
|
||||
"notificationsDrawer": {
|
||||
"read": "Lexuara e njoftimet ",
|
||||
"unread": "Njoftimet e palexuara",
|
||||
"markAsRead": "Shëno si të lexuara",
|
||||
"readAndJoin": "Lexo & Bashkohu",
|
||||
"accept": "Prano",
|
||||
"acceptAndJoin": "Prano & Bashkohu",
|
||||
"noNotifications": "Asnjë njoftim"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"nameYourOrganization": "Emërtoni organizatën tuaj.",
|
||||
"worklenzAccountTitle": "Zgjidhni një emër për llogarinë tuaj në Worklenz.",
|
||||
"continue": "Vazhdo"
|
||||
}
|
||||
7
worklenz-frontend/public/locales/alb/phases-drawer.json
Normal file
7
worklenz-frontend/public/locales/alb/phases-drawer.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"configurePhases": "Konfiguro Fazat",
|
||||
"phaseLabel": "Etiketa e Fazës",
|
||||
"enterPhaseName": "Vendosni një emër për etiketën e fazës",
|
||||
"addOption": "Shto Opsion",
|
||||
"phaseOptions": "Opsionet e Fazës:"
|
||||
}
|
||||
42
worklenz-frontend/public/locales/alb/project-drawer.json
Normal file
42
worklenz-frontend/public/locales/alb/project-drawer.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"createProject": "Krijo Projekt",
|
||||
"editProject": "Modifiko Projektin",
|
||||
"enterCategoryName": "Vendosni emër për kategorinë",
|
||||
"hitEnterToCreate": "Shtyp Enter për të krijuar!",
|
||||
"enterNotes": "Shënime",
|
||||
"youCanManageClientsUnderSettings": "Mund të menaxhoni klientët nën Cilësimet",
|
||||
"addCategory": "Shto kategori projektit",
|
||||
"newCategory": "Kategori e Re",
|
||||
"notes": "Shënime",
|
||||
"startDate": "Data e Fillimit",
|
||||
"endDate": "Data e Përfundimit",
|
||||
"estimateWorkingDays": "Vlerëso ditët e punës",
|
||||
"estimateManDays": "Vlerëso ditët e punëtorëve",
|
||||
"hoursPerDay": "Orë në ditë",
|
||||
"create": "Krijo",
|
||||
"update": "Përditëso",
|
||||
"delete": "Fshi",
|
||||
"typeToSearchClients": "Shkruani për të kërkuar klientë",
|
||||
"projectColor": "Ngjyra e Projektit",
|
||||
"pleaseEnterAName": "Ju lutemi vendosni një emër",
|
||||
"enterProjectName": "Vendosni emrin e projektit",
|
||||
"name": "Emri",
|
||||
"status": "Statusi",
|
||||
"health": "Gjendja",
|
||||
"category": "Kategoria",
|
||||
"projectManager": "Menaxheri i Projektit",
|
||||
"client": "Klienti",
|
||||
"deleteConfirmation": "Jeni i sigurt që doni të fshini?",
|
||||
"deleteConfirmationDescription": "Kjo do të fshijë të gjitha të dhënat e lidhura dhe nuk mund të zhbëhet.",
|
||||
"yes": "Po",
|
||||
"no": "Jo",
|
||||
"createdAt": "Krijuar më",
|
||||
"updatedAt": "Përditësuar më",
|
||||
"by": "nga",
|
||||
"add": "Shto",
|
||||
"asClient": "si klient",
|
||||
"createClient": "Krijo klient",
|
||||
"searchInputPlaceholder": "Kërko sipas emrit ose emailit",
|
||||
"hoursPerDayValidationMessage": "Orët në ditë duhet të jenë një numër midis 1 dhe 24",
|
||||
"noPermission": "Nuk ka leje"
|
||||
}
|
||||
14
worklenz-frontend/public/locales/alb/project-view-files.json
Normal file
14
worklenz-frontend/public/locales/alb/project-view-files.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"nameColumn": "Emri",
|
||||
"attachedTaskColumn": "Detyra e Bashkangjitur",
|
||||
"sizeColumn": "Madhësia",
|
||||
"uploadedByColumn": "Ngarkuar Nga",
|
||||
"uploadedAtColumn": "Ngarkuar Më",
|
||||
"fileIconAlt": "Ikona e skedarit",
|
||||
"titleDescriptionText": "Të gjitha bashkëngjitjet e detyrave në këtë projekt do të shfahen këtu.",
|
||||
"deleteConfirmationTitle": "Jeni i sigurt?",
|
||||
"deleteConfirmationOk": "Po",
|
||||
"deleteConfirmationCancel": "Anulo",
|
||||
"segmentedTooltip": "Së shpejti! Kaloni midis pamjes listë dhe pamjes miniaturash.",
|
||||
"emptyText": "Nuk ka bashkëngjitje në projekt."
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"overview": {
|
||||
"title": "Përmbledhje",
|
||||
"statusOverview": "Përmbledhje Statusi",
|
||||
"priorityOverview": "Përmbledhje Prioriteti",
|
||||
"lastUpdatedTasks": "Detyrat e Përditësuara Së Fundi"
|
||||
},
|
||||
"members": {
|
||||
"title": "Anëtarët",
|
||||
"tooltip": "Anëtarët",
|
||||
"tasksByMembers": "Detyrat sipas anëtarëve",
|
||||
"tasksByMembersTooltip": "Detyrat sipas anëtarëve",
|
||||
"name": "Emri",
|
||||
"taskCount": "Numri i Detyrave",
|
||||
"contribution": "Kontributi",
|
||||
"completed": "Të Përfunduara",
|
||||
"incomplete": "Të Papërfunduara",
|
||||
"overdue": "Të Vonuara",
|
||||
"progress": "Progresi"
|
||||
},
|
||||
"tasks": {
|
||||
"overdueTasks": "Detyrat e Vonuara",
|
||||
"overLoggedTasks": "Detyrat me regjistrim të tepërt",
|
||||
"tasksCompletedEarly": "Detyrat e përfunduara para afatit",
|
||||
"tasksCompletedLate": "Detyrat e përfunduara pas afatit",
|
||||
"overLoggedTasksTooltip": "Detyrat me kohë të regjistruar mbi kohën e vlerësuar",
|
||||
"overdueTasksTooltip": "Detyrat që kanë kaluar afatin e tyre"
|
||||
},
|
||||
"common": {
|
||||
"seeAll": "Shiko të gjitha",
|
||||
"totalLoggedHours": "Orët totale të regjistruara",
|
||||
"totalEstimation": "Vlerësimi total",
|
||||
"completedTasks": "Detyrat e përfunduara",
|
||||
"incompleteTasks": "Detyrat e papërfunduara",
|
||||
"overdueTasks": "Detyrat e vonuara",
|
||||
"overdueTasksTooltip": "Detyrat që kanë kaluar afatin e tyre",
|
||||
"totalLoggedHoursTooltip": "Vlerësimi dhe koha e regjistruar për detyrat.",
|
||||
"includeArchivedTasks": "Përfshi Detyrat e Arkivuara",
|
||||
"export": "Eksporto"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"nameColumn": "Emri",
|
||||
"jobTitleColumn": "Titulli i Punës",
|
||||
"emailColumn": "Email",
|
||||
"tasksColumn": "Detyrat",
|
||||
"taskProgressColumn": "Progresi i Detyrave",
|
||||
"accessColumn": "Qasja",
|
||||
"fileIconAlt": "Ikona e skedarit",
|
||||
"deleteConfirmationTitle": "Jeni i sigurt?",
|
||||
"deleteConfirmationOk": "Po",
|
||||
"deleteConfirmationCancel": "Anulo",
|
||||
"refreshButtonTooltip": "Rifresko anëtarët",
|
||||
"deleteButtonTooltip": "Hiq nga projekti",
|
||||
"memberCount": "Anëtar",
|
||||
"membersCountPlural": "Anëtarë",
|
||||
"emptyText": "Nuk ka bashkëngjitje në projekt."
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"inputPlaceholder": "Shto një koment..",
|
||||
"addButton": "Shto",
|
||||
"cancelButton": "Anulo",
|
||||
"deleteButton": "Fshi"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"importTaskTemplate": "Importo Shabllon Detyrash",
|
||||
"templateName": "Emri i Shabllonit",
|
||||
"templateDescription": "Përshkrimi i Shabllonit",
|
||||
"selectedTasks": "Detyrat e Përzgjedhura",
|
||||
"tasks": "Detyrat",
|
||||
"templates": "Shabllonet",
|
||||
"remove": "Hiq",
|
||||
"cancel": "Anulo",
|
||||
"import": "Importo"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "Anëtarët e Projektit",
|
||||
"searchLabel": "Shtoni anëtarë duke shkruar emrin ose email-in e tyre",
|
||||
"searchPlaceholder": "Shkruani emrin ose email-in",
|
||||
"inviteAsAMember": "Fto si anëtar",
|
||||
"inviteNewMemberByEmail": "Fto anëtar të ri me email"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"importTasks": "Importo detyra",
|
||||
"createTask": "Krijo detyrë",
|
||||
"settings": "Cilësimet",
|
||||
"subscribe": "Abonohu",
|
||||
"unsubscribe": "Ç'abonohu",
|
||||
"deleteProject": "Fshi projektin",
|
||||
"startDate": "Data e fillimit",
|
||||
"endDate": "Data e përfundimit",
|
||||
"projectSettings": "Cilësimet e projektit",
|
||||
"projectSummary": "Përmbledhja e projektit",
|
||||
"receiveProjectSummary": "Merrni një përmbledhje të projektit çdo mbrëmje."
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"title": "Ruaj si Shabllon",
|
||||
"templateName": "Emri i Shabllonit",
|
||||
"includes": "Çfarë duhet të përfshihet në shabllon nga projekti?",
|
||||
"includesOptions": {
|
||||
"statuses": "Statuset",
|
||||
"phases": "Fazat",
|
||||
"labels": "Etiketat"
|
||||
},
|
||||
"taskIncludes": "Çfarë duhet të përfshihet në shabllon nga detyrat?",
|
||||
"taskIncludesOptions": {
|
||||
"statuses": "Statuset",
|
||||
"phases": "Fazat",
|
||||
"labels": "Etiketat",
|
||||
"name": "Emri",
|
||||
"priority": "Prioriteti",
|
||||
"status": "Statusi",
|
||||
"phase": "Faza",
|
||||
"label": "Etiketa",
|
||||
"timeEstimate": "Vlerësimi i Kohës",
|
||||
"description": "Përshkrimi",
|
||||
"subTasks": "Nëndetyrat"
|
||||
},
|
||||
"cancel": "Anulo",
|
||||
"save": "Ruaj",
|
||||
"templateNamePlaceholder": "Shkruani emrin e shabllonit"
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"exportButton": "Eksporto",
|
||||
"timeLogsButton": "Regjistrimet e Kohës",
|
||||
"activityLogsButton": "Regjistrimet e Aktivitetit",
|
||||
"tasksButton": "Detyrat",
|
||||
"searchByNameInputPlaceholder": "Kërko sipas emrit",
|
||||
|
||||
"overviewTab": "Përmbledhje",
|
||||
"timeLogsTab": "Regjistrimet e Kohës",
|
||||
"activityLogsTab": "Regjistrimet e Aktivitetit",
|
||||
"tasksTab": "Detyrat",
|
||||
|
||||
"projectsText": "Projektet",
|
||||
"totalTasksText": "Detyrat Gjithsej",
|
||||
"assignedTasksText": "Detyrat e Caktuara",
|
||||
"completedTasksText": "Detyrat e Përfunduara",
|
||||
"ongoingTasksText": "Detyrat në Vazhdim",
|
||||
"overdueTasksText": "Detyrat e Vonuara",
|
||||
"loggedHoursText": "Orët e Regjistruara",
|
||||
|
||||
"tasksText": "Detyrat",
|
||||
"allText": "Të Gjitha",
|
||||
|
||||
"tasksByProjectsText": "Detyrat Sipas Projekteve",
|
||||
"tasksByStatusText": "Detyrat Sipas Statusit",
|
||||
"tasksByPriorityText": "Detyrat Sipas Prioritetit",
|
||||
|
||||
"todoText": "Për Të Bërë",
|
||||
"doingText": "Duke bërë",
|
||||
"doneText": "E Përfunduar",
|
||||
"lowText": "I Ulët",
|
||||
"mediumText": "I Mesëm",
|
||||
"highText": "I Lartë",
|
||||
|
||||
"billableButton": "Fakturueshme",
|
||||
"billableText": "Fakturueshme",
|
||||
"nonBillableText": "Jo Fakturueshme",
|
||||
|
||||
"timeLogsEmptyPlaceholder": "Asnjë regjistrim kohe për të shfaqur",
|
||||
"loggedText": "Regjistruar",
|
||||
"forText": "për",
|
||||
"inText": "në",
|
||||
"updatedText": "Përditësuar",
|
||||
"fromText": "Nga",
|
||||
"toText": "në",
|
||||
"withinText": "brenda",
|
||||
|
||||
"activityLogsEmptyPlaceholder": "Asnjë regjistrim aktiviteti për të shfaqur",
|
||||
|
||||
"filterByText": "Filtro sipas:",
|
||||
"selectProjectPlaceholder": "Zgjidh Projektin",
|
||||
|
||||
"taskColumn": "Detyra",
|
||||
"nameColumn": "Emri",
|
||||
"projectColumn": "Projekti",
|
||||
"statusColumn": "Statusi",
|
||||
"priorityColumn": "Prioriteti",
|
||||
"dueDateColumn": "Afati",
|
||||
"completedDateColumn": "Data e Përfundimit",
|
||||
"estimatedTimeColumn": "Koha e Vlerësuar",
|
||||
"loggedTimeColumn": "Koha e Regjistruar",
|
||||
"overloggedTimeColumn": "Koha e Tepërt",
|
||||
"daysLeftColumn": "Ditë të Mbetura/Vonuar",
|
||||
"startDateColumn": "Data e Fillimit",
|
||||
"endDateColumn": "Data e Përfundimit",
|
||||
"actualTimeColumn": "Koha Aktuale",
|
||||
"projectHealthColumn": "Gjendja e Projektit",
|
||||
"categoryColumn": "Kategoria",
|
||||
"projectManagerColumn": "Menaxheri i Projektit",
|
||||
|
||||
"tasksStatsOverviewDrawerTitle": "Detyrat e ",
|
||||
"projectsStatsOverviewDrawerTitle": "Projektet e ",
|
||||
|
||||
"cancelledText": "Anuluar",
|
||||
"blockedText": "E Bllokuar",
|
||||
"onHoldText": "Në Pritje",
|
||||
"proposedText": "E Propozuar",
|
||||
"inPlanningText": "Në Planifikim",
|
||||
"inProgressText": "Në Progres",
|
||||
"completedText": "E Përfunduar",
|
||||
"continuousText": "E Vazhdueshme",
|
||||
|
||||
"daysLeftText": "ditë të mbetura",
|
||||
"daysOverdueText": "ditë vonuar",
|
||||
|
||||
"notSetText": "Pa Caktuar",
|
||||
"needsAttentionText": "Kërkon Vëmendje",
|
||||
"atRiskText": "Në Rrezik",
|
||||
"goodText": "Në Rregull"
|
||||
}
|
||||
35
worklenz-frontend/public/locales/alb/reporting-members.json
Normal file
35
worklenz-frontend/public/locales/alb/reporting-members.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"yesterdayText": "Dje",
|
||||
"lastSevenDaysText": "7 Ditët e Fundit",
|
||||
"lastWeekText": "Javën e Kaluar",
|
||||
"lastThirtyDaysText": "30 Ditët e Fundit",
|
||||
"lastMonthText": "Muajin e Kaluar",
|
||||
"lastThreeMonthsText": "3 Muajt e Fundit",
|
||||
"allTimeText": "Të Gjitha",
|
||||
"customRangeText": "Interval i Përshtatur",
|
||||
"startDateInputPlaceholder": "Data e fillimit",
|
||||
"EndDateInputPlaceholder": "Data e përfundimit",
|
||||
"filterButton": "Filtro",
|
||||
|
||||
"membersTitle": "Anëtarët",
|
||||
"includeArchivedButton": "Përfshij Projektet e Arkivuara",
|
||||
"exportButton": "Eksporto",
|
||||
"excelButton": "Excel",
|
||||
"searchByNameInputPlaceholder": "Kërko sipas emrit",
|
||||
|
||||
"memberColumn": "Anëtari",
|
||||
"tasksProgressColumn": "Progresi i Detyrave",
|
||||
"tasksAssignedColumn": "Detyrat e Caktuara",
|
||||
"completedTasksColumn": "Detyrat e Përfunduara",
|
||||
"overdueTasksColumn": "Detyrat e Vonuara",
|
||||
"ongoingTasksColumn": "Detyrat në Vazhdim",
|
||||
|
||||
"tasksAssignedColumnTooltip": "Detyrat e caktuara në intervalin e zgjedhur",
|
||||
"overdueTasksColumnTooltip": "Detyrat e vonuara deri në fund të intervalit të zgjedhur",
|
||||
"completedTasksColumnTooltip": "Detyrat e përfunduara në intervalin e zgjedhur",
|
||||
"ongoingTasksColumnTooltip": "Detyrat e filluara por jo të përfunduara ende",
|
||||
|
||||
"todoText": "Për Të Bërë",
|
||||
"doingText": "Duke bërë",
|
||||
"doneText": "E Përfunduar"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"exportButton": "Eksporto",
|
||||
"projectsButton": "Projektet",
|
||||
"membersButton": "Anëtarët",
|
||||
"searchByNameInputPlaceholder": "Kërko sipas emrit",
|
||||
|
||||
"overviewTab": "Përmbledhje",
|
||||
"projectsTab": "Projektet",
|
||||
"membersTab": "Anëtarët",
|
||||
|
||||
"projectsByStatusText": "Projektet Sipas Statusit",
|
||||
"projectsByCategoryText": "Projektet Sipas Kategorisë",
|
||||
"projectsByHealthText": "Projektet Sipas Gjendjes",
|
||||
|
||||
"projectsText": "Projektet",
|
||||
"allText": "Të Gjitha",
|
||||
|
||||
"cancelledText": "Anuluar",
|
||||
"blockedText": "E Bllokuar",
|
||||
"onHoldText": "Në Pritje",
|
||||
"proposedText": "E Propozuar",
|
||||
"inPlanningText": "Në Planifikim",
|
||||
"inProgressText": "Në Progres",
|
||||
"completedText": "E Përfunduar",
|
||||
"continuousText": "E Vazhdueshme",
|
||||
|
||||
"notSetText": "Pa Caktuar",
|
||||
"needsAttentionText": "Kërkon Vëmendje",
|
||||
"atRiskText": "Në Rrezik",
|
||||
"goodText": "Në Rregull",
|
||||
|
||||
"nameColumn": "Emri",
|
||||
"emailColumn": "Email",
|
||||
"projectsColumn": "Projektet",
|
||||
"tasksColumn": "Detyrat",
|
||||
"overdueTasksColumn": "Detyrat e Vonuara",
|
||||
"completedTasksColumn": "Detyrat e Përfunduara",
|
||||
"ongoingTasksColumn": "Detyrat në Vazhdim"
|
||||
}
|
||||
25
worklenz-frontend/public/locales/alb/reporting-overview.json
Normal file
25
worklenz-frontend/public/locales/alb/reporting-overview.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"overviewTitle": "Përmbledhje",
|
||||
"includeArchivedButton": "Përfshij Projektet e Arkivuara",
|
||||
|
||||
"teamCount": "Ekip",
|
||||
"teamCountPlural": "Ekipe",
|
||||
"projectCount": "Projekt",
|
||||
"projectCountPlural": "Projekte",
|
||||
"memberCount": "Anëtar",
|
||||
"memberCountPlural": "Anëtarë",
|
||||
"activeProjectCount": "Projekt Aktiv",
|
||||
"activeProjectCountPlural": "Projekte Aktive",
|
||||
"overdueProjectCount": "Projekt i Vonuar",
|
||||
"overdueProjectCountPlural": "Projekte të Vonuara",
|
||||
"unassignedMemberCount": "Anëtar i Pacaktuar",
|
||||
"unassignedMemberCountPlural": "Anëtarë të Pacaktuar",
|
||||
"memberWithOverdueTaskCount": "Anëtar me Detyrë të Vonuar",
|
||||
"memberWithOverdueTaskCountPlural": "Anëtarë me Detyra të Vonuara",
|
||||
|
||||
"teamsText": "Ekipet",
|
||||
|
||||
"nameColumn": "Emri",
|
||||
"projectsColumn": "Projektet",
|
||||
"membersColumn": "Anëtarët"
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"exportButton": "Eksporto",
|
||||
"membersButton": "Anëtarët",
|
||||
"tasksButton": "Detyrat",
|
||||
"searchByNameInputPlaceholder": "Kërko sipas emrit",
|
||||
|
||||
"overviewTab": "Përmbledhje",
|
||||
"membersTab": "Anëtarët",
|
||||
"tasksTab": "Detyrat",
|
||||
|
||||
"completedTasksText": "Detyrat e Përfunduara",
|
||||
"incompleteTasksText": "Detyrat e Papërfunduara",
|
||||
"overdueTasksText": "Detyrat e Vonuara",
|
||||
"allocatedHoursText": "Orët e Alokuara",
|
||||
"loggedHoursText": "Orët e Regjistruara",
|
||||
|
||||
"tasksText": "Detyrat",
|
||||
"allText": "Të Gjitha",
|
||||
|
||||
"tasksByStatusText": "Detyrat Sipas Statusit",
|
||||
"tasksByPriorityText": "Detyrat Sipas Prioritetit",
|
||||
"tasksByDueDateText": "Detyrat Sipas Afatit",
|
||||
|
||||
"todoText": "Për Të Bërë",
|
||||
"doingText": "Duke bërë",
|
||||
"doneText": "E Përfunduar",
|
||||
"lowText": "I Ulët",
|
||||
"mediumText": "I Mesëm",
|
||||
"highText": "I Lartë",
|
||||
"completedText": "E Përfunduar",
|
||||
"upcomingText": "Në Ardhje",
|
||||
"overdueText": "E Vonuar",
|
||||
"noDueDateText": "Pa Afat",
|
||||
|
||||
"nameColumn": "Emri",
|
||||
"tasksCountColumn": "Numri i Detyrave",
|
||||
"completedTasksColumn": "Detyrat e Përfunduara",
|
||||
"incompleteTasksColumn": "Detyrat e Papërfunduara",
|
||||
"overdueTasksColumn": "Detyrat e Vonuara",
|
||||
"contributionColumn": "Kontributi",
|
||||
"progressColumn": "Progresi",
|
||||
"loggedTimeColumn": "Koha e Regjistruar",
|
||||
"taskColumn": "Detyra",
|
||||
"projectColumn": "Projekti",
|
||||
"statusColumn": "Statusi",
|
||||
"priorityColumn": "Prioriteti",
|
||||
"phaseColumn": "Faza",
|
||||
"dueDateColumn": "Afati",
|
||||
"completedDateColumn": "Data e Përfundimit",
|
||||
"estimatedTimeColumn": "Koha e Vlerësuar",
|
||||
"overloggedTimeColumn": "Koha e Tepërt",
|
||||
"completedOnColumn": "Përfunduar Më",
|
||||
"daysOverdueColumn": "Ditë vonim",
|
||||
|
||||
"groupByText": "Grupo Sipas:",
|
||||
"statusText": "Statusi",
|
||||
"priorityText": "Prioriteti",
|
||||
"phaseText": "Faza"
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"searchByNamePlaceholder": "Kërko sipas emrit",
|
||||
"searchByCategoryPlaceholder": "Kërko sipas kategorisë",
|
||||
|
||||
"statusText": "Statusi",
|
||||
"healthText": "Gjendja",
|
||||
"categoryText": "Kategoria",
|
||||
"projectManagerText": "Menaxheri i Projektit",
|
||||
"showFieldsText": "Shfaq fushat",
|
||||
|
||||
"cancelledText": "Anuluar",
|
||||
"blockedText": "E bllokuar",
|
||||
"onHoldText": "Në pritje",
|
||||
"proposedText": "E propozuar",
|
||||
"inPlanningText": "Në planifikim",
|
||||
"inProgressText": "Në progres",
|
||||
"completedText": "E përfunduar",
|
||||
"continuousText": "E vazhdueshme",
|
||||
|
||||
"notSetText": "Pa caktuar",
|
||||
"needsAttentionText": "Kërkon vëmendje",
|
||||
"atRiskText": "Në rrezik",
|
||||
"goodText": "Në rregull",
|
||||
|
||||
"nameText": "Projekti",
|
||||
"estimatedVsActualText": "Vlerësuar vs Aktual",
|
||||
"tasksProgressText": "Progresi i detyrave",
|
||||
"lastActivityText": "Aktiviteti i fundit",
|
||||
"datesText": "Datat e Fillimit/Përfundimit",
|
||||
"daysLeftText": "Ditë të mbetura/vonuar",
|
||||
"projectHealthText": "Gjendja e projektit",
|
||||
"projectUpdateText": "Përditësimi i projektit",
|
||||
"clientText": "Klienti",
|
||||
"teamText": "Ekipi"
|
||||
}
|
||||
52
worklenz-frontend/public/locales/alb/reporting-projects.json
Normal file
52
worklenz-frontend/public/locales/alb/reporting-projects.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"projectCount": "Projekt",
|
||||
"projectCountPlural": "Projekte",
|
||||
"includeArchivedButton": "Përfshij Projektet e Arkivuara",
|
||||
"exportButton": "Eksporto",
|
||||
"excelButton": "Excel",
|
||||
|
||||
"projectColumn": "Projekti",
|
||||
"estimatedVsActualColumn": "Vlerësuar vs Aktual",
|
||||
"tasksProgressColumn": "Progresi i Detyrave",
|
||||
"lastActivityColumn": "Aktiviteti i Fundit",
|
||||
"statusColumn": "Statusi",
|
||||
"datesColumn": "Data e Fillimit/Përfundimit",
|
||||
"daysLeftColumn": "Ditë të Mbetura/Vonuar",
|
||||
"projectHealthColumn": "Gjendja e Projektit",
|
||||
"categoryColumn": "Kategoria",
|
||||
"projectUpdateColumn": "Përditësimi i Projektit",
|
||||
"clientColumn": "Klienti",
|
||||
"teamColumn": "Ekipi",
|
||||
"projectManagerColumn": "Menaxheri i Projektit",
|
||||
|
||||
"openButton": "Hap",
|
||||
|
||||
"estimatedText": "Vlerësuar",
|
||||
"actualText": "Aktual",
|
||||
|
||||
"todoText": "Për të Bërë",
|
||||
"doingText": "duke bërë",
|
||||
"doneText": "E Përfunduar",
|
||||
|
||||
"cancelledText": "Anuluar",
|
||||
"blockedText": "E Bllokuar",
|
||||
"onHoldText": "Në Pritje",
|
||||
"proposedText": "E Propozuar",
|
||||
"inPlanningText": "Në Planifikim",
|
||||
"inProgressText": "Në Progres",
|
||||
"completedText": "E Përfunduar",
|
||||
"continuousText": "E Vazhdueshme",
|
||||
|
||||
"daysLeftText": "ditë të mbetura",
|
||||
"dayLeftText": "ditë e mbetur",
|
||||
"daysOverdueText": "ditë vonuar",
|
||||
|
||||
"notSetText": "Pa Caktuar",
|
||||
"needsAttentionText": "Kërkon Vëmendje",
|
||||
"atRiskText": "Në Rrezik",
|
||||
"goodText": "Në Rregull",
|
||||
|
||||
"setCategoryText": "Cakto Kategorinë",
|
||||
"searchByNameInputPlaceholder": "Kërko sipas emrit",
|
||||
"todayText": "Sot"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"overview": "Përmbledhje",
|
||||
"projects": "Projektet",
|
||||
"members": "Anëtarët",
|
||||
"timeReports": "Raportet e Kohës",
|
||||
"estimateVsActual": "Vlerësimi vs Aktual",
|
||||
"currentOrganizationTooltip": "Organizata aktuale"
|
||||
}
|
||||
39
worklenz-frontend/public/locales/alb/schedule.json
Normal file
39
worklenz-frontend/public/locales/alb/schedule.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"today": "Sot",
|
||||
"week": "Javë",
|
||||
"month": "Muaj",
|
||||
|
||||
"settings": "Cilësimet",
|
||||
"workingDays": "Ditët e punës",
|
||||
"monday": "E hënë",
|
||||
"tuesday": "E martë",
|
||||
"wednesday": "E mërkurë",
|
||||
"thursday": "E enjte",
|
||||
"friday": "E premte",
|
||||
"saturday": "E shtunë",
|
||||
"sunday": "E diel",
|
||||
"workingHours": "Orët e punës",
|
||||
"hours": "Orë",
|
||||
"saveButton": "Ruaj",
|
||||
|
||||
"totalAllocation": "Alokimi Total",
|
||||
"timeLogged": "Koha e Regjistruar",
|
||||
"remainingTime": "Koha e Mbetur",
|
||||
"total": "Total",
|
||||
"perDay": "Në Ditë",
|
||||
"tasks": "detyra",
|
||||
"startDate": "Data e Fillimit",
|
||||
"endDate": "Data e Përfundimit",
|
||||
|
||||
"hoursPerDay": "Orë Në Ditë",
|
||||
"totalHours": "Orë Totale",
|
||||
"deleteButton": "Fshi",
|
||||
"cancelButton": "Anulo",
|
||||
|
||||
"tabTitle": "Detyra pa Data Fillimi & Përfundimi",
|
||||
|
||||
"allocatedTime": "Koha e alokuar",
|
||||
"totalLogged": "Total i Regjistruar",
|
||||
"loggedBillable": "Regjistruar Fakturueshme",
|
||||
"loggedNonBillable": "Regjistruar Jo Fakturueshme"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"categoryColumn": "Kategoria",
|
||||
"deleteConfirmationTitle": "Jeni të sigurt?",
|
||||
"deleteConfirmationOk": "Po",
|
||||
"deleteConfirmationCancel": "Anulo",
|
||||
"associatedTaskColumn": "Projektet e Lidhura",
|
||||
"searchPlaceholder": "Kërko sipas emrit",
|
||||
"emptyText": "Kategoritë mund të krijohen gjatë përditësimit ose krijimit të projekteve.",
|
||||
"colorChangeTooltip": "Klikoni për të ndryshuar ngjyrën"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"title": "Ndrysho Fjalëkalimin",
|
||||
"currentPassword": "Fjalëkalimi Aktual",
|
||||
"newPassword": "Fjalëkalimi i Ri",
|
||||
"confirmPassword": "Konfirmo Fjalëkalimin",
|
||||
"currentPasswordPlaceholder": "Vendosni fjalëkalimin aktual",
|
||||
"newPasswordPlaceholder": "Fjalëkalimi i Ri",
|
||||
"confirmPasswordPlaceholder": "Konfirmo Fjalëkalimin",
|
||||
"currentPasswordRequired": "Ju lutemi vendosni fjalëkalimin aktual!",
|
||||
"newPasswordRequired": "Ju lutemi vendosni fjalëkalimin e ri!",
|
||||
"passwordValidationError": "Fjalëkalimi duhet të përmbajë të paktën 8 karaktere, me një shkronjë të madhe, një numër dhe një simbol.",
|
||||
"passwordMismatch": "Fjalëkalimet nuk përputhen!",
|
||||
"passwordRequirements": "Fjalëkalimi i ri duhet të jetë së paku 8 karaktere, me një shkronjë të madhe, një numër dhe një simbol.",
|
||||
"updateButton": "Përditëso Fjalëkalimin"
|
||||
}
|
||||
22
worklenz-frontend/public/locales/alb/settings/clients.json
Normal file
22
worklenz-frontend/public/locales/alb/settings/clients.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"nameColumn": "Emri",
|
||||
"projectColumn": "Projekti",
|
||||
"noProjectsAvailable": "Nuk ka projekte të disponueshme",
|
||||
"deleteConfirmationTitle": "Jeni i sigurt?",
|
||||
"deleteConfirmationOk": "Po",
|
||||
"deleteConfirmationCancel": "Anulo",
|
||||
"searchPlaceholder": "Kërko sipas emrit",
|
||||
"createClient": "Krijo Klient",
|
||||
"pinTooltip": "Klikoni për ta fiksuar në menynë kryesore",
|
||||
"createClientDrawerTitle": "Krijo Klient",
|
||||
"updateClientDrawerTitle": "Përditëso Klientin",
|
||||
"nameLabel": "Emri",
|
||||
"namePlaceholder": "Emri",
|
||||
"nameRequiredError": "Ju lutemi shkruani një Emër",
|
||||
"createButton": "Krijo",
|
||||
"updateButton": "Përditëso",
|
||||
"createClientSuccessMessage": "Klienti u krijua me sukses!",
|
||||
"createClientErrorMessage": "Krijimi i klientit dështoi!",
|
||||
"updateClientSuccessMessage": "Klienti u përditësua me sukses!",
|
||||
"updateClientErrorMessage": "Përditësimi i klientit dështoi!"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"nameColumn": "Emri",
|
||||
"deleteConfirmationTitle": "Jeni i sigurt?",
|
||||
"deleteConfirmationOk": "Po",
|
||||
"deleteConfirmationCancel": "Anulo",
|
||||
"searchPlaceholder": "Kërko sipas emrit",
|
||||
"createJobTitleButton": "Krijo Titull Pune",
|
||||
"pinTooltip": "Klikoni për ta fiksuar në menynë kryesore",
|
||||
"createJobTitleDrawerTitle": "Krijo Titull Pune",
|
||||
"updateJobTitleDrawerTitle": "Përditëso Titullin e Punës",
|
||||
"nameLabel": "Emri",
|
||||
"namePlaceholder": "Emri",
|
||||
"nameRequiredError": "Ju lutemi shkruani një Emër",
|
||||
"createButton": "Krijo",
|
||||
"updateButton": "Përditëso",
|
||||
"createJobTitleSuccessMessage": "Titulli i punës u krijua me sukses!",
|
||||
"createJobTitleErrorMessage": "Krijimi i titullit të punës dështoi!",
|
||||
"updateJobTitleSuccessMessage": "Titulli i punës u përditësua me sukses!",
|
||||
"updateJobTitleErrorMessage": "Përditësimi i titullit të punës dështoi!"
|
||||
}
|
||||
11
worklenz-frontend/public/locales/alb/settings/labels.json
Normal file
11
worklenz-frontend/public/locales/alb/settings/labels.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"labelColumn": "Etiketa",
|
||||
"deleteConfirmationTitle": "Jeni i sigurt?",
|
||||
"deleteConfirmationOk": "Po",
|
||||
"deleteConfirmationCancel": "Anulo",
|
||||
"associatedTaskColumn": "Numri i Detyrave të Lidhura",
|
||||
"searchPlaceholder": "Kërko sipas emrit",
|
||||
"emptyText": "Etiketat mund të krijohen gjatë përditësimit ose krijimit të detyrave.",
|
||||
"pinTooltip": "Klikoni për ta fiksuar në menynë kryesore",
|
||||
"colorChangeTooltip": "Klikoni për të ndryshuar ngjyrën"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"language": "Gjuha",
|
||||
"language_required": "Gjuha është e detyrueshme",
|
||||
"time_zone": "Zona kohore",
|
||||
"time_zone_required": "Zona kohore është e detyrueshme",
|
||||
"save_changes": "Ruaj Ndryshimet"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"title": "Cilësimet e Njoftimeve",
|
||||
"emailTitle": "Më dërgo njoftime me email",
|
||||
"emailDescription": "Kjo përfshin caktimet e reja të detyrave",
|
||||
"dailyDigestTitle": "Më dërgo një përmbledhje ditore",
|
||||
"dailyDigestDescription": "Çdo mbrëmje, do të merrni një përmbledhje të aktivitetit të fundit në detyra.",
|
||||
"popupTitle": "Shfaq njoftimet në kompjuterin tim kur Worklenz është i hapur",
|
||||
"popupDescription": "Njoftimet e shfaqura mund të çaktivizohen nga shfletuesi juaj. Ndryshoni cilësimet e shfletuesit për t'i lejuar ato.",
|
||||
"unreadItemsTitle": "Shfaq numrin e artikujve të palexuar",
|
||||
"unreadItemsDescription": "Do të shihni numërimin për çdo njoftim."
|
||||
}
|
||||
13
worklenz-frontend/public/locales/alb/settings/profile.json
Normal file
13
worklenz-frontend/public/locales/alb/settings/profile.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"uploadError": "Mund të ngarkoni vetëm skedarë JPG/PNG!",
|
||||
"uploadSizeError": "Imazhi duhet të jetë më i vogël se 2MB!",
|
||||
"upload": "Ngarko",
|
||||
"nameLabel": "Emri",
|
||||
"nameRequiredError": "Emri është i detyrueshëm",
|
||||
"emailLabel": "Email",
|
||||
"emailRequiredError": "Email-i është i detyrueshëm",
|
||||
"saveChanges": "Ruaj Ndryshimet",
|
||||
"profileJoinedText": "U bashkua një muaj më parë",
|
||||
"profileLastUpdatedText": "Përditësuar një muaj më parë",
|
||||
"avatarTooltip": "Klikoni për të ngarkuar një avatar"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"nameColumn": "Emri",
|
||||
"editToolTip": "Modifiko",
|
||||
"deleteToolTip": "Fshi",
|
||||
"confirmText": "Jeni i sigurt?",
|
||||
"okText": "Po",
|
||||
"cancelText": "Anulo"
|
||||
}
|
||||
14
worklenz-frontend/public/locales/alb/settings/sidebar.json
Normal file
14
worklenz-frontend/public/locales/alb/settings/sidebar.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"profile": "Profili",
|
||||
"notifications": "Njoftimet",
|
||||
"clients": "Klientët",
|
||||
"job-titles": "Tituj Pune",
|
||||
"labels": "Etiketa",
|
||||
"categories": "Kategoritë",
|
||||
"project-templates": "Shabllonet e Projekteve",
|
||||
"task-templates": "Shabllonet e Detyrave",
|
||||
"team-members": "Anëtarët e Ekipit",
|
||||
"teams": "Ekipet",
|
||||
"change-password": "Ndrysho Fjalëkalimin",
|
||||
"language-and-region": "Gjuha dhe Rajoni"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"nameColumn": "Emri",
|
||||
"createdColumn": "Krijuar",
|
||||
"editToolTip": "Redakto",
|
||||
"deleteToolTip": "Fshi",
|
||||
"confirmText": "Jeni i sigurt?",
|
||||
"okText": "Po",
|
||||
"cancelText": "Anulo"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"nameColumn": "Emri",
|
||||
"projectsColumn": "Projektet",
|
||||
"emailColumn": "Email",
|
||||
"teamAccessColumn": "Qasja në Ekip",
|
||||
"memberCount": "Anëtar",
|
||||
"membersCountPlural": "Anëtarë",
|
||||
"searchPlaceholder": "Kërko anëtarë sipas emrit",
|
||||
"pinTooltip": "Rifresko listën e anëtarëve",
|
||||
"addMemberButton": "Shto Anëtar të Ri",
|
||||
"editTooltip": "Modifiko anëtarin",
|
||||
"deactivateTooltip": "Çaktivizo anëtarin",
|
||||
"activateTooltip": "Aktivizo anëtarin",
|
||||
"deleteTooltip": "Fshi anëtarin",
|
||||
"confirmDeleteTitle": "Jeni i sigurt që doni të fshini këtë anëtar?",
|
||||
"confirmActivateTitle": "Jeni i sigurt që doni të ndryshoni statusin e këtij anëtari?",
|
||||
"okText": "Po, vazhdo",
|
||||
"cancelText": "Jo, anulo",
|
||||
"deactivatedText": "(Aktualisht i çaktivizuar)",
|
||||
"pendingInvitationText": "(Ftesë në pritje)",
|
||||
"addMemberDrawerTitle": "Shto Anëtar të Ri në Ekip",
|
||||
"updateMemberDrawerTitle": "Përditëso Anëtarin e Ekipit",
|
||||
"addMemberEmailHint": "Anëtarët do të shtohen në ekip pavarësisht nga statusi i pranimit të ftesës",
|
||||
"memberEmailLabel": "Email(o)",
|
||||
"memberEmailPlaceholder": "Vendos adresën email të anëtarit të ekipit",
|
||||
"memberEmailRequiredError": "Ju lutemi vendosni një adresë email të vlefshme",
|
||||
"jobTitleLabel": "Titulli i Punës",
|
||||
"jobTitlePlaceholder": "Zgjidh ose kërko titull pune (Opsionale)",
|
||||
"memberAccessLabel": "Niveli i Qasjes",
|
||||
"addToTeamButton": "Shto Anëtar në Ekip",
|
||||
"updateButton": "Ruaj Ndryshimet",
|
||||
"resendInvitationButton": "Dërgo Përsëri Email-in e Ftesës",
|
||||
"invitationSentSuccessMessage": "Ftesa për ekip u dërgua me sukses!",
|
||||
"createMemberSuccessMessage": "Anëtari i ri i ekipit u shtua me sukses!",
|
||||
"createMemberErrorMessage": "Dështoi shtimi i anëtarit të ri. Ju lutemi provoni përsëri.",
|
||||
"updateMemberSuccessMessage": "Anëtari i ekipit u përditësua me sukses!",
|
||||
"updateMemberErrorMessage": "Dështoi përditësimi i anëtarit. Ju lutemi provoni përsëri.",
|
||||
"memberText": "Anëtar",
|
||||
"adminText": "Administrues",
|
||||
"ownerText": "Pronar i Ekipit",
|
||||
"addedText": "Shtuar",
|
||||
"updatedText": "Përditësuar",
|
||||
"noResultFound": "Shkruani një adresë email dhe shtypni Enter..."
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"details": {
|
||||
"task-key": "Çelësi i Detyrës",
|
||||
"phase": "Faza",
|
||||
"assignees": "Përgjegjësit",
|
||||
"due-date": "Data e Përfundimit",
|
||||
"time-estimation": "Vlerësimi i Kohës",
|
||||
"priority": "Prioriteti",
|
||||
"labels": "Etiketa",
|
||||
"billable": "Fakturueshme",
|
||||
"notify": "Njofto",
|
||||
"when-done-notify": "Kur të përfundojë, njofto",
|
||||
"start-date": "Data e Fillimit",
|
||||
"end-date": "Data e Përfundimit",
|
||||
"hide-start-date": "Fshih Datën e Fillimit",
|
||||
"show-start-date": "Shfaq Datën e Fillimit",
|
||||
"hours": "Orë",
|
||||
"minutes": "Minuta"
|
||||
},
|
||||
"description": {
|
||||
"title": "Përshkrimi",
|
||||
"placeholder": "Shtoni një përshkrim më të detajuar..."
|
||||
},
|
||||
"subTasks": {
|
||||
"title": "Nën-Detyrat",
|
||||
"add-sub-task": "+ Shto Nën-Detyrë",
|
||||
"refresh-sub-tasks": "Rifresko Nën-Detyrat"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"taskHeader": {
|
||||
"taskNamePlaceholder": "Shkruani detyrën tuaj",
|
||||
"deleteTask": "Fshi Detyrën"
|
||||
},
|
||||
"taskInfoTab": {
|
||||
"title": "Info",
|
||||
"details": {
|
||||
"title": "Detajet",
|
||||
"task-key": "Çelësi i Detyrës",
|
||||
"phase": "Faza",
|
||||
"assignees": "Përgjegjësit",
|
||||
"due-date": "Afati i Përfundimit",
|
||||
"time-estimation": "Vlerësimi i Kohës",
|
||||
"priority": "Prioriteti",
|
||||
"labels": "Etiketa",
|
||||
"billable": "Fakturueshme",
|
||||
"notify": "Njofto",
|
||||
"when-done-notify": "Kur të përfundojë, njofto",
|
||||
"start-date": "Data e Fillimit",
|
||||
"end-date": "Data e Përfundimit",
|
||||
"hide-start-date": "Fshih Datën e Fillimit",
|
||||
"show-start-date": "Shfaq Datën e Fillimit",
|
||||
"hours": "Orë",
|
||||
"minutes": "Minuta"
|
||||
},
|
||||
"labels": {
|
||||
"labelInputPlaceholder": "Kërko ose krijo",
|
||||
"labelsSelectorInputTip": "Shtyp Enter për të krijuar"
|
||||
},
|
||||
"description": {
|
||||
"title": "Përshkrimi",
|
||||
"placeholder": "Shtoni një përshkrim më të detajuar..."
|
||||
},
|
||||
"subTasks": {
|
||||
"title": "Nën-Detyrat",
|
||||
"addSubTask": "+ Shto Nën-Detyrë",
|
||||
"addSubTaskInputPlaceholder": "Shkruani detyrën dhe shtypni Enter",
|
||||
"refreshSubTasks": "Rifresko Nën-Detyrat",
|
||||
"edit": "Modifiko",
|
||||
"delete": "Fshi",
|
||||
"confirmDeleteSubTask": "Jeni i sigurt që doni të fshini këtë nën-detyrë?",
|
||||
"deleteSubTask": "Fshi Nën-Detyrën"
|
||||
},
|
||||
"dependencies": {
|
||||
"title": "Varësitë",
|
||||
"addDependency": "+ Shto varësi të re",
|
||||
"blockedBy": "I bllokuar nga",
|
||||
"searchTask": "Shkruani për të kërkuar detyra",
|
||||
"noTasksFound": "Asnjë detyrë nuk u gjet",
|
||||
"confirmDeleteDependency": "Jeni i sigurt që doni të fshini?"
|
||||
},
|
||||
"attachments": {
|
||||
"title": "Bashkëngjitjet",
|
||||
"chooseOrDropFileToUpload": "Zgjidhni ose lëshoni skedar për ngarkim",
|
||||
"uploading": "Po ngarkohet..."
|
||||
},
|
||||
"comments": {
|
||||
"title": "Komentet",
|
||||
"addComment": "+ Shto koment të ri",
|
||||
"noComments": "Asnjë koment ende. Bëhu i pari që komenton!",
|
||||
"delete": "Fshi",
|
||||
"confirmDeleteComment": "Jeni i sigurt që doni të fshini këtë koment?"
|
||||
},
|
||||
"searchInputPlaceholder": "Kërko sipas emrit",
|
||||
"pendingInvitation": "Ftesë në Pritje"
|
||||
},
|
||||
"taskTimeLogTab": {
|
||||
"title": "Regjistri i Kohës",
|
||||
"addTimeLog": "Shto regjistrim të ri kohe",
|
||||
"totalLogged": "Koha totale e regjistruar",
|
||||
"exportToExcel": "Eksporto në Excel",
|
||||
"noTimeLogsFound": "Asnjë regjistrim kohe nuk u gjet"
|
||||
},
|
||||
"taskActivityLogTab": {
|
||||
"title": "Regjistri i Aktivitetit"
|
||||
}
|
||||
}
|
||||
59
worklenz-frontend/public/locales/alb/task-list-filters.json
Normal file
59
worklenz-frontend/public/locales/alb/task-list-filters.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"searchButton": "Kërko",
|
||||
"resetButton": "Rivendos",
|
||||
"searchInputPlaceholder": "Kërko sipas emrit",
|
||||
|
||||
"sortText": "Rendit",
|
||||
"statusText": "Statusi",
|
||||
"phaseText": "Faza",
|
||||
"memberText": "Anëtarët",
|
||||
"assigneesText": "Përgjegjësit",
|
||||
"priorityText": "Prioriteti",
|
||||
"labelsText": "Etiketa",
|
||||
"membersText": "Anëtarët",
|
||||
"groupByText": "Grupo sipas",
|
||||
"showArchivedText": "Shfaq të arkivuara",
|
||||
"showFieldsText": "Shfaq fushat",
|
||||
"keyText": "Çelësi",
|
||||
"taskText": "Detyra",
|
||||
"descriptionText": "Përshkrimi",
|
||||
"phasesText": "Fazat",
|
||||
"listText": "Listë",
|
||||
"progressText": "Progresi",
|
||||
"timeTrackingText": "Gjurmimi i Kohës",
|
||||
"timetrackingText": "Gjurmimi i Kohës",
|
||||
"estimationText": "Vlerësimi",
|
||||
"startDateText": "Data e Fillimit",
|
||||
"startdateText": "Data e Fillimit",
|
||||
"endDateText": "Data e Përfundimit",
|
||||
"dueDateText": "Afati",
|
||||
"duedateText": "Afati",
|
||||
"completedDateText": "Data e Përfundimit",
|
||||
"completeddateText": "Data e Përfundimit",
|
||||
"createdDateText": "Data e Krijimit",
|
||||
"createddateText": "Data e Krijimit",
|
||||
"lastUpdatedText": "Përditësuar Së Fundi",
|
||||
"lastupdatedText": "Përditësuar Së Fundi",
|
||||
"reporterText": "Raportuesi",
|
||||
"dueTimeText": "Koha e Afatit",
|
||||
"duetimeText": "Koha e Afatit",
|
||||
|
||||
"lowText": "I ulët",
|
||||
"mediumText": "I mesëm",
|
||||
"highText": "I lartë",
|
||||
|
||||
"createStatusButtonTooltip": "Cilësimet e statusit",
|
||||
"configPhaseButtonTooltip": "Cilësimet e fazës",
|
||||
"noLabelsFound": "Nuk u gjetën etiketa",
|
||||
|
||||
"addStatusButton": "Shto Status",
|
||||
"addPhaseButton": "Shto Fazë",
|
||||
|
||||
"createStatus": "Krijo Status",
|
||||
"name": "Emri",
|
||||
"category": "Kategoria",
|
||||
"selectCategory": "Zgjidh një kategori",
|
||||
"pleaseEnterAName": "Ju lutemi vendosni një emër",
|
||||
"pleaseSelectACategory": "Ju lutemi zgjidhni një kategori",
|
||||
"create": "Krijo"
|
||||
}
|
||||
63
worklenz-frontend/public/locales/alb/task-list-table.json
Normal file
63
worklenz-frontend/public/locales/alb/task-list-table.json
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"keyColumn": "Çelësi",
|
||||
"taskColumn": "Detyra",
|
||||
"descriptionColumn": "Përshkrimi",
|
||||
"progressColumn": "Progresi",
|
||||
"membersColumn": "Anëtarët",
|
||||
"assigneesColumn": "Përgjegjësit",
|
||||
"labelsColumn": "Etiketa",
|
||||
"phasesColumn": "Fazat",
|
||||
"phaseColumn": "Faza",
|
||||
"statusColumn": "Statusi",
|
||||
"priorityColumn": "Prioriteti",
|
||||
"timeTrackingColumn": "Gjurmimi i Kohës",
|
||||
"timetrackingColumn": "Gjurmimi i Kohës",
|
||||
"estimationColumn": "Vlerësimi",
|
||||
"startDateColumn": "Data e Fillimit",
|
||||
"startdateColumn": "Data e Fillimit",
|
||||
"dueDateColumn": "Data e Afatit",
|
||||
"duedateColumn": "Data e Afatit",
|
||||
"completedDateColumn": "Data e Përfundimit",
|
||||
"completeddateColumn": "Data e Përfundimit",
|
||||
"createdDateColumn": "Data e Krijimit",
|
||||
"createddateColumn": "Data e Krijimit",
|
||||
"lastUpdatedColumn": "Përditësuar Së Fundi",
|
||||
"lastupdatedColumn": "Përditësuar Së Fundi",
|
||||
"reporterColumn": "Raportuesi",
|
||||
"dueTimeColumn": "Koha e Afatit",
|
||||
"todoSelectorText": "Për të Bërë",
|
||||
"doingSelectorText": "Duke bërë",
|
||||
"doneSelectorText": "E Përfunduar",
|
||||
|
||||
"lowSelectorText": "I ulët",
|
||||
"mediumSelectorText": "I mesëm",
|
||||
"highSelectorText": "I lartë",
|
||||
|
||||
"selectText": "Zgjidh",
|
||||
"labelsSelectorInputTip": "Shtyp Enter për të krijuar!",
|
||||
|
||||
"addTaskText": "+ Shto Detyrë",
|
||||
"addSubTaskText": "+ Shto Nën-Detyrë",
|
||||
"addTaskInputPlaceholder": "Shkruaj detyrën dhe shtyp Enter",
|
||||
|
||||
"openButton": "Hap",
|
||||
"okButton": "Në rregull",
|
||||
|
||||
"noLabelsFound": "Nuk u gjetën etiketa",
|
||||
"searchInputPlaceholder": "Kërko ose krijo",
|
||||
"assigneeSelectorInviteButton": "Fto një anëtar të ri me email",
|
||||
"labelInputPlaceholder": "Kërko ose krijo",
|
||||
|
||||
"pendingInvitation": "Ftesë në Pritje",
|
||||
|
||||
"contextMenu": {
|
||||
"assignToMe": "Cakto mua",
|
||||
"moveTo": "Zhvendos në",
|
||||
"unarchive": "Ç'arkivizo",
|
||||
"archive": "Arkivizo",
|
||||
"convertToSubTask": "Shndërro në Nën-Detyrë",
|
||||
"convertToTask": "Shndërro në Detyrë",
|
||||
"delete": "Fshi",
|
||||
"searchByNameInputPlaceholder": "Kërko sipas emrit"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"createTaskTemplate": "Krijo Shabllon Detyre",
|
||||
"editTaskTemplate": "Modifiko Shabllon Detyre",
|
||||
"cancelText": "Anulo",
|
||||
"saveText": "Ruaj",
|
||||
"templateNameText": "Emri i Shabllonit",
|
||||
"selectedTasks": "Detyrat e Përzgjedhura",
|
||||
"removeTask": "Hiq",
|
||||
"cancelButton": "Anulo",
|
||||
"saveButton": "Ruaj"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"taskSelected": "detyrë e zgjedhur",
|
||||
"tasksSelected": "detyra të zgjedhura",
|
||||
"changeStatus": "Ndrysho Statusin/ Prioritetin/ Fazat",
|
||||
"changeLabel": "Ndrysho Etiketën",
|
||||
"assignToMe": "Cakto mua",
|
||||
"changeAssignees": "Ndrysho Përgjegjësit",
|
||||
"archive": "Arkivo",
|
||||
"unarchive": "Ç'arkivo",
|
||||
"delete": "Fshi",
|
||||
"moreOptions": "Më shumë opsione",
|
||||
"deselectAll": "Zgjidhja të gjitha",
|
||||
"status": "Statusi",
|
||||
"priority": "Prioriteti",
|
||||
"phase": "Faza",
|
||||
"member": "Anëtar",
|
||||
"createTaskTemplate": "Krijo Shabllon Detyre",
|
||||
"apply": "Apliko",
|
||||
"createLabel": "+ Krijo Etiketë",
|
||||
"hitEnterToCreate": "Shtyp Enter për të krijuar",
|
||||
"pendingInvitation": "Ftesë në Pritje",
|
||||
"noMatchingLabels": "Asnjë etiketë që përputhet",
|
||||
"noLabels": "Asnjë etiketë"
|
||||
}
|
||||
19
worklenz-frontend/public/locales/alb/template-drawer.json
Normal file
19
worklenz-frontend/public/locales/alb/template-drawer.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"title": "Modifiko Shabllon Detyre",
|
||||
"cancelText": "Anulo",
|
||||
"saveText": "Ruaj",
|
||||
"templateNameText": "Emri i Shabllonit",
|
||||
"selectedTasks": "Detyrat e Përzgjedhura",
|
||||
"removeTask": "Hiq",
|
||||
"description": "Përshkrimi",
|
||||
"phase": "Faza",
|
||||
"statuses": "Statuset",
|
||||
"priorities": "Prioritetet",
|
||||
"labels": "Etiketa",
|
||||
"tasks": "Detyrat",
|
||||
"noTemplateSelected": "Asnjë shabllon i përzgjedhur",
|
||||
"noDescription": "Pa përshkrim",
|
||||
"worklenzTemplates": "Shabllonet Worklenz",
|
||||
"yourTemplatesLibrary": "Biblioteka Juaj",
|
||||
"searchTemplates": "Kërko Shabllone"
|
||||
}
|
||||
23
worklenz-frontend/public/locales/alb/templateDrawer.json
Normal file
23
worklenz-frontend/public/locales/alb/templateDrawer.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"bugTracking": "Gjurmimi i Gabimeve",
|
||||
"construction": "Ndërtim",
|
||||
"designCreative": "Dizajn & Kreativ",
|
||||
"education": "Arsim",
|
||||
"finance": "Financë",
|
||||
"hrRecruiting": "Burime Njerëzore & Rekrutim",
|
||||
"informationTechnology": "Teknologji Informacioni",
|
||||
"legal": "Juridik",
|
||||
"manufacturing": "Prodhim",
|
||||
"marketing": "Marketing",
|
||||
"nonprofit": "Jo-fitimprurës",
|
||||
"personalUse": "Përdorim Personal",
|
||||
"salesCRM": "Shitje & CRM",
|
||||
"serviceConsulting": "Shërbime & Këshillim",
|
||||
"softwareDevelopment": "Zhvillim Softueri",
|
||||
"description": "Përshkrimi",
|
||||
"phase": "Faza",
|
||||
"statuses": "Statuset",
|
||||
"priorities": "Prioritetet",
|
||||
"labels": "Etiketa",
|
||||
"tasks": "Detyrat"
|
||||
}
|
||||
44
worklenz-frontend/public/locales/alb/time-report.json
Normal file
44
worklenz-frontend/public/locales/alb/time-report.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"includeArchivedProjects": "Përfshij Projektet e Arkivuara",
|
||||
"export": "Eksporto",
|
||||
"timeSheet": "Fletë Kohore",
|
||||
|
||||
"searchByName": "Kërko sipas emrit",
|
||||
"selectAll": "Zgjidh të Gjitha",
|
||||
"teams": "Ekipet",
|
||||
|
||||
"searchByProject": "Kërko sipas emrit të projektit",
|
||||
"projects": "Projektet",
|
||||
|
||||
"searchByCategory": "Kërko sipas emrit të kategorisë",
|
||||
"categories": "Kategoritë",
|
||||
|
||||
"billable": "Fakturueshme",
|
||||
"nonBillable": "Jo Fakturueshme",
|
||||
|
||||
"total": "Total",
|
||||
|
||||
"projectsTimeSheet": "Fletë Kohore e Projekteve",
|
||||
|
||||
"loggedTime": "Koha e Regjistruar(orë)",
|
||||
|
||||
"exportToExcel": "Eksporto në Excel",
|
||||
"logged": "regjistruar",
|
||||
"for": "për",
|
||||
|
||||
"membersTimeSheet": "Fletë Kohore e Anëtarëve",
|
||||
"member": "Anëtar",
|
||||
|
||||
"estimatedVsActual": "Vlerësuar vs Aktual",
|
||||
"workingDays": "Ditë Pune",
|
||||
"manDays": "Ditë Njeri",
|
||||
"days": "Ditë",
|
||||
"estimatedDays": "Ditë të Vlerësuara",
|
||||
"actualDays": "Ditë Aktuale",
|
||||
|
||||
"noCategories": "Nuk u gjetën kategori",
|
||||
"noCategory": "Pa Kategori",
|
||||
"noProjects": "Nuk u gjetën projekte",
|
||||
"noTeams": "Nuk u gjetën ekipe",
|
||||
"noData": "Nuk u gjetën të dhëna"
|
||||
}
|
||||
5
worklenz-frontend/public/locales/alb/unauthorized.json
Normal file
5
worklenz-frontend/public/locales/alb/unauthorized.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "E paautorizuar!",
|
||||
"subtitle": "Nuk jeni të autorizuar të hyni në këtë faqe",
|
||||
"button": "Kthehu në Faqen Kryesore"
|
||||
}
|
||||
4
worklenz-frontend/public/locales/de/404-page.json
Normal file
4
worklenz-frontend/public/locales/de/404-page.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"doesNotExistText": "Entschuldigung, die von Ihnen besuchte Seite existiert nicht.",
|
||||
"backHomeButton": "Zurück zur Startseite"
|
||||
}
|
||||
31
worklenz-frontend/public/locales/de/account-setup.json
Normal file
31
worklenz-frontend/public/locales/de/account-setup.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"continue": "Weiter",
|
||||
|
||||
"setupYourAccount": "Richten Sie Ihr Worklenz-Konto ein.",
|
||||
"organizationStepTitle": "Organisation benennen",
|
||||
"organizationStepLabel": "Wählen Sie einen Namen für Ihr Worklenz-Konto.",
|
||||
|
||||
"projectStepTitle": "Erstellen Sie Ihr erstes Projekt",
|
||||
"projectStepLabel": "An welchem Projekt arbeiten Sie gerade?",
|
||||
"projectStepPlaceholder": "z.B. Marketingplan",
|
||||
|
||||
"tasksStepTitle": "Erstellen Sie Ihre ersten Aufgaben",
|
||||
"tasksStepLabel": "Geben Sie einige Aufgaben ein, die Sie in",
|
||||
"tasksStepAddAnother": "Weitere hinzufügen",
|
||||
|
||||
"emailPlaceholder": "E-Mail-Adresse",
|
||||
"invalidEmail": "Bitte geben Sie eine gültige E-Mail-Adresse ein",
|
||||
"or": "oder",
|
||||
"templateButton": "Aus Vorlage importieren",
|
||||
"goBack": "Zurück",
|
||||
"cancel": "Abbrechen",
|
||||
"create": "Erstellen",
|
||||
"templateDrawerTitle": "Aus Vorlagen auswählen",
|
||||
"step3InputLabel": "Per E-Mail einladen",
|
||||
"addAnother": "Weitere hinzufügen",
|
||||
"skipForNow": "Jetzt überspringen",
|
||||
"formTitle": "Erstellen Sie Ihre erste Aufgabe.",
|
||||
"step3Title": "Laden Sie Ihr Team zur Zusammenarbeit ein",
|
||||
"maxMembers": " (Sie können bis zu 5 Mitglieder einladen)",
|
||||
"maxTasks": " (Sie können bis zu 5 Aufgaben erstellen)"
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"title": "Abrechnungen",
|
||||
"currentBill": "Aktuelle Rechnung",
|
||||
"configuration": "Konfiguration",
|
||||
"currentPlanDetails": "Aktuelle Plan Details",
|
||||
"upgradePlan": "Plan upgraden",
|
||||
"cardBodyText01": "Kostenlose Testversion",
|
||||
"cardBodyText02": "(Ihr Testplan läuft in 1 Monat 19 Tagen ab)",
|
||||
"redeemCode": "Gutscheincode einlösen",
|
||||
"accountStorage": "Kontospeicher",
|
||||
"used": "Verwendet:",
|
||||
"remaining": "Verbleibend:",
|
||||
"charges": "Gebühren",
|
||||
"tooltip": "Gebühren für den aktuellen Abrechnungszeitraum",
|
||||
"description": "Beschreibung",
|
||||
"billingPeriod": "Abrechnungszeitraum",
|
||||
"billStatus": "Rechnungsstatus",
|
||||
"perUserValue": "Pro Benutzer Wert",
|
||||
"users": "Benutzer",
|
||||
|
||||
"amount": "Betrag",
|
||||
"invoices": "Rechnungen",
|
||||
"transactionId": "Transaktions-ID",
|
||||
"transactionDate": "Transaktionsdatum",
|
||||
"paymentMethod": "Zahlungsmethode",
|
||||
"status": "Status",
|
||||
"ltdUsers": "Sie können bis zu {{ltd_users}} Benutzer hinzufügen.",
|
||||
|
||||
"totalSeats": "Gesamte Plätze",
|
||||
"availableSeats": "Verfügbare Plätze",
|
||||
"addMoreSeats": "Weitere Plätze hinzufügen",
|
||||
|
||||
"drawerTitle": "Gutscheincode einlösen",
|
||||
"label": "Gutscheincode",
|
||||
"drawerPlaceholder": "Geben Sie Ihren Gutscheincode ein",
|
||||
"redeemSubmit": "Einreichen",
|
||||
|
||||
"modalTitle": "Wählen Sie den besten Plan für Ihr Team",
|
||||
"seatLabel": "Anzahl der Plätze",
|
||||
"freePlan": "Kostenloser Plan",
|
||||
"startup": "Startup",
|
||||
"business": "Business",
|
||||
"tag": "Am beliebtesten",
|
||||
"enterprise": "Enterprise",
|
||||
|
||||
"freeSubtitle": "kostenlos für immer",
|
||||
"freeUsers": "Ideal für die persönliche Nutzung",
|
||||
"freeText01": "100MB Speicher",
|
||||
"freeText02": "3 Projekte",
|
||||
"freeText03": "5 Teammitglieder",
|
||||
|
||||
"startupSubtitle": "PAUSCHALPREIS / Monat",
|
||||
"startupUsers": "Bis zu 15 Benutzer",
|
||||
"startupText01": "25GB Speicher",
|
||||
"startupText02": "Unbegrenzte aktive Projekte",
|
||||
"startupText03": "Zeitplan",
|
||||
"startupText04": "Berichterstattung",
|
||||
"startupText05": "Projekte abonnieren",
|
||||
|
||||
"businessSubtitle": "Benutzer / Monat",
|
||||
"businessUsers": "16 - 200 Benutzer",
|
||||
|
||||
"enterpriseUsers": "200 - 500+ Benutzer",
|
||||
|
||||
"footerTitle": "Bitte geben Sie uns eine Kontaktnummer, unter der wir Sie erreichen können.",
|
||||
"footerLabel": "Kontaktnummer",
|
||||
"footerButton": "Kontaktieren Sie uns",
|
||||
|
||||
"redeemCodePlaceHolder": "Geben Sie Ihren Gutscheincode ein",
|
||||
"submit": "Einreichen",
|
||||
|
||||
"trialPlan": "Kostenlose Testversion",
|
||||
"trialExpireDate": "Gültig bis {{trial_expire_date}}",
|
||||
"trialExpired": "Ihre kostenlose Testversion ist {{trial_expire_string}} abgelaufen",
|
||||
"trialInProgress": "Ihre kostenlose Testversion läuft {{trial_expire_string}} ab",
|
||||
|
||||
"required": "Dieses Feld ist erforderlich",
|
||||
"invalidCode": "Ungültiger Code",
|
||||
|
||||
"selectPlan": "Wählen Sie den besten Plan für Ihr Team",
|
||||
"changeSubscriptionPlan": "Ändern Sie Ihren Abonnementplan",
|
||||
"noOfSeats": "Anzahl der Plätze",
|
||||
"annualPlan": "Pro - Jährlich",
|
||||
"monthlyPlan": "Pro - Monatlich",
|
||||
"freeForever": "Kostenlos für immer",
|
||||
"bestForPersonalUse": "Ideal für die persönliche Nutzung",
|
||||
"storage": "Speicher",
|
||||
"projects": "Projekte",
|
||||
"teamMembers": "Teammitglieder",
|
||||
"unlimitedTeamMembers": "Unbegrenzte Teammitglieder",
|
||||
"unlimitedActiveProjects": "Unbegrenzte aktive Projekte",
|
||||
"schedule": "Zeitplan",
|
||||
"reporting": "Berichterstattung",
|
||||
"subscribeToProjects": "Projekte abonnieren",
|
||||
"billedAnnually": "Jährlich abgerechnet",
|
||||
"billedMonthly": "Monatlich abgerechnet",
|
||||
|
||||
"pausePlan": "Plan pausieren",
|
||||
"resumePlan": "Plan fortsetzen",
|
||||
"changePlan": "Plan ändern",
|
||||
"cancelPlan": "Plan kündigen",
|
||||
|
||||
"perMonthPerUser": "pro Benutzer/Monat",
|
||||
"viewInvoice": "Rechnung anzeigen",
|
||||
"switchToFreePlan": "Wechsel zum kostenlosen Plan",
|
||||
|
||||
"expirestoday": "heute",
|
||||
"expirestomorrow": "morgen",
|
||||
"expiredDaysAgo": "vor {{days}} Tagen",
|
||||
|
||||
"continueWith": "Fortfahren mit {{plan}}",
|
||||
"changeToPlan": "Wechseln zu {{plan}}"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"overview": "Übersicht",
|
||||
"name": "Organisationsname",
|
||||
"owner": "Organisationsinhaber",
|
||||
"admins": "Organisationsadministratoren",
|
||||
"contactNumber": "Kontaktnummer hinzufügen",
|
||||
"edit": "Bearbeiten"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"membersCount": "Mitgliederanzahl",
|
||||
"createdAt": "Erstellt am",
|
||||
"projectName": "Projektname",
|
||||
"teamName": "Teamname",
|
||||
"refreshProjects": "Projekte aktualisieren",
|
||||
"searchPlaceholder": "Nach Projektname suchen",
|
||||
"deleteProject": "Sind Sie sicher, dass Sie dieses Projekt löschen möchten?",
|
||||
"confirm": "Bestätigen",
|
||||
"cancel": "Abbrechen",
|
||||
"delete": "Projekt löschen"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"overview": "Übersicht",
|
||||
"users": "Benutzer",
|
||||
"teams": "Teams",
|
||||
"billing": "Abrechnung",
|
||||
"projects": "Projekte",
|
||||
"adminCenter": "Admin-Center"
|
||||
}
|
||||
33
worklenz-frontend/public/locales/de/admin-center/teams.json
Normal file
33
worklenz-frontend/public/locales/de/admin-center/teams.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"title": "Teams",
|
||||
"subtitle": "Teams",
|
||||
"tooltip": "Teams aktualisieren",
|
||||
"placeholder": "Nach Namen suchen",
|
||||
"addTeam": "Team hinzufügen",
|
||||
"team": "Team",
|
||||
"membersCount": "Mitgliederanzahl",
|
||||
"members": "Mitglieder",
|
||||
"drawerTitle": "Neues Team erstellen",
|
||||
"label": "Teamname",
|
||||
"drawerPlaceholder": "Name",
|
||||
"create": "Erstellen",
|
||||
"delete": "Löschen",
|
||||
"settings": "Einstellungen",
|
||||
"popTitle": "Sind Sie sicher?",
|
||||
"message": "Bitte geben Sie einen Namen ein",
|
||||
"teamSettings": "Team-Einstellungen",
|
||||
"teamName": "Teamname",
|
||||
"teamDescription": "Teambeschreibung",
|
||||
"teamMembers": "Teammitglieder",
|
||||
"teamMembersCount": "Anzahl der Teammitglieder",
|
||||
"teamMembersPlaceholder": "Nach Namen suchen",
|
||||
"addMember": "Mitglied hinzufügen",
|
||||
"add": "Hinzufügen",
|
||||
"update": "Aktualisieren",
|
||||
"teamNamePlaceholder": "Name des Teams",
|
||||
"user": "Benutzer",
|
||||
"role": "Rolle",
|
||||
"owner": "Besitzer",
|
||||
"admin": "Administrator",
|
||||
"member": "Mitglied"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "Benutzer",
|
||||
"subTitle": "Benutzer",
|
||||
"placeholder": "Nach Namen suchen",
|
||||
"user": "Benutzer",
|
||||
"email": "E-Mail",
|
||||
"lastActivity": "Letzte Aktivität",
|
||||
"refresh": "Benutzer aktualisieren"
|
||||
}
|
||||
23
worklenz-frontend/public/locales/de/all-project-list.json
Normal file
23
worklenz-frontend/public/locales/de/all-project-list.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "Name",
|
||||
"client": "Kunde",
|
||||
"category": "Kategorie",
|
||||
"status": "Status",
|
||||
"tasksProgress": "Aufgabenfortschritt",
|
||||
"updated_at": "Zuletzt aktualisiert",
|
||||
"members": "Mitglieder",
|
||||
"setting": "Einstellungen",
|
||||
"projects": "Projekte",
|
||||
"refreshProjects": "Projekte aktualisieren",
|
||||
"all": "Alle",
|
||||
"favorites": "Favoriten",
|
||||
"archived": "Archiviert",
|
||||
"placeholder": "Nach Namen suchen",
|
||||
"archive": "Archivieren",
|
||||
"unarchive": "Dearchivieren",
|
||||
"archiveConfirm": "Sind Sie sicher, dass Sie dieses Projekt archivieren möchten?",
|
||||
"unarchiveConfirm": "Sind Sie sicher, dass Sie dieses Projekt dearchivieren möchten?",
|
||||
"clickToFilter": "Zum Filtern klicken nach",
|
||||
"noProjects": "Keine Projekte gefunden",
|
||||
"addToFavourites": "Zu Favoriten hinzufügen"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"loggingOut": "Abmelden...",
|
||||
"authenticating": "Authentifizierung läuft...",
|
||||
"gettingThingsReady": "Bereite alles für Sie vor..."
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"headerDescription": "Passwort zurücksetzen",
|
||||
"emailLabel": "E-Mail",
|
||||
"emailPlaceholder": "Ihre E-Mail eingeben",
|
||||
"emailRequired": "Bitte geben Sie Ihre E-Mail-Adresse ein!",
|
||||
"resetPasswordButton": "Passwort zurücksetzen",
|
||||
"returnToLoginButton": "Zurück zum Login",
|
||||
"passwordResetSuccessMessage": "Ein Link zum Zurücksetzen des Passworts wurde an Ihre E-Mail gesendet.",
|
||||
"orText": "ODER",
|
||||
"successTitle": "Anweisung zum Zurücksetzen gesendet!",
|
||||
"successMessage": "Die Informationen zum Zurücksetzen wurden an Ihre E-Mail gesendet. Bitte überprüfen Sie Ihr E-Mail-Postfach."
|
||||
}
|
||||
27
worklenz-frontend/public/locales/de/auth/login.json
Normal file
27
worklenz-frontend/public/locales/de/auth/login.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"headerDescription": "Melden Sie sich an",
|
||||
"emailLabel": "E-Mail",
|
||||
"emailPlaceholder": "Ihre E-Mail-Adresse eingeben",
|
||||
"emailRequired": "Bitte geben Sie Ihre E-Mail-Adresse ein!",
|
||||
"passwordLabel": "Passwort",
|
||||
"passwordPlaceholder": "Ihr Passwort eingeben",
|
||||
"passwordRequired": "Bitte geben Sie Ihr Passwort ein!",
|
||||
"rememberMe": "Erinnere dich an mich",
|
||||
"loginButton": "Anmelden",
|
||||
"signupButton": "Registrieren",
|
||||
"forgotPasswordButton": "Passwort vergessen?",
|
||||
"signInWithGoogleButton": "Mit Google anmelden",
|
||||
"dontHaveAccountText": "Noch kein Konto?",
|
||||
"orText": "ODER",
|
||||
"successMessage": "Sie haben sich erfolgreich angemeldet!",
|
||||
"loginError": "Anmeldung fehlgeschlagen",
|
||||
"googleLoginError": "Google-Anmeldung fehlgeschlagen",
|
||||
"validationMessages": {
|
||||
"email": "Bitte geben Sie eine gültige E-Mail-Adresse ein",
|
||||
"password": "Das Passwort muss mindestens 8 Zeichen lang sein"
|
||||
},
|
||||
"errorMessages": {
|
||||
"loginErrorTitle": "Anmeldung fehlgeschlagen",
|
||||
"loginErrorMessage": "Bitte überprüfen Sie Ihre E-Mail-Adresse und Ihr Passwort und versuchen Sie es erneut"
|
||||
}
|
||||
}
|
||||
29
worklenz-frontend/public/locales/de/auth/signup.json
Normal file
29
worklenz-frontend/public/locales/de/auth/signup.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"headerDescription": "Registrieren Sie sich, um loszulegen",
|
||||
"nameLabel": "Vollständiger Name",
|
||||
"namePlaceholder": "Ihren vollständigen Namen eingeben",
|
||||
"nameRequired": "Bitte geben Sie Ihren vollständigen Namen ein!",
|
||||
"nameMinCharacterRequired": "Der Name muss mindestens 4 Zeichen lang sein!",
|
||||
"emailLabel": "E-Mail",
|
||||
"emailPlaceholder": "Ihre E-Mail-Adresse eingeben",
|
||||
"emailRequired": "Bitte geben Sie Ihre E-Mail-Adresse ein!",
|
||||
"passwordLabel": "Passwort",
|
||||
"passwordPlaceholder": "Ihr Passwort eingeben",
|
||||
"passwordRequired": "Bitte geben Sie Ihr Passwort ein!",
|
||||
"passwordMinCharacterRequired": "Das Passwort muss mindestens 8 Zeichen lang sein!",
|
||||
"passwordPatternRequired": "Das Passwort erfüllt nicht die Anforderungen!",
|
||||
"strongPasswordPlaceholder": "Ein stärkeres Passwort eingeben",
|
||||
"passwordValidationAltText": "Das Passwort muss mindestens 8 Zeichen enthalten, mit Groß- und Kleinbuchstaben, einer Zahl und einem Sonderzeichen.",
|
||||
"signupSuccessMessage": "Sie haben sich erfolgreich registriert!",
|
||||
"privacyPolicyLink": "Datenschutzrichtlinie",
|
||||
"termsOfUseLink": "Nutzungsbedingungen",
|
||||
"bySigningUpText": "Mit der Registrierung stimmen Sie unseren",
|
||||
"andText": "und",
|
||||
"signupButton": "Registrieren",
|
||||
"signInWithGoogleButton": "Mit Google anmelden",
|
||||
"alreadyHaveAccountText": "Sie haben bereits ein Konto?",
|
||||
"loginButton": "Anmelden",
|
||||
"orText": "ODER",
|
||||
"reCAPTCHAVerificationError": "reCAPTCHA-Verifizierungsfehler",
|
||||
"reCAPTCHAVerificationErrorMessage": "Wir konnten Ihre reCAPTCHA nicht verifizieren. Bitte versuchen Sie es erneut."
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"title": "E-Mail zurücksetzen bestätigen",
|
||||
"description": "Geben Sie Ihr neues Passwort ein",
|
||||
"placeholder": "Neues Passwort eingeben",
|
||||
"confirmPasswordPlaceholder": "Neues Passwort bestätigen",
|
||||
"passwordHint": "Mindestens 8 Zeichen, mit Groß- und Kleinbuchstaben, einer Zahl und einem Sonderzeichen.",
|
||||
"resetPasswordButton": "Passwort zurücksetzen",
|
||||
"orText": "Oder",
|
||||
"resendResetEmail": "Zurücksetz-E-Mail erneut senden",
|
||||
"passwordRequired": "Bitte geben Sie Ihr neues Passwort ein",
|
||||
"returnToLoginButton": "Zurück zur Anmeldung",
|
||||
"confirmPasswordRequired": "Bitte bestätigen Sie Ihr neues Passwort",
|
||||
"passwordMismatch": "Die beiden Passwörter stimmen nicht überein"
|
||||
}
|
||||
9
worklenz-frontend/public/locales/de/common.json
Normal file
9
worklenz-frontend/public/locales/de/common.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"login-success": "Anmeldung erfolgreich!",
|
||||
"login-failed": "Anmeldung fehlgeschlagen. Bitte überprüfen Sie Ihre Anmeldedaten und versuchen Sie es erneut.",
|
||||
"signup-success": "Registrierung erfolgreich! Willkommen an Bord.",
|
||||
"signup-failed": "Registrierung fehlgeschlagen. Bitte füllen Sie alle erforderlichen Felder aus und versuchen Sie es erneut.",
|
||||
"reconnecting": "Vom Server getrennt.",
|
||||
"connection-lost": "Verbindung zum Server fehlgeschlagen. Bitte überprüfen Sie Ihre Internetverbindung.",
|
||||
"connection-restored": "Erfolgreich mit dem Server verbunden"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"formTitle": "Erstellen Sie Ihr erstes Projekt",
|
||||
"inputLabel": "An welchem Projekt arbeiten Sie gerade?",
|
||||
"or": "oder",
|
||||
"templateButton": "Aus Vorlage importieren",
|
||||
"createFromTemplate": "Aus Vorlage erstellen",
|
||||
"goBack": "Zurück",
|
||||
"continue": "Weitermachen",
|
||||
"cancel": "Abbrechen",
|
||||
"create": "Erstellen",
|
||||
"templateDrawerTitle": "Aus Vorlagen auswählen",
|
||||
"createProject": "Projekt erstellen"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"formTitle": "Erstellen Sie Ihre erste Aufgabe.",
|
||||
"inputLabel": "Geben Sie einige Aufgaben ein, die Sie erledigen werden in",
|
||||
"addAnother": "Einen weiteren hinzufügen",
|
||||
"goBack": "Zurück",
|
||||
"continue": "Weiter"
|
||||
}
|
||||
46
worklenz-frontend/public/locales/de/home.json
Normal file
46
worklenz-frontend/public/locales/de/home.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"todoList": {
|
||||
"title": "Aufgabenliste",
|
||||
"refreshTasks": "Aufgaben aktualisieren",
|
||||
"addTask": "+ Aufgabe hinzufügen",
|
||||
"noTasks": "Keine Aufgaben",
|
||||
"pressEnter": "Drücken Sie",
|
||||
"toCreate": "zum Erstellen.",
|
||||
"markAsDone": "Als erledigt markieren"
|
||||
},
|
||||
"projects": {
|
||||
"title": "Projekte",
|
||||
"refreshProjects": "Projekte aktualisieren",
|
||||
"noRecentProjects": "Sie sind aktuell keinem Projekt zugewiesen.",
|
||||
"noFavouriteProjects": "Keine Projekte als Favoriten markiert.",
|
||||
"recent": "Kürzlich",
|
||||
"favourites": "Favoriten"
|
||||
},
|
||||
"tasks": {
|
||||
"assignedToMe": "Mir zugewiesen",
|
||||
"assignedByMe": "Von mir zugewiesen",
|
||||
"all": "Alle",
|
||||
"today": "Heute",
|
||||
"upcoming": "Bevorstehend",
|
||||
"overdue": "Überfällig",
|
||||
"noDueDate": "Kein Fälligkeitsdatum",
|
||||
"noTasks": "Keine Aufgaben zum Anzeigen.",
|
||||
"addTask": "+ Aufgabe hinzufügen",
|
||||
"name": "Name",
|
||||
"project": "Projekt",
|
||||
"status": "Status",
|
||||
"dueDate": "Fälligkeitsdatum",
|
||||
"dueDatePlaceholder": "Fälligkeitsdatum festlegen",
|
||||
"tomorrow": "Morgen",
|
||||
"nextWeek": "Nächste Woche",
|
||||
"nextMonth": "Nächster Monat",
|
||||
"projectRequired": "Bitte wählen Sie ein Projekt aus",
|
||||
"pressTabToSelectDueDateAndProject": "Drücken Sie Tab, um ein Fälligkeitsdatum und ein Projekt auszuwählen",
|
||||
"dueOn": "Fällige Aufgaben am",
|
||||
"taskRequired": "Bitte fügen Sie eine Aufgabe hinzu",
|
||||
"list": "Liste",
|
||||
"calendar": "Kalender",
|
||||
"tasks": "Aufgaben",
|
||||
"refresh": "Aktualisieren"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"formTitle": "Laden Sie Ihr Team zur Zusammenarbeit ein",
|
||||
"inputLabel": "Per E-Mail einladen",
|
||||
"addAnother": "Weitere hinzufügen",
|
||||
"goBack": "Zurück",
|
||||
"continue": "Weitermachen",
|
||||
"skipForNow": "Vorerst überspringen"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user