From a79b72fbaf7a23de360b3c92734117e3990eb86c Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Fri, 24 Nov 2017 16:22:31 +0400 Subject: [PATCH 1/2] Port PHRAS-1593 --- .bowerrc | 3 +- .../Controller/Prod/ShareController.php | 85 +++++---- .../Phrasea/ControllerProvider/Prod/Share.php | 20 ++- templates/web/prod/Share/record.html.twig | 163 ++++++++++++------ .../Phrasea/Controller/Prod/ShareTest.php | 108 +++++------- 5 files changed, 230 insertions(+), 149 deletions(-) diff --git a/.bowerrc b/.bowerrc index 764e156e8a..bb6d6aafdb 100644 --- a/.bowerrc +++ b/.bowerrc @@ -1,3 +1,4 @@ { - "directory" : "www/bower_components" + "directory" : "www/bower_components", + "timeout": 1200000 } diff --git a/lib/Alchemy/Phrasea/Controller/Prod/ShareController.php b/lib/Alchemy/Phrasea/Controller/Prod/ShareController.php index 85df3351cf..04b0f00612 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/ShareController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/ShareController.php @@ -23,44 +23,71 @@ class ShareController extends Controller */ public function shareRecord($base_id, $record_id) { - $outputVars = [ - 'isAvailable' => false, - 'preview' => [ - 'permalinkUrl' => '', - 'permaviewUrl' => '', - 'embedUrl' => '', - 'width' => '', - 'height' => '' - ] - ]; $record = new \record_adapter($this->app, \phrasea::sbasFromBas($this->app, $base_id), $record_id); - if (!$this->getAclForUser()->has_access_to_subdef($record, 'preview')) { - $this->app->abort(403); - } + //get list of subdefs + $subdefs = $record->get_subdefs(); - $preview = $record->get_preview(); + $databoxSubdefs = $record->getDatabox()->get_subdef_structure()->getSubdefGroup($record->getType()); + $acl = $this->getAclForUser(); + $subdefList = []; + $defaultKey = null; + foreach ($subdefs as $subdef) { + $subdefName = $subdef->get_name(); + if ($subdefName == 'document') { + if (!$acl->has_right_on_base($record->getBaseId(), \ACL::CANDWNLDHD)) { + continue; + } + $label = $this->app->trans('prod::tools: document'); + } + elseif ($databoxSubdefs->hasSubdef($subdefName)) { + if (!$acl->has_access_to_subdef($record, $subdefName)) { + continue; + } + $label = $databoxSubdefs->getSubdef($subdefName)->get_label($this->app['locale']); + } + else { + // this subdef does no exists anymore in databox structure ? + continue; // don't publish it + } + $value = $subdef->get_name(); + $preview = $record->get_subdef($value); + $defaultKey = $value; // will set a default option if neither preview,thumbnail or document is present - if (null !== $previewLink = $preview->get_permalink()) { - $permalinkUrl = $previewLink->get_url(); - $permaviewUrl = $previewLink->get_page(); - $previewWidth = $preview->get_width(); - $previewHeight = $preview->get_height(); - $embedUrl = $this->app->url('alchemy_embed_view', ['url' => (string)$permalinkUrl]); - - $outputVars = [ - 'isAvailable' => true, - 'preview' => [ + if ( ($previewLink = $preview->get_permalink()) !== null ) { + $permalinkUrl = $previewLink->get_url()->__toString(); + $permaviewUrl = $previewLink->get_page(); + $previewWidth = $preview->get_width(); + $previewHeight = $preview->get_height(); + $embedUrl = $this->app->url('alchemy_embed_view', ['url' => (string)$permalinkUrl]); + $previewData = [ + 'label' => $label, 'permalinkUrl' => $permalinkUrl, 'permaviewUrl' => $permaviewUrl, - 'embedUrl' => $embedUrl, - 'width' => $previewWidth, - 'height' => $previewHeight - ] - ]; + 'embedUrl' => $embedUrl, + 'width' => $previewWidth, + 'height' => $previewHeight + ]; + $subdefList[$value] = $previewData; + } } + // candidates as best default selected option + foreach(["preview", "thumbnail", "document"] as $k) { + if (array_key_exists($k, $subdefList)) { + $defaultKey = $k; + break; + } + } + // if no subdef was sharable, subdefList is empty and defaultKey is null + // the twig MUST handle that + $outputVars = [ + 'isAvailable' => !empty($subdefList), + 'subdefList' => $subdefList, + 'defaultKey' => $defaultKey + ]; + return $this->renderResponse('prod/Share/record.html.twig', $outputVars); } } diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Share.php b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Share.php index e4e58e53b2..d2f1901814 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Prod/Share.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Prod/Share.php @@ -47,10 +47,22 @@ class Share implements ControllerProviderInterface, ServiceProviderInterface $controllers->get('/record/{base_id}/{record_id}/', 'controller.prod.share:shareRecord') ->before(function (Request $request) use ($app, $firewall) { - $firewall->requireRightOnSbas( - \phrasea::sbasFromBas($app, $request->attributes->get('base_id')), - \ACL::BAS_CHUPUB - ); + $socialTools = $app['conf']->get(['registry', 'actions', 'social-tools']); + if($socialTools === "all") { + return; + } + elseif($socialTools === "none") { + $app->abort(403, 'social tools disabled'); + } + elseif($socialTools === "publishers") { + $firewall->requireRightOnSbas( + \phrasea::sbasFromBas($app, $request->attributes->get('base_id')), + \ACL::BAS_CHUPUB + ); + } + else { + throw new \Exception("bad value \"" . $socialTools . "\" for social tools"); + } }) ->bind('share_record'); diff --git a/templates/web/prod/Share/record.html.twig b/templates/web/prod/Share/record.html.twig index 24c26fb200..477f0fe192 100644 --- a/templates/web/prod/Share/record.html.twig +++ b/templates/web/prod/Share/record.html.twig @@ -1,59 +1,122 @@ {% if not isAvailable %}

{{ 'No permalink available.' | trans }}

{% else %} - {% if preview.permalinkUrl is not empty %} + {% if subdefList is not empty %} + {% set defKey = defaultKey %}
-
-

- - - {% trans %}Send to Twitter{% endtrans %} - -

-

- - - {% trans %}Send to Facebook{% endtrans %} - -

- -
-
- - - -

- {{ 'previewLinkLabel' | trans }}    - {{ 'copyClipboardLabel' | trans }} -

-
-
- - -

- {{ 'previewLinkLabel' | trans }}    - {{ 'copyClipboardLabel' | trans }} -

-
-
- {#{% if type == 'image' %}#} - - {% spaceless %} - - {% endspaceless %} -

- {{ 'previewLinkLabel' | trans }}    - {{ 'copyClipboardLabel' | trans }} -

-
- {#{% endif %}#} -
+
+

+ {{ 'share::share-record: advance' | trans }} + + {{ 'share::share-record: select-shared-def' | trans }} + +

+

+ + + {% trans %}Send to Twitter{% endtrans %} + +

+

+ + + {% trans %}Send to Facebook{% endtrans %} + +

+ +
+
+ + + +

+ {{ 'previewLinkLabel' | trans }}    + {{ 'copyClipboardLabel' | trans }} +

+
+
+ + +

+ {{ 'previewLinkLabel' | trans }}    + {{ 'copyClipboardLabel' | trans }} +

+
+
+ {#{% if type == 'image' %}#} + + {% spaceless %} + + {% endspaceless %} +

+ {{ 'previewLinkLabel' | trans }}    + {{ 'copyClipboardLabel' | trans }} +

+
+ {#{% endif %}#} +
+ + {% else %}
{{ 'No URL available' | trans }}
{% endif %} -{% endif %} +{% endif %} \ No newline at end of file diff --git a/tests/Alchemy/Tests/Phrasea/Controller/Prod/ShareTest.php b/tests/Alchemy/Tests/Phrasea/Controller/Prod/ShareTest.php index e8aa79d03d..f3163a99ef 100644 --- a/tests/Alchemy/Tests/Phrasea/Controller/Prod/ShareTest.php +++ b/tests/Alchemy/Tests/Phrasea/Controller/Prod/ShareTest.php @@ -2,6 +2,7 @@ namespace Alchemy\Tests\Phrasea\Controller\Prod; +use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Controller\Prod\ShareController; use Alchemy\Phrasea\ControllerProvider\Prod\Share; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -19,86 +20,63 @@ class ShareTest extends \PhraseanetAuthenticatedWebTestCase /** * @covers Alchemy\Phrasea\Controller\Prod\Share::shareRecord * @covers Alchemy\Phrasea\Controller\Prod\Share::connect - * @covers Alchemy\Phrasea\Controller\Prod\Share::call */ - public function testMountedRouteSlash() + public function testRouteSlashALL() { - $url = sprintf('/prod/share/record/%d/%d/', self::$DI['record_1']->get_base_id(), self::$DI['record_1']->get_record_id()); - self::$DI['client']->request('GET', $url); - $this->assertTrue(self::$DI['client']->getResponse()->isOk()); + $this->_RouteSlash("all", [0=>true, 1=>true, 2=>true, 3=>true]); } - /** - * @covers Alchemy\Phrasea\Controller\Prod\Share::shareRecord - * @covers Alchemy\Phrasea\Controller\Prod\Share::connect - */ - public function testRouteSlash() + public function testRouteSlashPublishers() { - $stubbedACL = $this->stubACL(); - - //has_right_on_base return true - $stubbedACL->expects($this->once()) - ->method('has_right_on_sbas') - ->will($this->returnValue(true)); - - //has_access_to_subdef return true - $stubbedACL->expects($this->once()) - ->method('has_access_to_subdef') - ->will($this->returnValue(true)); - - - $url = sprintf('/prod/share/record/%d/%d/', self::$DI['record_1']->get_base_id(), self::$DI['record_1']->get_record_id()); - self::$DI['client']->request('GET', $url); - $this->assertTrue(self::$DI['client']->getResponse()->isOk()); + $this->_RouteSlash("publishers", [0=>false, 1=>true, 2=>false, 3=>true]); + } + public function testRouteSlashNone() + { + $this->_RouteSlash("none", [0=>false, 1=>false, 2=>false, 3=>false]); + } + private function _RouteSlash($setting, $expected) + { + $app = $this->getApplication(); + $_conf = $app['conf']; + $app['conf'] = $this->getMockBuilder('Alchemy\Phrasea\Core\Configuration\PropertyAccess') + ->disableOriginalConstructor() + ->getMock(); + $app['conf'] + ->expects($this->any()) + ->method('get') + ->will($this->returnCallback(function ($param, $default) use ($_conf, $setting) { + switch ($param) { + case ['registry', 'actions', 'social-tools']: + return $setting; + } + return $_conf->get($param, $default); + })); + $result = []; + foreach($expected as $flags=>$v) { + $stubbedACL = $this->stubACL(); + // "has_right_on_sbas" IS checked by the route->before(), the url will return 403 + $stubbedACL->expects($this->any()) + ->method('has_right_on_sbas') + ->will($this->returnValue(($flags & 1) ? true:false)); + // but "has_access_to_subdef" IS NOT checked (the url will return a 200 with a message "no subdef to share") + $stubbedACL->expects($this->any()) + ->method('has_access_to_subdef') + ->will($this->returnValue(($flags & 2) ? true:false)); + $url = sprintf('/prod/share/record/%d/%d/', self::$DI['record_1']->get_base_id(), self::$DI['record_1']->get_record_id()); + self::$DI['client']->request('GET', $url); + $result[$flags] = self::$DI['client']->getResponse()->isOk(); + } + $this->assertEquals($expected, $result); } - /** * @covers Alchemy\Phrasea\Controller\Prod\Share::shareRecord */ public function testShareRecord() { $share = new ShareController(self::$DI['app']); - /** @var \record_adapter $record_1 */ $record_1 = self::$DI['record_1']; - $response = $share->shareRecord($record_1->getBaseId(), $record_1->getRecordId()); $this->assertTrue($response->isOk()); } - - /** - * @covers Alchemy\Phrasea\Controller\Prod\Share::shareRecord - */ - public function testShareRecordBadAccess() - { - $share = new ShareController(self::$DI['app']); - - $stubbedACL = $this->getMockBuilder('\ACL') - ->disableOriginalConstructor() - ->getMock(); - - //has_access_to_subdef return false - $stubbedACL->expects($this->once()) - ->method('has_access_to_subdef') - ->will($this->returnValue(false)); - - $aclProvider = $this->getMockBuilder('Alchemy\Phrasea\Authentication\ACLProvider') - ->disableOriginalConstructor() - ->getMock(); - $aclProvider->expects($this->any()) - ->method('get') - ->will($this->returnValue($stubbedACL)); - - self::$DI['app']['acl'] = $aclProvider; - - try { - $share->shareRecord(self::$DI['record_1']->get_base_id(), self::$DI['record_1']->get_record_id()); - } catch (HttpException $exception) { - $this->assertEquals(403, $exception->getStatusCode()); - - return; - } - - $this->fail('An access denied exception should have been thrown.'); - } } From cc2f919fe029f32619e34fb200ae448d66879368 Mon Sep 17 00:00:00 2001 From: Mike Ng Date: Fri, 24 Nov 2017 16:41:22 +0400 Subject: [PATCH 2/2] dump locales --- resources/locales/messages.de.xlf | 37 +++++++++++++++++++---------- resources/locales/messages.en.xlf | 37 +++++++++++++++++++---------- resources/locales/messages.fr.xlf | 37 +++++++++++++++++++---------- resources/locales/messages.nl.xlf | 37 +++++++++++++++++++---------- resources/locales/validators.de.xlf | 2 +- resources/locales/validators.en.xlf | 2 +- resources/locales/validators.fr.xlf | 2 +- resources/locales/validators.nl.xlf | 2 +- 8 files changed, 100 insertions(+), 56 deletions(-) diff --git a/resources/locales/messages.de.xlf b/resources/locales/messages.de.xlf index c2aacbe27e..6b031485e7 100644 --- a/resources/locales/messages.de.xlf +++ b/resources/locales/messages.de.xlf @@ -1,6 +1,6 @@ - +
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. @@ -2265,7 +2265,7 @@ Detailed view URL Detailansicht URL - prod/Share/record.html.twig + prod/Share/record.html.twig Details @@ -2580,7 +2580,7 @@ Embed code Embed-Code - prod/Share/record.html.twig + prod/Share/record.html.twig Empty a collection @@ -4245,7 +4245,7 @@ No URL available keine verfügbare URL - prod/Share/record.html.twig + prod/Share/record.html.twig No account yet? @@ -5461,7 +5461,7 @@ Resource URL Resource URL - prod/Share/record.html.twig + prod/Share/record.html.twig Resquest access @@ -5739,12 +5739,12 @@ Send to Facebook Auf Facebook teilen - prod/Share/record.html.twig + prod/Share/record.html.twig Send to Twitter Auf Twitter teilen - prod/Share/record.html.twig + prod/Share/record.html.twig Sent @@ -9325,9 +9325,9 @@ copyClipboardLabel in der Zwischenablage kopieren - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig dans %category% @@ -10652,9 +10652,9 @@ previewLinkLabel ansichten - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig print:: image de choix et description @@ -10967,6 +10967,7 @@ prod::tools: document Dokument + Controller/Prod/ShareController.php Controller/Prod/ToolsController.php @@ -12107,6 +12108,16 @@ Test E-Mail Überprüfungen web/admin/dashboard.html.twig + + share::share-record: advance + share::share-record: advance + prod/Share/record.html.twig + + + share::share-record: select-shared-def + share::share-record: select-shared-def + prod/Share/record.html.twig + sport Sport diff --git a/resources/locales/messages.en.xlf b/resources/locales/messages.en.xlf index 6e4ee0b7ed..e255caea7f 100644 --- a/resources/locales/messages.en.xlf +++ b/resources/locales/messages.en.xlf @@ -1,6 +1,6 @@ - +
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. @@ -2265,7 +2265,7 @@ Detailed view URL URL of the detailed view - prod/Share/record.html.twig + prod/Share/record.html.twig Details @@ -2580,7 +2580,7 @@ Embed code Embed code - prod/Share/record.html.twig + prod/Share/record.html.twig Empty a collection @@ -4245,7 +4245,7 @@ No URL available No URL available - prod/Share/record.html.twig + prod/Share/record.html.twig No account yet? @@ -5461,7 +5461,7 @@ Resource URL Resource URL - prod/Share/record.html.twig + prod/Share/record.html.twig Resquest access @@ -5739,12 +5739,12 @@ Send to Facebook Send to Facebook - prod/Share/record.html.twig + prod/Share/record.html.twig Send to Twitter Send to Twitter - prod/Share/record.html.twig + prod/Share/record.html.twig Sent @@ -9326,9 +9326,9 @@ copyClipboardLabel Copy to clipboard - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig dans %category% @@ -10653,9 +10653,9 @@ previewLinkLabel Preview - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig print:: image de choix et description @@ -10968,6 +10968,7 @@ prod::tools: document Document + Controller/Prod/ShareController.php Controller/Prod/ToolsController.php @@ -12108,6 +12109,16 @@ E-mails send test web/admin/dashboard.html.twig + + share::share-record: advance + share::share-record: advance + prod/Share/record.html.twig + + + share::share-record: select-shared-def + share::share-record: select-shared-def + prod/Share/record.html.twig + sport sport diff --git a/resources/locales/messages.fr.xlf b/resources/locales/messages.fr.xlf index 120dd38604..ddb08c69b6 100644 --- a/resources/locales/messages.fr.xlf +++ b/resources/locales/messages.fr.xlf @@ -1,6 +1,6 @@ - +
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. @@ -2265,7 +2265,7 @@ Detailed view URL URL de la vue détaillée - prod/Share/record.html.twig + prod/Share/record.html.twig Details @@ -2580,7 +2580,7 @@ Embed code Code d'intégration (Embed code) - prod/Share/record.html.twig + prod/Share/record.html.twig Empty a collection @@ -4245,7 +4245,7 @@ No URL available Aucune URL de disponible - prod/Share/record.html.twig + prod/Share/record.html.twig No account yet? @@ -5463,7 +5463,7 @@ Pour les utilisateurs authentifiés, la demande de validation est également dis Resource URL URL de la ressource - prod/Share/record.html.twig + prod/Share/record.html.twig Resquest access @@ -5741,12 +5741,12 @@ Pour les utilisateurs authentifiés, la demande de validation est également dis Send to Facebook Envoyer vers Facebook - prod/Share/record.html.twig + prod/Share/record.html.twig Send to Twitter Envoyer vers Twitter - prod/Share/record.html.twig + prod/Share/record.html.twig Sent @@ -9329,9 +9329,9 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le copyClipboardLabel Copier dans le presse-papier - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig dans %category% @@ -10656,9 +10656,9 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le previewLinkLabel Prévisualiser - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig print:: image de choix et description @@ -10971,6 +10971,7 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le prod::tools: document Document + Controller/Prod/ShareController.php Controller/Prod/ToolsController.php @@ -12111,6 +12112,16 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le Tests d'envois d'e-mails web/admin/dashboard.html.twig + + share::share-record: advance + share::share-record: advance + prod/Share/record.html.twig + + + share::share-record: select-shared-def + share::share-record: select-shared-def + prod/Share/record.html.twig + sport sport diff --git a/resources/locales/messages.nl.xlf b/resources/locales/messages.nl.xlf index f368872247..deabb6ae7a 100644 --- a/resources/locales/messages.nl.xlf +++ b/resources/locales/messages.nl.xlf @@ -1,6 +1,6 @@ - +
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. @@ -2269,7 +2269,7 @@ Detailed view URL Gedetailleerde weergave URL - prod/Share/record.html.twig + prod/Share/record.html.twig Details @@ -2584,7 +2584,7 @@ Embed code Sluit de code in - prod/Share/record.html.twig + prod/Share/record.html.twig Empty a collection @@ -4249,7 +4249,7 @@ No URL available Geen URL beschikbaar - prod/Share/record.html.twig + prod/Share/record.html.twig No account yet? @@ -5465,7 +5465,7 @@ Resource URL Bron URL - prod/Share/record.html.twig + prod/Share/record.html.twig Resquest access @@ -5743,12 +5743,12 @@ Send to Facebook Verstuur naar Facebook - prod/Share/record.html.twig + prod/Share/record.html.twig Send to Twitter Verstuur naar Twitter - prod/Share/record.html.twig + prod/Share/record.html.twig Sent @@ -9329,9 +9329,9 @@ copyClipboardLabel copyClipboardLabel - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig dans %category% @@ -10656,9 +10656,9 @@ previewLinkLabel previewLinkLabel - prod/Share/record.html.twig - prod/Share/record.html.twig - prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig + prod/Share/record.html.twig print:: image de choix et description @@ -10971,6 +10971,7 @@ prod::tools: document prod::tools: document + Controller/Prod/ShareController.php Controller/Prod/ToolsController.php @@ -12111,6 +12112,16 @@ Testen voor het versturen van mail web/admin/dashboard.html.twig + + share::share-record: advance + share::share-record: advance + prod/Share/record.html.twig + + + share::share-record: select-shared-def + share::share-record: select-shared-def + prod/Share/record.html.twig + sport sport diff --git a/resources/locales/validators.de.xlf b/resources/locales/validators.de.xlf index e9542f0cc8..c38d4d62b3 100644 --- a/resources/locales/validators.de.xlf +++ b/resources/locales/validators.de.xlf @@ -1,6 +1,6 @@ - +
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. diff --git a/resources/locales/validators.en.xlf b/resources/locales/validators.en.xlf index 324bce198f..8e508b21ff 100644 --- a/resources/locales/validators.en.xlf +++ b/resources/locales/validators.en.xlf @@ -1,6 +1,6 @@ - +
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. diff --git a/resources/locales/validators.fr.xlf b/resources/locales/validators.fr.xlf index 6446b7e611..574553b0a6 100644 --- a/resources/locales/validators.fr.xlf +++ b/resources/locales/validators.fr.xlf @@ -1,6 +1,6 @@ - +
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. diff --git a/resources/locales/validators.nl.xlf b/resources/locales/validators.nl.xlf index 7077d6f7e7..8937ac1dfa 100644 --- a/resources/locales/validators.nl.xlf +++ b/resources/locales/validators.nl.xlf @@ -1,6 +1,6 @@ - +
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.