prepare release 1.7 (#1388)

This commit is contained in:
Kevin Papst
2020-01-19 21:49:04 +01:00
committed by GitHub
parent 352fac26f3
commit 9eff89963c
44 changed files with 225 additions and 57 deletions

View File

@@ -1,6 +1,6 @@
# Change Log
## [1.7](https://github.com/kevinpapst/kimai2/tree/1.7) (2020-01-0?)
## [1.7](https://github.com/kevinpapst/kimai2/tree/1.7) (2020-01-19)
[Full Changelog](https://github.com/kevinpapst/kimai2/compare/1.6.2...1.7)
Release notes including the changelog can be found [here](https://github.com/kevinpapst/kimai2/releases/tag/1.7)

View File

@@ -7,8 +7,8 @@ As announced in the [README](README.md) I only support the latest available rele
| Version | Supported |
| ------- | ------------------ |
| master | :white_check_mark: |
| 1.6 | :white_check_mark: |
| < 1.6 | :x: |
| 1.7 | :white_check_mark: |
| < 1.7 | :x: |
## Reporting a Vulnerability

View File

@@ -15,7 +15,7 @@ export default class KimaiPaginatedBoxWidget {
constructor(boxId) {
this.selector = boxId;
this.overlay = jQuery('<div class="overlay"><div class="fa fa-refresh fa-spin"></div></div>');
this.overlay = jQuery('<div class="overlay"><div class="fas fa-sync fa-spin"></div></div>');
this.widget = jQuery(this.selector);
this.href = this.widget.data('href');
this.events = this.widget.data('reload').split(' ');
@@ -63,6 +63,11 @@ export default class KimaiPaginatedBoxWidget {
const html = jQuery(response);
jQuery(selector + ' .box-tools').replaceWith(html.find('.box-tools'));
jQuery(selector + ' .box-body').replaceWith(html.find('.box-body'));
jQuery(selector + ' .box-title').replaceWith(html.find('.box-title'));
if (jQuery(selector + ' .box-footer').length > 0) {
jQuery(selector + ' .box-footer').replaceWith(html.find('.box-footer'));
}
jQuery(selector + ' .box-body [data-toggle="tooltip"]').tooltip();
self.widget.removeData('error-retry');
self._hideOverlay();
},

View File

@@ -14,7 +14,7 @@ import jQuery from "jquery";
export default class KimaiReloadPageWidget {
constructor(events, fullReload) {
this.overlay = jQuery('<div class="overlay-wrapper"><div class="overlay"><div class="fa fa-refresh fa-spin"></div></div></div>');
this.overlay = jQuery('<div class="overlay-wrapper"><div class="overlay"><div class="fas fa-sync fa-spin"></div></div></div>');
this.widget = jQuery('div.content-wrapper');
const self = this;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@
"build/runtime.6ca1eea5.js",
"build/0.1a6ffb43.js",
"build/1.16767f92.js",
"build/app.6ece8872.js"
"build/app.8b409f35.js"
],
"css": [
"build/app.8240996d.css"
@@ -35,7 +35,7 @@
"build/runtime.6ca1eea5.js": "sha384-xNNrNinl64G3nCUrIskgSjU0mUXXCB9lj6XCSInBTwxSKXk8uTMafnLHtdWdIGtd",
"build/0.1a6ffb43.js": "sha384-vuVCyLVj2b4h3jpKl+JSANRCacmXeLk+ihK5T5NZBO7+SJ5Y+o6d4qju116hTPSD",
"build/1.16767f92.js": "sha384-JPoKdrVtBemSiVBoAnmSxLML7xXM9zYeuwOPYQv/kLzt/P4cmLY5r9gH8oaGRPFG",
"build/app.6ece8872.js": "sha384-4GinRERdzHwjjjUjAu6BfF705cW61DDoScnO+mWdMx7FjuXqGrQRlVzjlW7f5k3g",
"build/app.8b409f35.js": "sha384-KLjCz4QplvRgAqezJx4OSJp38bRW0WHel8mmbmGgDtYTKIHBahoGY72PQwD+UU4m",
"build/app.8240996d.css": "sha384-ZaS4ro6HGbDfLyaJc8cVXJzTd8plX3mRzhHhiiUEErSzPlRKdZfViDk23BNvAaz+",
"build/2.dad56560.js": "sha384-oKsefSmRq0GL+Qa6f6jExXvFay3cM6YZFHQRKoAHi2p54UOCtjJfjF2eAB1qykoL",
"build/chart.7f4d7f29.js": "sha384-I57c9DtU3AOG2kzKqIZkIu0hi1aGYHRZ5QG4LKC9+9slzJnAMttPGXoL2cQG3m6y",

View File

@@ -3,7 +3,7 @@
"build/1.16767f92.js": "build/1.16767f92.js",
"build/2.dad56560.js": "build/2.dad56560.js",
"build/app.css": "build/app.8240996d.css",
"build/app.js": "build/app.6ece8872.js",
"build/app.js": "build/app.8b409f35.js",
"build/calendar.css": "build/calendar.ade7bcdf.css",
"build/calendar.js": "build/calendar.13664a8f.js",
"build/chart.js": "build/chart.7f4d7f29.js",

View File

@@ -21,7 +21,7 @@ class Constants
/**
* The current release status, either "stable" or "dev"
*/
public const STATUS = 'dev';
public const STATUS = 'stable';
/**
* The software name
*/

View File

@@ -55,6 +55,29 @@ class DoctorController extends AbstractController
$this->projectDirectory = $projectDirectory;
}
/**
* @Route(path="/flush-log", name="doctor_flush_log", methods={"GET"})
* @Security("is_granted('system_configuration')")
*/
public function deleteLogfileAction(): Response
{
$logfile = $this->getLogFilename();
if (file_exists($logfile)) {
if (!is_writable($logfile)) {
$this->flashError('action.delete.error', ['%reason%' => 'Logfile cannot be written']);
} else {
if (false === file_put_contents($logfile, '')) {
$this->flashError('action.delete.error', ['%reason%' => 'Failed writing to logfile']);
} else {
$this->flashSuccess('action.delete.success');
}
}
}
return $this->redirectToRoute('doctor');
}
/**
* @Route(path="", name="doctor", methods={"GET"})
*/
@@ -62,6 +85,8 @@ class DoctorController extends AbstractController
{
$logLines = 100;
$canDeleteLogfile = $this->isGranted('system_configuration') && is_writable($this->getLogFilename());
return $this->render('doctor/index.html.twig', array_merge(
[
'modules' => get_loaded_extensions(),
@@ -70,6 +95,7 @@ class DoctorController extends AbstractController
'settings' => $this->getIniSettings(),
'extensions' => $this->getLoadedExtensions(),
'directories' => $this->getFilePermissions(),
'log_delete' => $canDeleteLogfile,
'logs' => $this->getLog(),
'logLines' => $logLines,
'logSize' => $this->getLogSize(),
@@ -106,20 +132,31 @@ class DoctorController extends AbstractController
return filesize($logfile);
}
private function getLog(int $lines = 100)
private function getLogFilename(): string
{
// why is this check here ???
if (!in_array(getenv('APP_ENV'), ['test', 'dev', 'prod'])) {
return [
'Unsupported log environment'
];
throw new \RuntimeException('Unsupported log environment');
}
$logfileName = 'var/log/' . getenv('APP_ENV') . '.log';
$logfile = $this->projectDirectory . '/' . $logfileName;
return $this->projectDirectory . '/' . $logfileName;
}
private function getLog(int $lines = 100)
{
try {
$logfile = $this->getLogFilename();
} catch (\Exception $ex) {
return [
$ex->getMessage()
];
}
if (!file_exists($logfile)) {
return [
'Could not find logfile: ' . $logfileName
'Empty or missing logfile'
];
}

View File

@@ -64,6 +64,7 @@ class ThemeOptionsSubscriber implements EventSubscriberInterface
/** @var User $user */
$user = $this->storage->getToken()->getUser();
/** @var UserPreference $ref */
foreach ($user->getPreferences() as $ref) {
$name = $ref->getName();
switch ($name) {
@@ -73,6 +74,16 @@ class ThemeOptionsSubscriber implements EventSubscriberInterface
}
break;
case 'theme.layout':
if ($ref->getValue() === 'boxed') {
$this->helper->setOption('boxed_layout', true);
$this->helper->setOption('fixed_layout', false);
} elseif ($ref->getValue() === 'fixed') {
$this->helper->setOption('boxed_layout', false);
$this->helper->setOption('fixed_layout', true);
}
break;
case 'theme.collapsed_sidebar':
$this->helper->setOption('collapsed_sidebar', $ref->getValue());
break;

View File

@@ -18,6 +18,7 @@ use App\Form\Type\CalendarViewType;
use App\Form\Type\InitialViewType;
use App\Form\Type\LanguageType;
use App\Form\Type\SkinType;
use App\Form\Type\ThemeLayoutType;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
@@ -128,6 +129,12 @@ class UserPreferenceSubscriber implements EventSubscriberInterface
->setOrder(400)
->setType(SkinType::class),
(new UserPreference())
->setName('theme.layout')
->setValue('fixed')
->setOrder(450)
->setType(ThemeLayoutType::class),
(new UserPreference())
->setName('theme.collapsed_sidebar')
->setValue(false)

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Custom form field type to select the theme layout.
*/
class ThemeLayoutType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'required' => true,
'choices' => [
'fixed' => 'fixed',
'boxed' => 'boxed',
]
]);
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return ChoiceType::class;
}
}

View File

@@ -37,8 +37,8 @@ class UserCreateType extends UserEditType
->add('plainPassword', RepeatedType::class, [
'required' => true,
'type' => PasswordType::class,
'first_options' => ['label' => 'label.password'],
'second_options' => ['label' => 'label.password_repeat'],
'first_options' => ['label' => 'label.password', 'attr' => ['autocomplete' => 'new-password']],
'second_options' => ['label' => 'label.password_repeat', 'attr' => ['autocomplete' => 'new-password']],
]);
parent::buildForm($builder, $options);

View File

@@ -29,8 +29,8 @@ class UserPasswordType extends AbstractType
$builder
->add('plainPassword', RepeatedType::class, [
'type' => PasswordType::class,
'first_options' => ['label' => 'label.password'],
'second_options' => ['label' => 'label.password_repeat'],
'first_options' => ['label' => 'label.password', 'attr' => ['autocomplete' => 'new-password']],
'second_options' => ['label' => 'label.password_repeat', 'attr' => ['autocomplete' => 'new-password']],
])
;
}

View File

@@ -304,6 +304,8 @@ final class InvoiceModel
'project.name' => $project->getName(),
'project.comment' => $project->getComment(),
'project.order_number' => $project->getOrderNumber(),
'project.start_date' => null !== $project->getStart() ? $formatter->getFormattedDateTime($project->getStart()) : '',
'project.end_date' => null !== $project->getEnd() ? $formatter->getFormattedDateTime($project->getEnd()) : '',
'project.order_date' => null !== $project->getOrderDate() ? $formatter->getFormattedDateTime($project->getOrderDate()) : '',
'project.fixed_rate' => $formatter->getFormattedMoney($project->getFixedRate(), $currency),
'project.fixed_rate_nc' => $formatter->getFormattedMoney($project->getFixedRate(), null),
@@ -408,14 +410,47 @@ final class InvoiceModel
'entry.user_name' => $user->getUsername(),
'entry.user_title' => $user->getTitle(),
'entry.user_alias' => $user->getAlias(),
'entry.activity' => $activity->getName(),
'entry.activity_id' => $activity->getId(),
'entry.project' => $project->getName(),
'entry.project_id' => $project->getId(),
'entry.customer' => $customer->getName(),
'entry.customer_id' => $customer->getId(),
];
if (null !== $activity) {
$values = array_merge($values, [
'entry.activity' => $activity->getName(),
'entry.activity_id' => $activity->getId(),
]);
foreach ($activity->getVisibleMetaFields() as $metaField) {
$values = array_merge($values, [
'entry.activity.meta.' . $metaField->getName() => $metaField->getValue(),
]);
}
}
if (null !== $project) {
$values = array_merge($values, [
'entry.project' => $project->getName(),
'entry.project_id' => $project->getId(),
]);
foreach ($project->getVisibleMetaFields() as $metaField) {
$values = array_merge($values, [
'entry.project.meta.' . $metaField->getName() => $metaField->getValue(),
]);
}
}
if (null !== $customer) {
$values = array_merge($values, [
'entry.customer' => $customer->getName(),
'entry.customer_id' => $customer->getId(),
]);
foreach ($customer->getVisibleMetaFields() as $metaField) {
$values = array_merge($values, [
'entry.customer.meta.' . $metaField->getName() => $metaField->getValue(),
]);
}
}
foreach ($invoiceItem->getAdditionalFields() as $name => $value) {
$values = array_merge($values, [
'entry.meta.' . $name => $value,

View File

@@ -131,7 +131,7 @@
{% endif %}
{% for metaField in customer.visibleMetaFields %}
<tr>
<th>{{ metaField.name }}</th>
<th>{{ metaField.label }}</th>
<td>{{ widgets.form_type_value(metaField.type, metaField.value, customer) }}</td>
</tr>
{% endfor %}
@@ -168,7 +168,7 @@
{{ parent() }}
<script type="text/javascript">
document.addEventListener('kimai.initialized', function() {
KimaiReloadPageWidget.create('kimai.customerTeamUpdate kimai.customerUpdate kimai.teamUpdate');
KimaiReloadPageWidget.create('kimai.customerTeamUpdate kimai.customerUpdate kimai.teamUpdate kimai.projectTeamUpdate kimai.projectUpdate');
});
</script>
{% endblock %}

View File

@@ -1,6 +1,7 @@
{% if projects|length > 0 %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with {'customer': customer, 'projects': projects, 'page': page} %}
{% import "project/actions.html.twig" as actions %}
{% import "macros/widgets.html.twig" as widgets %}
{% block box_title %}{{ 'menu.admin_project'|trans }}{% endblock %}
{% block box_attributes %}
id="project_list_box" data-href="{{ path('customer_projects', {'id': customer.id}) }}" data-reload="kimai.projectUpdate"
@@ -17,6 +18,13 @@
<tr>
<td>{{ project.name }}</td>
<td>{{ project.comment|comment2html }}</td>
<td>
{% if project.teams|length > 0 %}
{{ widgets.badge_counter(project.teams|length) }}
{% else %}
{{ widgets.icon('unlocked') }}
{% endif %}
</td>
<td class="actions">{{ actions.project(project, 'custom') }}</td>
</tr>
{% endfor %}

View File

@@ -74,6 +74,11 @@
{% endif %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with logOpts %}
{% block box_title %}Logfile (max. {{ logLines }} last lines){% endblock %}
{% block box_tools %}
{% if log_delete %}
<a class="btn-box-tool confirmation-link" href="{{ path('doctor_flush_log') }}" data-question="confirm.delete"><i class="{{ 'delete'|icon }}"></i></a>
{% endif %}
{% endblock %}
{% block box_body %}
{% if logSize > 52428800 %}
<p>Your logfile is larger than 50 MB, consider deleting it (it will be re-created automatically).</p>

View File

@@ -22,7 +22,7 @@
<a href="{{ path(route_pin, {'id': comment.id}) }}" class="btn btn-default btn-xs {% if comment.pinned %}active{% endif %}"><i class="{{ 'pin'|icon }}"></i></a>
{% endif %}
{% if route_delete is not null %}
<a href="{{ path(route_delete, {'id': comment.id}) }}" class="confirmation-link btn btn-default btn-xs" data-method="POST" data-question="confirm.delete" data-msg-error="action.delete.error" data-msg-success="action.delete.success"><i class="{{ 'delete'|icon }}"></i></a>
<a href="{{ path(route_delete, {'id': comment.id}) }}" class="confirmation-link btn btn-default btn-xs" data-question="confirm.delete"><i class="{{ 'delete'|icon }}"></i></a>
{% endif %}
{{ comment.createdAt|date_full }}
</span>

View File

@@ -105,7 +105,7 @@
{% endif %}
{% for metaField in project.visibleMetaFields %}
<tr>
<th>{{ metaField.name }}</th>
<th>{{ metaField.label }}</th>
<td>{{ widgets.form_type_value(metaField.type, metaField.value, project) }}</td>
</tr>
{% endfor %}

View File

@@ -12,6 +12,11 @@
{% if tags|length == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
<script type="text/javascript">
document.addEventListener('kimai.initialized', function() {
KimaiReloadPageWidget.create('kimai.tagUpdate');
});
</script>
{% else %}
{% set columns = {

View File

@@ -58,6 +58,11 @@
{% if entries.count == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
<script type="text/javascript">
document.addEventListener('kimai.initialized', function() {
KimaiReloadPageWidget.create('kimai.timesheetUpdate');
});
</script>
{% else %}
{{ tables.datatable_header(tableName, columns, query, {'striped': not showSummary, 'reload': 'kimai.timesheetUpdate'}) }}

View File

@@ -12,7 +12,7 @@
{% set options = {'class': 'alwaysVisible text-center'} %}
{% if canEditPermissions and role.name not in system_roles|keys %}
{% set widget %}
&nbsp;<a href="{{ path('admin_user_role_delete', {'id': role.id}) }}" class="confirmation-link" data-question="confirm.delete" data-msg-error="action.delete.error" data-msg-success="action.delete.success">{{ widgets.icon('trash') }}</a>
&nbsp;<a href="{{ path('admin_user_role_delete', {'id': role.id}) }}" class="confirmation-link" data-question="confirm.delete">{{ widgets.icon('trash') }}</a>
{% endset %}
{% set options = options|merge({'html_after': widget}) %}
{% endif %}

View File

@@ -9,18 +9,12 @@
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/progressbar.html.twig" as progress %}
{% block box_attributes %}id="{{ widgetId }}"{% endblock %}
{% block box_body_class %}no-padding{% endblock %}
{% block box_title %}
{% if not title is empty %}{{ title|trans }}{% endif %}
{% endblock %}
{% block box_body %}
<table class="table table-hover dataTable" role="grid">
<thead>
<tr>
<th>{{ 'label.project'|trans }}</th>
<th class="hidden-xs hidden-sm hidden-md">{{ 'label.team'|trans }}</th>
<th style="width:50%">{{ 'label.progress'|trans }}</th>
</tr>
</thead>
<tbody>
{% for stats in projectStats %}
{% set project = stats.project %}
@@ -33,7 +27,7 @@
<td class="hidden-xs hidden-sm hidden-md">
{% for team in project.teams %}
{% if app.user.isInTeam(team) %}
{{ widgets.label_team(team) }}
{{ team.name }}
{% endif %}
{% endfor %}
</td>

View File

@@ -402,6 +402,7 @@ class ProfileControllerTest extends ControllerBaseTest
['name' => 'timezone', 'value' => 'America/Creston'],
['name' => 'language', 'value' => 'ar'],
['name' => UserPreference::SKIN, 'value' => 'blue'],
['name' => 'theme.layout', 'value' => 'fixed'],
['name' => 'theme.collapsed_sidebar', 'value' => true],
['name' => 'calendar.initial_view', 'value' => 'agendaDay'],
]

View File

@@ -135,6 +135,8 @@ class DebugRendererTest extends TestCase
'project.hourly_rate_nc',
'project.hourly_rate_plain',
'project.meta.foo-project',
'project.start_date',
'project.end_date',
]);
}
@@ -174,10 +176,13 @@ class DebugRendererTest extends TestCase
'entry.user_title',
'entry.activity',
'entry.activity_id',
'entry.activity.meta.foo-activity',
'entry.project',
'entry.customer',
'entry.project_id',
'entry.project.meta.foo-project',
'entry.customer',
'entry.customer_id',
'entry.customer.meta.foo-customer',
'entry.category',
'entry.type',
];

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="about.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="about.en.xlf">
<body>
<trans-unit id="about.title">
<source>about.title</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="daterangepicker.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="daterangepicker.en.xlf">
<body>
<trans-unit id="daterangepicker.today">
<source>daterangepicker.today</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="exceptions.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="exceptions.en.xlf">
<body>
<trans-unit id="access.denied">
<source>access.denied</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="flashmessages.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="flashmessages.en.xlf">
<body>
<trans-unit id="warning">
<source>warning</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="invoice-calculator.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="invoice-calculator.en.xlf">
<body>
<trans-unit id="label.invoice_calculator">
<source>label.invoice_calculator</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="invoice-numbergenerator.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="invoice-numbergenerator.en.xlf">
<body>
<trans-unit id="label.invoice_number_generator">
<source>label.invoice_number_generator</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="invoice-renderer.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="invoice-renderer.en.xlf">
<body>
<trans-unit id="label.invoice_renderer">
<source>label.invoice_renderer</source>

View File

@@ -266,7 +266,11 @@
</trans-unit>
<trans-unit id="label.skin">
<source>label.skin</source>
<target>Kimai-Theme</target>
<target>Darstellung: Farben</target>
</trans-unit>
<trans-unit id="label.theme.layout">
<source>label.theme.layout</source>
<target>Darstellung: Layout</target>
</trans-unit>
<trans-unit id="label.hours">
<source>label.hours</source>

View File

@@ -266,7 +266,11 @@
</trans-unit>
<trans-unit id="label.skin">
<source>label.skin</source>
<target>Kimai-Theme</target>
<target>Display: colors</target>
</trans-unit>
<trans-unit id="label.theme.layout">
<source>label.theme.layout</source>
<target>Display: layout</target>
</trans-unit>
<trans-unit id="label.hours">
<source>label.hours</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="messages.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="messages.en.xlf">
<body>
<!--
Global template keys

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="pagerfanta.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="pagerfanta.en.xlf">
<body>
<trans-unit id="previous">
<source>previous</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="fr" datatype="plaintext" original="plugins.en.xliff ">
<file source-language="en" target-language="fr" datatype="plaintext" original="plugins.en.xlf">
<body>
<trans-unit id="plugins.title">
<source>plugins.title</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="plugins.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="plugins.en.xlf">
<body>
<trans-unit id="plugins.title">
<source>plugins.title</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="system-configuration.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="system-configuration.en.xlf">
<body>
<trans-unit id="title">
<source>title</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="tags.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="tags.en.xlf">
<body>
<trans-unit id="tags.title">
<source>tags.title</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="teams.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="teams.en.xlf">
<body>
<trans-unit id="teams.title">
<source>teams.title</source>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="validators.en.xliff">
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="validators.en.xlf">
<body>
<trans-unit id="This value is not a valid role.">
<source>This value is not a valid role.</source>