prepare release 1.12 (#2183)

* updated dependencies (#2125)
* display application name and version in console (#2150)
This commit is contained in:
Kevin Papst
2020-12-10 16:25:14 +01:00
committed by GitHub
parent 78d8212e57
commit 26c2d5aa81
29 changed files with 2042 additions and 2376 deletions

View File

@@ -1,5 +1,5 @@
unreleased=true
future-release=1.11.1
exclude-labels=duplicate,support,question,invalid,wontfix,release
future-release=1.12
exclude-labels=duplicate,support,question,invalid,wontfix,release,waiting for feedback
enhancement_labels=>enhancement,Enhancement,feature request,translation i18n,technical debt,documentation
issues-wo-labels=false

View File

@@ -1,5 +1,10 @@
# Changelog
## [1.12](https://github.com/kevinpapst/kimai2/tree/1.12)
[Full Changelog](https://github.com/kevinpapst/kimai2/compare/1.11.1...1.12)
Release notes including the changelog can be found [here](https://github.com/kevinpapst/kimai2/releases/tag/1.12)
## [1.11.1](https://github.com/kevinpapst/kimai2/tree/1.11.1)
[Full Changelog](https://github.com/kevinpapst/kimai2/compare/1.11...1.11.1)

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.11 | :white_check_mark: |
| < 1.11 | :x: |
| 1.12 | :white_check_mark: |
| < 1.12 | :x: |
## Reporting a Vulnerability

View File

@@ -8,6 +8,10 @@ you can upgrade your Kimai installation to the latest stable release.
Check below if there are more version specific steps required, which need to be executed after the normal update process.
Perform EACH version specific task between your version and the new one, otherwise you risk data inconsistency or a broken installation.
## [1.12](https://github.com/kevinpapst/kimai2/releases/tag/1.12)
- Export templates can now include items from plugins (eg. Expenses).
## [1.10](https://github.com/kevinpapst/kimai2/releases/tag/1.10)
**New database tables and fields were created, don't forget to [run the updater](https://www.kimai.org/documentation/updates.html).**

View File

@@ -48,7 +48,7 @@ export default class KimaiConfirmationLink extends KimaiPlugin {
if (value) {
if (form === null) {
document.location = url;
} else {
} else {
if (url !== null) {
form.action = url;
}

View File

@@ -14,10 +14,10 @@ import KimaiPlugin from "../KimaiPlugin";
export default class KimaiReducedClickHandler extends KimaiPlugin {
_addClickHandler(selector, callback)  {
_addClickHandler(selector, callback) {
jQuery('body').on('click', selector, function(event) {
// just in case an inner element is editable, than this should not be triggered
if (event.target.parentNode.isContentEditable || event.target.isContentEditable) {
if (event.target.parentNode.isContentEditable || event.target.isContentEditable) {
return;
}

View File

@@ -2,7 +2,7 @@
<?php
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use App\ConsoleApplication;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\Dotenv\Dotenv;
@@ -25,5 +25,5 @@ if ($debug) {
}
$kernel = new Kernel($env, $debug);
$application = new Application($kernel);
$application = new ConsoleApplication($kernel);
$application->run($input);

View File

@@ -24,8 +24,9 @@
"doctrine/doctrine-migrations-bundle": "^2.1",
"doctrine/orm": "^2.7",
"erusev/parsedown": "^1.6",
"friendsofsymfony/rest-bundle": "^2.5",
"friendsofsymfony/rest-bundle": "^3.0",
"gedmo/doctrine-extensions": "^2.4",
"handcraftedinthealps/rest-routing-bundle": "^1.0",
"hslavich/oneloginsaml-bundle": "^1.4",
"jms/metadata": "^2.0",
"jms/serializer-bundle": "^3.2",

4039
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -21,4 +21,5 @@ return [
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
HandcraftedInTheAlps\RestRoutingBundle\RestRoutingBundle::class => ['all' => true],
];

View File

@@ -1,111 +1,52 @@
# TODO upgrade to 2.8
# https://github.com/FriendsOfSymfony/FOSRestBundle/releases/tag/2.8.0
fos_rest:
# disable_csrf_role: IS_AUTHENTICATED_ANONYMOUSLY
# unauthorized_challenge: null
param_fetcher_listener:
enabled: true
# force: false
# service: null
cache_dir: '%kernel.cache_dir%/fos_rest'
# allowed_methods_listener:
# enabled: false
# service: null
# TODO activate with 2.8
# routing_loader: false
routing_loader:
default_format: json
include_format: true
enabled: true
cache_dir: '%kernel.cache_dir%/fos_rest'
routing_loader: false
body_converter:
enabled: true
# validate: false
# validation_errors_argument: validationErrors
# service:
# router: router
# templating: templating
# serializer: null
# view_handler: fos_rest.view_handler.default
# inflector: fos_rest.inflector.doctrine
# validator: validator
enabled: true
serializer:
# version: null
# groups: []
serialize_null: true
serialize_null: true
view:
default_engine: twig
# force_redirects:
# name: ~
# mime_types:
# enabled: false
# service: null
# formats:
# name: ~
formats:
json: true
xml: false
# templating_formats:
# name: ~
view_response_listener:
enabled: true
# force: true
# service: null
failed_validation: 400
# empty_content: 204
# serialize_null: false
# jsonp_handler:
# callback_param: callback
# mime_type: application/javascript+jsonp
enabled: true
failed_validation: 400
exception:
enabled: true
# TODO active with 2.8
# serialize_exceptions: false
# TODO deprecated with 2.8
# https://github.com/FriendsOfSymfony/FOSRestBundle/issues/2200#issuecomment-629150462
# https://github.com/FriendsOfSymfony/FOSRestBundle/issues/2224
exception_controller: 'fos_rest.exception.controller:showAction'
enabled: true
map_exception_codes: true
serializer_error_renderer: true
serialize_exceptions: false
exception_listener: false
codes:
# 'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
# 'Doctrine\ORM\OptimisticLockException': HTTP_CONFLICT
# 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException': 400
'Symfony\Component\HttpKernel\Exception\BadRequestHttpException': 400
'App\Validator\ValidationFailedException': 400
messages:
'Symfony\Component\Routing\Exception\ResourceNotFoundException': true
'Symfony\Component\HttpKernel\Exception\NotFoundHttpException': true
'Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException': 401
'Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException': 403
'Symfony\Component\Routing\Exception\ResourceNotFoundException': 404
'Symfony\Component\HttpKernel\Exception\NotFoundHttpException': 404
'App\API\NotFoundException': 404
body_listener:
enabled: true
# service: null
# default_format: null
# throw_exception_on_unsupported_content_type: false
# decoders:
# name: ~
enabled: true
decoders:
json: fos_rest.decoder.json
array_normalizer:
service: fos_rest.normalizer.camel_keys
forms: true
service: fos_rest.normalizer.camel_keys
forms: true
format_listener:
enabled: true
# service: null
rules:
- { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json ] }
# host: null # URL host name
# methods: null # Method for URL
# stop: false
# attributes: []
# versioning:
# enabled: false
# default_version: ~
# resolvers:
# query:
# enabled: true
# parameter_name: version
# custom_header:
# enabled: true
# header_name: X-Accept-Version
# media_type:
# enabled: true
# regex: /(v|version)=(?P<version>[0-9\.]+)/
# guessing_order:
# - query
# - custom_header
# - media_type
zone:
- { path: ^/api/* }
handcraftedinthealps_rest_routing:
routing_loader:
default_format: 'json'
prefix_methods: true
include_format: true
formats:
json: true
xml: false

View File

@@ -1,5 +1,4 @@
twig:
#paths: ['%kernel.project_dir%/templates']
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
form_themes:

View File

@@ -22,10 +22,10 @@ use App\Repository\ActivityRepository;
use App\Repository\Query\ActivityQuery;
use App\Utils\SearchTerm;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\RestBundle\Request\ParamFetcherInterface;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;

View File

@@ -22,10 +22,10 @@ use App\Repository\CustomerRepository;
use App\Repository\Query\CustomerQuery;
use App\Utils\SearchTerm;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\RestBundle\Request\ParamFetcherInterface;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;

View File

@@ -23,10 +23,10 @@ use App\Repository\ProjectRepository;
use App\Repository\Query\ProjectQuery;
use App\Utils\SearchTerm;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\RestBundle\Request\ParamFetcherInterface;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;

View File

@@ -15,10 +15,10 @@ use App\Entity\Tag;
use App\Form\API\TagApiEditForm;
use App\Repository\TagRepository;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\RestBundle\Request\ParamFetcherInterface;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;

View File

@@ -22,10 +22,10 @@ use App\Repository\CustomerRepository;
use App\Repository\ProjectRepository;
use App\Repository\TeamRepository;
use App\Repository\UserRepository;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\RestBundle\Request\ParamFetcherInterface;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;

View File

@@ -24,10 +24,10 @@ use App\Timesheet\TrackingModeService;
use App\Utils\SearchTerm;
use Doctrine\Common\Collections\ArrayCollection;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\RestBundle\Request\ParamFetcherInterface;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
use Pagerfanta\Pagerfanta;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

View File

@@ -19,10 +19,10 @@ use App\Repository\Query\UserQuery;
use App\Repository\UserRepository;
use App\Utils\SearchTerm;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\RestBundle\Request\ParamFetcherInterface;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Swagger\Annotations as SWG;

View File

@@ -0,0 +1,25 @@
<?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;
use Symfony\Bundle\FrameworkBundle\Console\Application;
class ConsoleApplication extends Application
{
public function getName()
{
return Constants::SOFTWARE;
}
public function getVersion()
{
return Constants::VERSION;
}
}

View File

@@ -17,7 +17,7 @@ class Constants
/**
* The current release version
*/
public const VERSION = '1.11.1';
public const VERSION = '1.12';
/**
* The current release status, either "stable" or "dev"
*/

View File

@@ -99,6 +99,9 @@
"doctrine/reflection": {
"version": "v1.0.0"
},
"doctrine/sql-formatter": {
"version": "1.1.1"
},
"egulias/email-validator": {
"version": "2.1.3"
},
@@ -135,44 +138,8 @@
"guzzlehttp/psr7": {
"version": "1.6.1"
},
"hoa/compiler": {
"version": "3.17.08.08"
},
"hoa/consistency": {
"version": "1.17.05.02"
},
"hoa/event": {
"version": "1.17.01.13"
},
"hoa/exception": {
"version": "1.17.01.16"
},
"hoa/file": {
"version": "1.17.07.11"
},
"hoa/iterator": {
"version": "2.17.01.10"
},
"hoa/math": {
"version": "1.17.05.16"
},
"hoa/protocol": {
"version": "1.17.01.14"
},
"hoa/regex": {
"version": "1.17.01.13"
},
"hoa/stream": {
"version": "1.17.02.21"
},
"hoa/ustring": {
"version": "4.17.01.16"
},
"hoa/visitor": {
"version": "2.17.01.16"
},
"hoa/zformat": {
"version": "1.17.01.10"
"handcraftedinthealps/rest-routing-bundle": {
"version": "1.0.0"
},
"hslavich/oneloginsaml-bundle": {
"version": "v1.4.1"
@@ -189,9 +156,6 @@
"intervention/image": {
"version": "2.5.0"
},
"jdorn/sql-formatter": {
"version": "v1.2.17"
},
"jms/metadata": {
"version": "1.6.0"
},
@@ -225,6 +189,9 @@
"lorenzo/pinky": {
"version": "1.0.5"
},
"maennchen/zipstream-php": {
"version": "2.1.0"
},
"markbaker/complex": {
"version": "1.4.6"
},
@@ -240,6 +207,9 @@
"myclabs/deep-copy": {
"version": "1.7.0"
},
"myclabs/php-enum": {
"version": "1.7.6"
},
"nelmio/api-doc-bundle": {
"version": "3.0",
"recipe": {
@@ -357,6 +327,12 @@
"psr/container": {
"version": "1.0.0"
},
"psr/http-client": {
"version": "1.0.1"
},
"psr/http-factory": {
"version": "1.0.1"
},
"psr/http-message": {
"version": "1.0.1"
},
@@ -471,6 +447,9 @@
"symfony/dependency-injection": {
"version": "v4.0.3"
},
"symfony/deprecation-contracts": {
"version": "v2.2.0"
},
"symfony/doctrine-bridge": {
"version": "v4.0.3"
},

View File

@@ -31,22 +31,19 @@
{% if not customer.visible %}
<tr>
<th>{{ 'label.visible'|trans }}</th>
<td>
{{ widgets.label_boolean(customer.visible) }}
</td>
<td>{{ widgets.label_boolean(customer.visible) }}</td>
</tr>
{% endif %}
{% if customer.address is not empty %}
<tr>
<th>{{ 'label.address'|trans }}</th>
<td>
{{ customer.address|nl2br }}
{% if customer.country is not empty %}
<br>
{{ customer.country|country }}
{% endif %}
</td>
<td>{{ customer.address|nl2br }}</td>
</tr>
{% endif %}
{% if customer.country is not empty %}
<tr>
<th>{{ 'label.country'|trans }}</th>
<td>{{ customer.country|country }}</td>
</tr>
{% endif %}
{% if customer.contact is not empty %}
@@ -88,7 +85,7 @@
{% if customer.timezone is not empty %}
<tr>
<th>{{ 'label.timezone'|trans }}</th>
<td><span data-toggle="tooltip" data-placement="top" title="{{ customer.timezone }}">{{ now|date_time }}</span></td>
<td>{{ now|date_full }} ({{ customer.timezone }})</td>
</tr>
{% endif %}
{% if customer.currency is not empty %}

View File

@@ -56,7 +56,6 @@ class AppExtensionTest extends TestCase
],
],
'data_dir' => '/tmp/',
'plugin_dir' => '/tmp/', // still here, to make sure that this value is NOT applied!
'timesheet' => [],
'saml' => [
'connection' => []
@@ -325,6 +324,21 @@ class AppExtensionTest extends TestCase
$this->extension->load($minConfig, $container = $this->getContainer());
}
/**
* @expectedDeprecation Changing the plugin directory via "kimai.plugin_dir" is not supported since 1.9
* @group legacy
*/
public function testChangingPluginsIsIgnoredAndTriggersDeprecation()
{
$minConfig = $this->getMinConfig();
$minConfig['kimai']['plugin_dir'] = '/tmp/';
$expected = realpath(__DIR__ . '/../../') . '/var/plugins';
$this->extension->load($minConfig, $container = $this->getContainer());
$this->assertEquals($expected, $container->getParameter('kimai.plugin_dir'), 'Invalid config: kimai.plugin_dir');
}
public function testLdapDefaultValues()
{
$minConfig = $this->getMinConfig();

View File

@@ -18,11 +18,10 @@ use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
*/
class ConfigurationTest extends TestCase
{
protected function getMinConfig($dataDir = '/tmp/', $pluginDir = '/tmp/')
protected function getMinConfig($dataDir = '/tmp/')
{
return [
'data_dir' => $dataDir,
'plugin_dir' => $pluginDir,
'timesheet' => [],
];
}
@@ -52,12 +51,17 @@ class ConfigurationTest extends TestCase
$this->assertConfig($this->getMinConfig('sdfsdfsdfds'), []);
}
/**
* @expectedDeprecation Changing the plugin directory via "kimai.plugin_dir" is not supported since 1.9
* @group legacy
*/
public function testValidatePluginDir()
{
$finalizedConfig = $this->getCompiledConfig($this->getMinConfig());
$finalizedConfig['plugin_dir'] = 'sdfsdfs';
$config = $this->getMinConfig();
$config['plugin_dir'] = '/tmp/';
$config = $this->getMinConfig('/tmp/', 'sdfsdfs');
$finalizedConfig = $this->getCompiledConfig($config);
$finalizedConfig['plugin_dir'] = '/tmp/';
$this->assertConfig($config, $finalizedConfig);
}
@@ -257,7 +261,6 @@ class ConfigurationTest extends TestCase
{
$fullDefaultConfig = [
'data_dir' => '/tmp/',
'plugin_dir' => '/tmp/',
'timesheet' => [
'default_begin' => 'now',
'mode' => 'default',

View File

@@ -2,10 +2,6 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<file source-language="en" target-language="ar" datatype="plaintext" original="email.en.xlf">
<body>
<trans-unit id="button_copy_url_to_browser">
<source>button_copy_url_to_browser</source>
<target/>
</trans-unit>
<trans-unit id="automated_email_dont_answer">
<source>automated_email_dont_answer</source>
<target>هذا بريد آلي. رجاء لاترد، بريدك لن يقرء.</target>
@@ -22,26 +18,6 @@
<source>registration.button</source>
<target>فعل حسابك</target>
</trans-unit>
<trans-unit id="registration.intro">
<source>registration.intro</source>
<target/>
</trans-unit>
<trans-unit id="reset.subject">
<source>reset.subject</source>
<target/>
</trans-unit>
<trans-unit id="reset.title">
<source>reset.title</source>
<target/>
</trans-unit>
<trans-unit id="reset.button">
<source>reset.button</source>
<target/>
</trans-unit>
<trans-unit id="reset.intro">
<source>reset.intro</source>
<target/>
</trans-unit>
</body>
</file>
</xliff>

View File

@@ -54,11 +54,11 @@
-->
<trans-unit id="label.password">
<source>label.password</source>
<target>Senha</target>
<target>Palavra-passe</target>
</trans-unit>
<trans-unit id="label.password_repeat">
<source>label.password_repeat</source>
<target>Repita a Senha</target>
<target>Repita a palavra-passe</target>
</trans-unit>
<trans-unit id="label.logout">
<source>label.logout</source>
@@ -70,11 +70,11 @@
</trans-unit>
<trans-unit id="label.api_token">
<source>label.api_token</source>
<target>Senha API</target>
<target>Palavra-passe da API</target>
</trans-unit>
<trans-unit id="label.api_token_repeat">
<source>label.api_token_repeat</source>
<target>Repita Senha da API</target>
<target>Repita a palavra-passe da API</target>
</trans-unit>
<!--
Menu / Navbar items
@@ -366,7 +366,7 @@
</trans-unit>
<trans-unit id="profile.password">
<source>profile.password</source>
<target>Senha</target>
<target>Palavra-passe</target>
</trans-unit>
<trans-unit id="profile.api-token">
<source>profile.api-token</source>
@@ -618,7 +618,7 @@
</trans-unit>
<trans-unit id="stats.userActiveWeek">
<source>stats.userActiveWeek</source>
<target>Usuários ativos nessa semana</target>
<target>Utilizadores ativos nessa semana</target>
</trans-unit>
<trans-unit id="stats.userActiveMonth">
<source>stats.userActiveMonth</source>
@@ -1098,4 +1098,4 @@
</trans-unit>
</body>
</file>
</xliff>
</xliff>

View File

@@ -906,10 +906,6 @@
<source>upload</source>
<target>Enviar</target>
</trans-unit>
<trans-unit id="help.rate">
<source>help.rate</source>
<target></target>
</trans-unit>
<trans-unit id="error.no_comments_found">
<source>error.no_comments_found</source>
<target>Não houve nenhum comentários postados ainda.</target>

View File

@@ -6,34 +6,6 @@
<source>teams.title</source>
<target>الفريق</target>
</trans-unit>
<trans-unit id="teams.project_access">
<source>teams.project_access</source>
<target/>
</trans-unit>
<trans-unit id="teams.customer_access">
<source>teams.customer_access</source>
<target/>
</trans-unit>
<trans-unit id="team.visibility_global">
<source>team.visibility_global</source>
<target/>
</trans-unit>
<trans-unit id="team.visibility_restricted">
<source>team.visibility_restricted</source>
<target/>
</trans-unit>
<trans-unit id="team.project_visibility_inherited">
<source>team.project_visibility_inherited</source>
<target/>
</trans-unit>
<trans-unit id="team.activity_visibility_inherited">
<source>team.activity_visibility_inherited</source>
<target/>
</trans-unit>
<trans-unit id="team.create_default">
<source>team.create_default</source>
<target/>
</trans-unit>
</body>
</file>
</xliff>