PHRAS-3694 bin/maintenance clean:users finish (#4139)

* clean users

* fix help

* add usertype

* relance user connection

* unused option

* test

* send token to connect to phraseanet

* add alpha on help

* bump rc6, add alpha , fix input to integer
Co-authored-by: jygaulier <gaulier@alchemy.fr>
This commit is contained in:
Aina Sitraka
2022-10-06 19:10:15 +03:00
committed by GitHub
parent 9f349e063b
commit e4760b88f2
15 changed files with 362 additions and 170 deletions

View File

@@ -95,6 +95,10 @@ class Authenticator
{ {
$user = $session->getUser(); $user = $session->getUser();
$user->setLastConnection($session->getCreated()); $user->setLastConnection($session->getCreated());
// reset inactivity email when login
$user->setNbInactivityEmail(0);
$user->setLastInactivityEmail(null);
$this->em->persist($user); $this->em->persist($user);
$this->em->flush(); $this->em->flush();

View File

@@ -11,10 +11,17 @@
namespace Alchemy\Phrasea\Command\Maintenance; namespace Alchemy\Phrasea\Command\Maintenance;
use Alchemy\Phrasea\Application\Helper\NotifierAware;
use Alchemy\Phrasea\Command\Command; use Alchemy\Phrasea\Command\Command;
use Alchemy\Phrasea\Core\LazyLocator;
use Alchemy\Phrasea\Model\Entities\User;
use Alchemy\Phrasea\Model\Manipulator\BasketManipulator;
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
use Alchemy\Phrasea\Model\Manipulator\UserManipulator; use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
use Alchemy\Phrasea\Model\Repositories\BasketRepository; use Alchemy\Phrasea\Model\Repositories\BasketRepository;
use Alchemy\Phrasea\Model\Repositories\UserRepository; use Alchemy\Phrasea\Model\Repositories\UserRepository;
use Alchemy\Phrasea\Notification\Mail\MailRequestInactifAccount;
use Alchemy\Phrasea\Notification\Receiver;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -22,49 +29,33 @@ use Symfony\Component\Console\Question\ConfirmationQuestion;
class CleanUsersCommand extends Command class CleanUsersCommand extends Command
{ {
use NotifierAware;
const CLEAR_EMAIL = 8;
const REVOKE = 4;
const DELETE_DATA = 2;
const DELETE_ALL = 1;
static private $mapListToColumn = [
'email' => 'email',
'login' => 'login',
'id' => 'usr_id',
];
public function __construct() public function __construct()
{ {
parent::__construct('clean:users'); parent::__construct('clean:users');
$this $this
->setDescription('Delete "sleepy" users (not connected since a long time)') ->setDescription('ALPHA - Delete "sleepy" users (not connected since a long time)')
// ->addOption('action', null, InputOption::VALUE_REQUIRED|InputOption::VALUE_IS_ARRAY, '"clear_email" ; "revoke" ; "delete_data" ; "delete_all"') ->addOption('inactivity_period', null, InputOption::VALUE_REQUIRED, 'cleanup older than \<inactivity_period> days')
->addOption('older_than', null, InputOption::VALUE_REQUIRED, 'delete older than \<OLDER_THAN>') ->addOption('usertype', null, InputOption::VALUE_REQUIRED, 'specify type of user to clean')
->addOption('dry', null, InputOption::VALUE_NONE, 'dry run, count but don\'t delete') ->addOption('grace_duration', null, InputOption::VALUE_REQUIRED, 'grace period in days after sending email')
->addOption('list', null, InputOption::VALUE_REQUIRED, 'list only, don\'t delete') ->addOption('max_relances', null, InputOption::VALUE_REQUIRED, 'number of email relance')
->addOption('remove_basket', null, InputOption::VALUE_NONE, 'remove basket for user')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'dry run, list result users')
->addOption('show_sql', null, InputOption::VALUE_NONE, 'show sql pre-selecting users') ->addOption('show_sql', null, InputOption::VALUE_NONE, 'show sql pre-selecting users')
->addOption('yes', 'y', InputOption::VALUE_NONE, 'don\'t ask for confirmation') ->addOption('yes', 'y', InputOption::VALUE_NONE, 'don\'t ask for confirmation')
->setHelp( ->setHelp(
"" ""
// . "<info>action=clear-email</info> will set the email to (null)\n" . "\<INACTIVITY_PERIOD> <info>integer to specify the number of inactivity days, value not 0 (zero)</info>\n"
// . "<info>action=revoke</info> will delete all access rights (= make user a \"ghost\")\n" . "\<USERTYPE>specify type of user to clean : \n"
// . "<info>action=delete_data</info> will delete every appbox elements related to the user (rights, baskets, notifications, ...) but preserves dbox logs\n" . "- <info>admin</info> \n"
// . "<info>action=delete_all</info> will delete all db elements, including the dbox logs and the user itself\n" . "- <info>appowner</info> \n"
// . "default = clear_email ; revoke ; delete_data" . "- <info>ghost</info> \n"
// . "\n" . "- <info>basket_owner</info> \n"
. "\<OLDER_THAN> can be absolute or relative from now, e.g.:\n" . "- <info>basket_participant</info> \n"
. "- <info>2022-01-01</info> (please use strict date format, do not add time)\n" . "- <info>story_owner</info> \n"
. "- <info>10 days</info>\n"
. "- <info>2 weeks</info>\n"
. "- <info>6 months</info>\n"
. "- <info>1 year</info>\n"
. "\<LIST> sepcifies the user column to be listed, set one of:\n"
. "- <info>id</info>\n"
. "- <info>login</info>\n"
. "- <info>email</info>"
); );
} }
@@ -74,71 +65,76 @@ class CleanUsersCommand extends Command
$dry = false; $dry = false;
$show_sql = false; $show_sql = false;
$yes = false; $yes = false;
$this->setDelivererLocator(new LazyLocator($this->container, 'notification.deliverer'));
// sanity check options $cnx = $this->container->getApplicationBox()->get_connection();
//
// --action (multiple values allowed) $inactivityPeriod = $input->getOption('inactivity_period');
if (!preg_match("/^\d+$/", $inactivityPeriod)) {
$output->writeln("<error>invalid value form '--inactivity_period' option</error>(see possible value with --help)");
/*
$action = 0; // actions requested, as bitfield
$actions = [
'CLEAR_EMAIL' => self::CLEAR_EMAIL,
'REVOKE' => self::REVOKE,
'DELETE_DATA' => self::DELETE_DATA,
'DELETE_ALL' => self::DELETE_ALL
];
if(empty($action_parm = $input->getOption('action'))) {
$action_parm = ['clear_email', 'revoke', 'delete_data'];
}
foreach($action_parm as $a) {
$a = strtoupper($a);
if(!array_key_exists($a, $actions)) {
$output->writeln(sprintf("<error>Invalid value \"%s\" for --action option.</error>", $a));
return 1; return 1;
} }
$action |= $action[$a];
}
if($action & self::DELETE_ALL && $action !== self::DELETE_ALL) {
$output->writeln(sprintf("<error>Action \"delete_all\" cannot be mixed with other action.</error>"));
return 1;
}
*/
// --older_than $graceDuration = $input->getOption('grace_duration');
if (!preg_match("/^\d+$/", $graceDuration)) {
$output->writeln("<error>invalid value form '--grace_duration' option</error>(see possible value with --help)");
$older_than = str_replace(['-', '/', ' '], '-', $input->getOption('older_than'));
if($older_than === "") {
$output->writeln("<error>set '--older_than' option.</error>");
return 1; return 1;
} }
$matches = [];
preg_match("/(\d{4}-\d{2}-\d{2})|(\d+)-(day|week|month|year)s?/i", $older_than, $matches); $maxRelances = $input->getOption('max_relances');
$n = count($matches);
if($n === 2) { if (!preg_match("/^\d+$/", $maxRelances)) {
// yyyy-mm-dd $output->writeln("<error>invalid value form '--max_relances' option</error>(see possible value with --help)");
$clauses[] = "`last_connection` < " . $matches[1];
}
elseif($n === 4 && empty($matches[1])) {
// 1-day ; 2-weeks ; ...
$expr = (int)$matches[2];
$unit = strtoupper($matches[3]);
$clauses[] = sprintf("`last_connection` < DATE_SUB(NOW(), INTERVAL %d %s)", $expr, $unit);
}
else {
$output->writeln("<error>invalid value form '--older_than' option.</error> (see possible values with --help)");
return 1; return 1;
} }
$clauses[] = sprintf("`last_connection` < DATE_SUB(NOW(), INTERVAL %d day)", $inactivityPeriod);
$sql_where_u = 1;
$sql_where_ub = 1;
if ($input->getOption('usertype') == 'admin') {
$clauses[] = "`admin`=1";
} else {
$clauses[] = "`admin`=0"; // dont delete super admins $clauses[] = "`admin`=0"; // dont delete super admins
}
if ($input->getOption('usertype') == 'appowner') {
$clauses[] = "`ApiAccounts`.`id` IS NOT NULL";
} else {
$clauses[] = "ISNULL(`ApiAccounts`.`id`)";
}
if ($input->getOption('usertype') == 'ghost') {
$sql_where_u = "`u`.`bids` IS NULL";
$sql_where_ub = "`ub`.`sbids` IS NULL";
}
if ($input->getOption('usertype') == 'basket_owner') {
$clauses[] = "`Baskets`.`id` IS NOT NULL";
}
if ($input->getOption('usertype') == 'basket_participant') {
$clauses[] = "`BasketParticipants`.`id` IS NOT NULL";
$clauses[] = "`B`.`user_id` != `BasketParticipants`.`user_id`";
}
if ($input->getOption('usertype') == 'story_owner') {
$clauses[] = "`StoryWZ`.`id` IS NOT NULL";
}
$clauses[] = "`deleted`=0"; // dont delete twice $clauses[] = "`deleted`=0"; // dont delete twice
$clauses[] = "ISNULL(`model_of`)"; // dont delete models $clauses[] = "ISNULL(`model_of`)"; // dont delete models
$clauses[] = "`login`!='autoregister'"; // dont delete "autoregister" $clauses[] = "`login`!='autoregister'"; // dont delete "autoregister"
$clauses[] = "`login`!='guest'"; // dont delete "guest" $clauses[] = "`login`!='guest'"; // dont delete "guest"
$clauses[] = "ISNULL(`ApiAccounts`.`id`)"; // dont delete api service accounts
// --dry
if($input->getOption('dry')) { if ($input->getOption('dry-run')) {
$dry = true; $dry = true;
} }
@@ -150,32 +146,8 @@ class CleanUsersCommand extends Command
$yes = true; $yes = true;
} }
if(!is_null($list = $input->getOption('list'))) {
if(!array_key_exists($list, self::$mapListToColumn)) {
$output->writeln(sprintf("<error>bad \"list\" value '%s'</error> (see possible values with --help)", $list));
return 1;
}
}
// do the job
//
$sql_where = join(") AND (", $clauses); $sql_where = join(") AND (", $clauses);
$cnx = $this->container->getApplicationBox()->get_connection();
$sql_count = "SELECT COUNT(`Users`.`id`) AS n FROM (`Users` LEFT JOIN `ApiAccounts` ON `ApiAccounts`.`user_id`=`Users`.`id`) WHERE (" . $sql_where . ")";
if($show_sql) {
$output->writeln(sprintf("sql: \"<info>%s</info>\"", $sql_count));
}
$stmt = $cnx->prepare($sql_count);
$stmt->execute();
$n = $stmt->fetchColumn(0);
$stmt->closeCursor();
if(!$list) {
$output->writeln(sprintf("Acting on %s users.", $n));
}
/** @var UserManipulator $userManipulator */ /** @var UserManipulator $userManipulator */
$userManipulator = $this->container['manipulator.user']; $userManipulator = $this->container['manipulator.user'];
/** @var UserRepository $userRepository */ /** @var UserRepository $userRepository */
@@ -183,90 +155,133 @@ class CleanUsersCommand extends Command
/** @var BasketRepository $basketRepository */ /** @var BasketRepository $basketRepository */
$basketRepository = $this->container['repo.baskets']; $basketRepository = $this->container['repo.baskets'];
$sql_list = "SELECT u.*, GROUP_CONCAT(`basusr`.`base_id` SEPARATOR ',') AS `bids`\n" $sql_list = "SELECT * FROM \n"
. "(SELECT ub.*, GROUP_CONCAT(`basusr`.`base_id` SEPARATOR ',') AS `bids`\n"
. "FROM\n" . "FROM\n"
. "( SELECT `Users`.`id` AS `usr_id`, `Users`.`login`, `Users`.`email`, `Users`.`last_connection`, GROUP_CONCAT(`sbasusr`.`sbas_id` SEPARATOR ',') AS `sbids`\n" . "( SELECT `Users`.`id` AS `usr_id`, `Users`.`login`, `Users`.`email`, `Users`.`last_connection`, GROUP_CONCAT(`sbasusr`.`sbas_id` SEPARATOR ',') AS `sbids`\n"
. " FROM (`Users` LEFT JOIN `ApiAccounts` ON `ApiAccounts`.`user_id` = `Users`.`id`) \n" . " FROM (`Users` LEFT JOIN `ApiAccounts` ON `ApiAccounts`.`user_id` = `Users`.`id`) \n"
. " LEFT JOIN `sbasusr` ON `sbasusr`.`usr_id` = `Users`.`id`\n" . " LEFT JOIN `sbasusr` ON `sbasusr`.`usr_id` = `Users`.`id`\n"
. " LEFT JOIN Baskets ON Baskets.user_id = `Users`.`id`\n"
. " LEFT JOIN BasketParticipants ON BasketParticipants.user_id = `Users`.`id`\n"
. " LEFT JOIN Baskets as B ON B.id = BasketParticipants.basket_id \n"
. " LEFT JOIN StoryWZ ON StoryWZ.user_id = `Users`.`id`\n"
. " WHERE (" . $sql_where . ")" . " WHERE (" . $sql_where . ")"
. " GROUP BY `sbasusr`.`usr_id`\n" . " GROUP BY `Users`.`id`\n"
. ") AS u\n" . ") AS ub\n"
. "LEFT JOIN `basusr` ON `basusr`.`usr_id` = `u`.`usr_id` GROUP BY `basusr`.`usr_id`"; . "LEFT JOIN `basusr` ON `basusr`.`usr_id` = `ub`.`usr_id`"
. " WHERE " . $sql_where_ub ."\n"
. " GROUP BY `ub`.`usr_id`) AS u\n"
. " WHERE ". $sql_where_u ;
if ($show_sql) { if ($show_sql) {
$output->writeln(sprintf("sql: \"<info>%s</info>\"", $sql_list)); $output->writeln(sprintf("sql: \"<info>%s</info>\"", $sql_list));
} }
if(!$yes && !$list) { $stmt = $cnx->prepare($sql_list);
$stmt->execute();
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
if (!$yes && !$dry) {
$helper = $this->getHelper('question'); $helper = $this->getHelper('question');
$question = new ConfirmationQuestion(sprintf("Confirm deletion of %s user(s) [y/n] : ", $n), false); $question = new ConfirmationQuestion(sprintf("Confirm cleanup for %s user(s) [y/n] : ", count($rows)), false);
if (!$helper->ask($input, $output, $question)) { if (!$helper->ask($input, $output, $question)) {
return 0; return 0;
} }
} }
$stmt = $cnx->prepare($sql_list); $usersList = [];
$stmt->execute(); $nbUserRelanced = 0;
while( $row = ($stmt->fetch(\PDO::FETCH_ASSOC)) ) { $nbUserDeleted = 0;
foreach ( $rows as $row ) {
if( !is_null($user = $userRepository->find($row['usr_id'])) ) { if( !is_null($user = $userRepository->find($row['usr_id'])) ) {
$lastInactivityEmail = $user->getLastInactivityEmail();
$nbRelance = $user->getNbInactivityEmail();
$nowDate = new \DateTime();
if ($list) { $interval = sprintf('P%dD', $graceDuration);
$s = $row[self::$mapListToColumn[$list]];
$output->write(sprintf("%s%s", $s, "\n"));
}
else {
$output->write(sprintf("%s : %s / %s (%s)", $row['usr_id'], $row['login'], $row['email'], $row['last_connection']));
$nowDate->sub(new \DateInterval($interval));
$action = "in grace period";
if (empty($lastInactivityEmail) || $lastInactivityEmail < $nowDate) {
// first, relance the user by email to have a grace period
if ($nbRelance < $maxRelances) {
if (!$dry) { if (!$dry) {
$acl = $this->container->getAclForUser($user); $this->relanceUser($user, $graceDuration);
$user->setNbInactivityEmail($nbRelance+1);
// revoke bas rights $user->setLastInactivityEmail(new \DateTime());
if (!is_null($row['bids'])) { $userManipulator->updateUser($user);
$bids = array_map(function ($bid) { }
return (int)$bid; $action = sprintf("max_relances=%d , found %d times relanced (will be relance if not --dry-run)", $maxRelances, $nbRelance);
}, explode(',', $row['bids'])); $nbUserRelanced++;
$acl->revoke_access_from_bases($bids); } else {
if (!$dry) {
if ($input->getOption('remove_basket')) {
$baskets = $basketRepository->findBy(['user' => $user]);
$this->getBasketManipulator()->removeBaskets($baskets);
} }
// revoke sbas rights
$acl->revoke_unused_sbas_rights();
// delete user // delete user
$userManipulator->delete($user); $userManipulator->delete($user);
$output->write(sprintf("%s : %s / %s (%s)", $row['usr_id'], $row['login'], $row['email'], $row['last_connection']));
$output->writeln(" deleted."); $output->writeln(" deleted.");
} }
else { $action = sprintf("max_relances=%d , found %d times relanced (will be deleted if not --dry-run)", $maxRelances, $nbRelance);
$output->writeln(" not deleted (dry mode)."); $nbUserDeleted++;
} }
} }
// else we are in grace period, nothing to do
$usersList[] = [
$user->getId(),
$user->getLogin(),
$user->getLastConnection()->format('Y-m-d h:m:s'),
$action
];
} }
} }
$stmt->closeCursor(); $stmt->closeCursor();
if ($dry) {
/* $output->writeln(sprintf("dry-run , %d users included in the given inactivity_period", count($rows)));
// clear email $userTable = $this->getHelperSet()->get('table');
$headers = ['id', 'login', 'last_connection', 'action'];
if($action & self::CLEAR_EMAIL) { $userTable
$sql = "UPDATE `Users` SET `email`=NULL WHERE (" . $sql_where . ")"; ->setHeaders($headers)
if($show_sql) { ->setRows($usersList)
$output->writeln(sprintf("sql: \"<info>%s</info>\"", $sql)); ->render($output);
} else {
$output->writeln(sprintf("%d users relanced , %d in grace period, %d users deleted", $nbUserRelanced, (count($rows)-$nbUserDeleted-$nbUserRelanced), $nbUserDeleted));
} }
if(!$dry) {
$cnx->exec($sql);
}
}
// revoke rights
if($action & self::REVOKE) {
$sql = "DELETE "
}
*/
return 0; return 0;
} }
private function relanceUser(User $user, $graceDuration)
{
/** @var TokenManipulator $tokenManipulator */
$tokenManipulator = $this->container['manipulator.token'];
$token = $tokenManipulator->create($user, TokenManipulator::TYPE_USER_RELANCE, new \DateTime("+{$graceDuration} day"));
$receiver = Receiver::fromUser($user);
$mail = MailRequestInactifAccount::create($this->container, $receiver);
$servername = $this->container['conf']->get('servername');
$mail->setButtonUrl('http://'.$servername.'/prod/?LOG='.$token->getValue());
$mail->setExpiration($token->getExpiration());
$this->deliver($mail);
}
/**
* @return BasketManipulator
*/
private function getBasketManipulator()
{
return $this->container['manipulator.basket'];
}
} }

View File

@@ -14,10 +14,12 @@ namespace Alchemy\Phrasea\ControllerProvider\Prod;
use Alchemy\Phrasea\Application as PhraseaApplication; use Alchemy\Phrasea\Application as PhraseaApplication;
use Alchemy\Phrasea\Controller\Prod\RootController; use Alchemy\Phrasea\Controller\Prod\RootController;
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait; use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
use Alchemy\Phrasea\Helper; use Alchemy\Phrasea\Model\Entities\Token;
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
use Silex\Application; use Silex\Application;
use Silex\ControllerProviderInterface; use Silex\ControllerProviderInterface;
use Silex\ServiceProviderInterface; use Silex\ServiceProviderInterface;
use Symfony\Component\HttpFoundation\Request;
class Root implements ControllerProviderInterface, ServiceProviderInterface class Root implements ControllerProviderInterface, ServiceProviderInterface
{ {
@@ -40,7 +42,7 @@ class Root implements ControllerProviderInterface, ServiceProviderInterface
public function connect(Application $app) public function connect(Application $app)
{ {
$controllers = $this->createCollection($app); $controllers = $this->createCollection($app);
$controllers->before([$this, 'redirectOnLogRequests']);
$controllers->before('controller.prod:assertAuthenticated'); $controllers->before('controller.prod:assertAuthenticated');
$controllers->get('/', 'controller.prod:indexAction') $controllers->get('/', 'controller.prod:indexAction')
@@ -48,4 +50,31 @@ class Root implements ControllerProviderInterface, ServiceProviderInterface
return $controllers; return $controllers;
} }
public function redirectOnLogRequests(Request $request, PhraseaApplication $app)
{
if (!$request->query->has('LOG')) {
return null;
}
if ($app->getAuthenticator()->isAuthenticated()) {
$app->getAuthenticator()->closeAccount();
}
/** @var Token $token */
$token = $app['repo.tokens']->findValidToken($request->query->get('LOG'));
// actually just type user-relance can access here with token
// PHRAS-3694
if (null === $token || $token->getType() != TokenManipulator::TYPE_USER_RELANCE) {
$app->addFlash('error', $app->trans('The URL you used is out of date, please login'));
return $app->redirectPath('homepage');
}
/** @var Token $token */
$app->getAuthenticator()->openAccount($token->getUser());
return $app->redirectPath('prod');
}
} }

View File

@@ -17,7 +17,7 @@ class Version
* @var string * @var string
*/ */
private $number = '4.1.6-rc5'; private $number = '4.1.6-rc6';
/** /**
* @var string * @var string

View File

@@ -266,6 +266,16 @@ class User
*/ */
private $grantedApi = false; private $grantedApi = false;
/**
* @ORM\Column(type="integer", name="nb_inactivity_email", options={"default" = 0})
*/
private $nbInactivityEmail = 0;
/**
* @ORM\Column(type="datetime", name="last_inactivity_email", nullable=true)
*/
private $lastInactivityEmail;
/** /**
* Constructor * Constructor
*/ */
@@ -1078,6 +1088,36 @@ class User
return $this; return $this;
} }
public function setNbInactivityEmail($nbEnactivityEmail)
{
$this->nbInactivityEmail = $nbEnactivityEmail;
}
public function getNbInactivityEmail()
{
return $this->nbInactivityEmail;
}
/**
* @param \DateTime|null $lastInactivityEmail
*
* @return $this
*/
public function setLastInactivityEmail($lastInactivityEmail)
{
$this->lastInactivityEmail = $lastInactivityEmail;
return $this;
}
/**
* @return \DateTime|null
*/
public function getLastInactivityEmail()
{
return $this->lastInactivityEmail;
}
/** /**
* @return boolean * @return boolean
*/ */

View File

@@ -36,6 +36,7 @@ class TokenManipulator implements ManipulatorInterface
const TYPE_VIEW = 'view'; const TYPE_VIEW = 'view';
const TYPE_VALIDATE = 'validate'; const TYPE_VALIDATE = 'validate';
const TYPE_RSS = 'rss'; const TYPE_RSS = 'rss';
const TYPE_USER_RELANCE = 'user-relance';
/** @var Objectmanager */ /** @var Objectmanager */
private $om; private $om;

View File

@@ -0,0 +1,39 @@
<?php
namespace Alchemy\Phrasea\Notification\Mail;
class MailRequestInactifAccount extends AbstractMailWithLink
{
/**
* @inheritDoc
*/
public function getSubject()
{
return $this->app->trans("mail:: inactif account");
}
/**
* @inheritDoc
*/
public function getMessage()
{
return $this->app->trans("mail:: your account is inactif and to be deleted!");
}
/**
* @inheritDoc
*/
public function getButtonText()
{
return $this->app->trans("mail:: connect to phraseanet");
}
/**
* @inheritDoc
*/
public function getButtonURL()
{
return $this->url;
}
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2022-10-05T11:50:19Z" source-language="en" target-language="de" datatype="plaintext" original="not.available"> <file date="2022-10-06T07:54:20Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
<header> <header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/> <tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note> <note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
@@ -6613,6 +6613,7 @@
<trans-unit id="2558cc2c887bbe4e2444ec6ef83b4982386e871a" resname="The URL you used is out of date, please login" approved="yes"> <trans-unit id="2558cc2c887bbe4e2444ec6ef83b4982386e871a" resname="The URL you used is out of date, please login" approved="yes">
<source>The URL you used is out of date, please login</source> <source>The URL you used is out of date, please login</source>
<target state="translated">Die URL, die Sie benutzt haben, ist nicht mehr gültig. Bitte loggen Sie sich ein</target> <target state="translated">Die URL, die Sie benutzt haben, ist nicht mehr gültig. Bitte loggen Sie sich ein</target>
<jms:reference-file line="70">ControllerProvider/Prod/Root.php</jms:reference-file>
<jms:reference-file line="133">Phrasea/ControllerProvider/Lightbox.php</jms:reference-file> <jms:reference-file line="133">Phrasea/ControllerProvider/Lightbox.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="45a947887469ff8c2aec684433450dad352130ed" resname="The Youtube servers have received too many calls from the same caller in a short amount of time." approved="yes"> <trans-unit id="45a947887469ff8c2aec684433450dad352130ed" resname="The Youtube servers have received too many calls from the same caller in a short amount of time." approved="yes">
@@ -11509,11 +11510,26 @@
<target state="translated">Mai</target> <target state="translated">Mai</target>
<jms:reference-file line="718">classes/module/report.php</jms:reference-file> <jms:reference-file line="718">classes/module/report.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="e1b209a684084fff65dc7751a56b68d13683ad38" resname="mail:: connect to phraseanet">
<source>mail:: connect to phraseanet</source>
<target state="new">mail:: connect to phraseanet</target>
<jms:reference-file line="29">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="f8798f45953d19a36e7a4cfafd17b56ba32c8b58" resname="mail:: inactif account">
<source>mail:: inactif account</source>
<target state="new">mail:: inactif account</target>
<jms:reference-file line="13">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="c1cd96a63c0756a0cdfdf6ef5c3d167b04e3d92f" resname="mail:: validation: Vote will expire on %expire%"> <trans-unit id="c1cd96a63c0756a0cdfdf6ef5c3d167b04e3d92f" resname="mail:: validation: Vote will expire on %expire%">
<source>mail:: validation: Vote will expire on %expire%</source> <source>mail:: validation: Vote will expire on %expire%</source>
<target state="translated">Das Feedback läuft am ab %expire%</target> <target state="translated">Das Feedback läuft am ab %expire%</target>
<jms:reference-file line="108">Notification/Mail/MailInfoValidationRequest.php</jms:reference-file> <jms:reference-file line="108">Notification/Mail/MailInfoValidationRequest.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="9c627983e8b23c12caf1415fd0e7b49c4712c219" resname="mail:: your account is inactif and to be deleted!">
<source>mail:: your account is inactif and to be deleted!</source>
<target state="new">mail:: your account is inactif and to be deleted!</target>
<jms:reference-file line="21">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="b36bafaf28ce6a4b603bc5169e4459c854e83569" resname="mail::share Open with Lightbox"> <trans-unit id="b36bafaf28ce6a4b603bc5169e4459c854e83569" resname="mail::share Open with Lightbox">
<source>mail::share Open with Lightbox</source> <source>mail::share Open with Lightbox</source>
<target state="translated">Mit Lightbox öffnen</target> <target state="translated">Mit Lightbox öffnen</target>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2022-10-05T11:50:35Z" source-language="en" target-language="en" datatype="plaintext" original="not.available"> <file date="2022-10-06T07:54:36Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
<header> <header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/> <tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note> <note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
@@ -6616,6 +6616,7 @@
<trans-unit id="2558cc2c887bbe4e2444ec6ef83b4982386e871a" resname="The URL you used is out of date, please login" approved="yes"> <trans-unit id="2558cc2c887bbe4e2444ec6ef83b4982386e871a" resname="The URL you used is out of date, please login" approved="yes">
<source>The URL you used is out of date, please login</source> <source>The URL you used is out of date, please login</source>
<target state="translated">The URL you used is out of date. Please login.</target> <target state="translated">The URL you used is out of date. Please login.</target>
<jms:reference-file line="70">ControllerProvider/Prod/Root.php</jms:reference-file>
<jms:reference-file line="133">Phrasea/ControllerProvider/Lightbox.php</jms:reference-file> <jms:reference-file line="133">Phrasea/ControllerProvider/Lightbox.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="45a947887469ff8c2aec684433450dad352130ed" resname="The Youtube servers have received too many calls from the same caller in a short amount of time." approved="yes"> <trans-unit id="45a947887469ff8c2aec684433450dad352130ed" resname="The Youtube servers have received too many calls from the same caller in a short amount of time." approved="yes">
@@ -11512,11 +11513,26 @@
<target state="translated">May</target> <target state="translated">May</target>
<jms:reference-file line="718">classes/module/report.php</jms:reference-file> <jms:reference-file line="718">classes/module/report.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="e1b209a684084fff65dc7751a56b68d13683ad38" resname="mail:: connect to phraseanet">
<source>mail:: connect to phraseanet</source>
<target state="new">mail:: connect to phraseanet</target>
<jms:reference-file line="29">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="f8798f45953d19a36e7a4cfafd17b56ba32c8b58" resname="mail:: inactif account">
<source>mail:: inactif account</source>
<target state="new">mail:: inactif account</target>
<jms:reference-file line="13">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="c1cd96a63c0756a0cdfdf6ef5c3d167b04e3d92f" resname="mail:: validation: Vote will expire on %expire%"> <trans-unit id="c1cd96a63c0756a0cdfdf6ef5c3d167b04e3d92f" resname="mail:: validation: Vote will expire on %expire%">
<source>mail:: validation: Vote will expire on %expire%</source> <source>mail:: validation: Vote will expire on %expire%</source>
<target state="translated">Feedback session expires on %expire%</target> <target state="translated">Feedback session expires on %expire%</target>
<jms:reference-file line="108">Notification/Mail/MailInfoValidationRequest.php</jms:reference-file> <jms:reference-file line="108">Notification/Mail/MailInfoValidationRequest.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="9c627983e8b23c12caf1415fd0e7b49c4712c219" resname="mail:: your account is inactif and to be deleted!">
<source>mail:: your account is inactif and to be deleted!</source>
<target state="new">mail:: your account is inactif and to be deleted!</target>
<jms:reference-file line="21">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="b36bafaf28ce6a4b603bc5169e4459c854e83569" resname="mail::share Open with Lightbox"> <trans-unit id="b36bafaf28ce6a4b603bc5169e4459c854e83569" resname="mail::share Open with Lightbox">
<source>mail::share Open with Lightbox</source> <source>mail::share Open with Lightbox</source>
<target state="translated">Open with Lightbox</target> <target state="translated">Open with Lightbox</target>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2022-10-05T11:50:53Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available"> <file date="2022-10-06T07:54:55Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
<header> <header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/> <tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note> <note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
@@ -6613,6 +6613,7 @@
<trans-unit id="2558cc2c887bbe4e2444ec6ef83b4982386e871a" resname="The URL you used is out of date, please login" approved="yes"> <trans-unit id="2558cc2c887bbe4e2444ec6ef83b4982386e871a" resname="The URL you used is out of date, please login" approved="yes">
<source>The URL you used is out of date, please login</source> <source>The URL you used is out of date, please login</source>
<target state="translated">L'URL utilisée est périmé. Veuillez vous identifier.</target> <target state="translated">L'URL utilisée est périmé. Veuillez vous identifier.</target>
<jms:reference-file line="70">ControllerProvider/Prod/Root.php</jms:reference-file>
<jms:reference-file line="133">Phrasea/ControllerProvider/Lightbox.php</jms:reference-file> <jms:reference-file line="133">Phrasea/ControllerProvider/Lightbox.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="45a947887469ff8c2aec684433450dad352130ed" resname="The Youtube servers have received too many calls from the same caller in a short amount of time." approved="yes"> <trans-unit id="45a947887469ff8c2aec684433450dad352130ed" resname="The Youtube servers have received too many calls from the same caller in a short amount of time." approved="yes">
@@ -11510,11 +11511,26 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le
<target state="translated">mai</target> <target state="translated">mai</target>
<jms:reference-file line="718">classes/module/report.php</jms:reference-file> <jms:reference-file line="718">classes/module/report.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="e1b209a684084fff65dc7751a56b68d13683ad38" resname="mail:: connect to phraseanet">
<source>mail:: connect to phraseanet</source>
<target state="new">mail:: connect to phraseanet</target>
<jms:reference-file line="29">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="f8798f45953d19a36e7a4cfafd17b56ba32c8b58" resname="mail:: inactif account">
<source>mail:: inactif account</source>
<target state="new">mail:: inactif account</target>
<jms:reference-file line="13">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="c1cd96a63c0756a0cdfdf6ef5c3d167b04e3d92f" resname="mail:: validation: Vote will expire on %expire%"> <trans-unit id="c1cd96a63c0756a0cdfdf6ef5c3d167b04e3d92f" resname="mail:: validation: Vote will expire on %expire%">
<source>mail:: validation: Vote will expire on %expire%</source> <source>mail:: validation: Vote will expire on %expire%</source>
<target state="translated">La validation expire le %expire%</target> <target state="translated">La validation expire le %expire%</target>
<jms:reference-file line="108">Notification/Mail/MailInfoValidationRequest.php</jms:reference-file> <jms:reference-file line="108">Notification/Mail/MailInfoValidationRequest.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="9c627983e8b23c12caf1415fd0e7b49c4712c219" resname="mail:: your account is inactif and to be deleted!">
<source>mail:: your account is inactif and to be deleted!</source>
<target state="new">mail:: your account is inactif and to be deleted!</target>
<jms:reference-file line="21">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="b36bafaf28ce6a4b603bc5169e4459c854e83569" resname="mail::share Open with Lightbox"> <trans-unit id="b36bafaf28ce6a4b603bc5169e4459c854e83569" resname="mail::share Open with Lightbox">
<source>mail::share Open with Lightbox</source> <source>mail::share Open with Lightbox</source>
<target state="translated">Ouvrir avec Lightbox</target> <target state="translated">Ouvrir avec Lightbox</target>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2022-10-05T11:51:14Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available"> <file date="2022-10-06T07:55:16Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
<header> <header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/> <tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note> <note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>
@@ -6619,6 +6619,7 @@
<trans-unit id="2558cc2c887bbe4e2444ec6ef83b4982386e871a" resname="The URL you used is out of date, please login" approved="yes"> <trans-unit id="2558cc2c887bbe4e2444ec6ef83b4982386e871a" resname="The URL you used is out of date, please login" approved="yes">
<source>The URL you used is out of date, please login</source> <source>The URL you used is out of date, please login</source>
<target state="translated">De gebruikte URL is niet meer geldig, gelieve u aan te melden</target> <target state="translated">De gebruikte URL is niet meer geldig, gelieve u aan te melden</target>
<jms:reference-file line="70">ControllerProvider/Prod/Root.php</jms:reference-file>
<jms:reference-file line="133">Phrasea/ControllerProvider/Lightbox.php</jms:reference-file> <jms:reference-file line="133">Phrasea/ControllerProvider/Lightbox.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="45a947887469ff8c2aec684433450dad352130ed" resname="The Youtube servers have received too many calls from the same caller in a short amount of time." approved="yes"> <trans-unit id="45a947887469ff8c2aec684433450dad352130ed" resname="The Youtube servers have received too many calls from the same caller in a short amount of time." approved="yes">
@@ -11515,11 +11516,26 @@
<target state="translated">mei</target> <target state="translated">mei</target>
<jms:reference-file line="718">classes/module/report.php</jms:reference-file> <jms:reference-file line="718">classes/module/report.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="e1b209a684084fff65dc7751a56b68d13683ad38" resname="mail:: connect to phraseanet">
<source>mail:: connect to phraseanet</source>
<target state="new">mail:: connect to phraseanet</target>
<jms:reference-file line="29">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="f8798f45953d19a36e7a4cfafd17b56ba32c8b58" resname="mail:: inactif account">
<source>mail:: inactif account</source>
<target state="new">mail:: inactif account</target>
<jms:reference-file line="13">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="c1cd96a63c0756a0cdfdf6ef5c3d167b04e3d92f" resname="mail:: validation: Vote will expire on %expire%"> <trans-unit id="c1cd96a63c0756a0cdfdf6ef5c3d167b04e3d92f" resname="mail:: validation: Vote will expire on %expire%">
<source>mail:: validation: Vote will expire on %expire%</source> <source>mail:: validation: Vote will expire on %expire%</source>
<target state="new">mail:: validation: Vote will expire on %expire%</target> <target state="new">mail:: validation: Vote will expire on %expire%</target>
<jms:reference-file line="108">Notification/Mail/MailInfoValidationRequest.php</jms:reference-file> <jms:reference-file line="108">Notification/Mail/MailInfoValidationRequest.php</jms:reference-file>
</trans-unit> </trans-unit>
<trans-unit id="9c627983e8b23c12caf1415fd0e7b49c4712c219" resname="mail:: your account is inactif and to be deleted!">
<source>mail:: your account is inactif and to be deleted!</source>
<target state="new">mail:: your account is inactif and to be deleted!</target>
<jms:reference-file line="21">Notification/Mail/MailRequestInactifAccount.php</jms:reference-file>
</trans-unit>
<trans-unit id="b36bafaf28ce6a4b603bc5169e4459c854e83569" resname="mail::share Open with Lightbox"> <trans-unit id="b36bafaf28ce6a4b603bc5169e4459c854e83569" resname="mail::share Open with Lightbox">
<source>mail::share Open with Lightbox</source> <source>mail::share Open with Lightbox</source>
<target state="new">mail::share Open with Lightbox</target> <target state="new">mail::share Open with Lightbox</target>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2022-10-05T11:50:19Z" source-language="en" target-language="de" datatype="plaintext" original="not.available"> <file date="2022-10-06T07:54:20Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
<header> <header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/> <tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note> <note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2022-10-05T11:50:35Z" source-language="en" target-language="en" datatype="plaintext" original="not.available"> <file date="2022-10-06T07:54:36Z" source-language="en" target-language="en" datatype="plaintext" original="not.available">
<header> <header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/> <tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note> <note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2022-10-05T11:50:53Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available"> <file date="2022-10-06T07:54:55Z" source-language="en" target-language="fr" datatype="plaintext" original="not.available">
<header> <header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/> <tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note> <note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2"> <xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:jms="urn:jms:translation" version="1.2">
<file date="2022-10-05T11:51:14Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available"> <file date="2022-10-06T07:55:16Z" source-language="en" target-language="nl" datatype="plaintext" original="not.available">
<header> <header>
<tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/> <tool tool-id="JMSTranslationBundle" tool-name="JMSTranslationBundle" tool-version="1.1.0-DEV"/>
<note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note> <note>The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message.</note>