Giter Club home page Giter Club logo

Comments (7)

froschdesign avatar froschdesign commented on August 31, 2024

@bkilinc
Please compare your code with the example in the related documentation: https://docs.zendframework.com/zend-validator/messages/#using-pre-translated-validation-messages

from zend-validator.

bkilinc avatar bkilinc commented on August 31, 2024

It doesn't work either. I don't use MVC framework. This is an expressive API application.

from zend-validator.

weierophinney avatar weierophinney commented on August 31, 2024

@bkilinc If you look carefully at the typehints, each of those that accept a translator are looking for a Zend\Validator\Translator\TranslatorInterface instance. This interface is compatible with that found in zend-i18n (it defines a singe method, translate(), which has an identical signature to the equivalent method in zend-i18n), so you can implement it via an anonymous class.

As an example, I would create a delegator factory on the zend-i18n TranslatorInterface service that does the following:

use Psr\Container\ContainerInterface;
use Zend\I18n\Translator\TranslatorInterface as I18nTranslatorInterface;
use Zend\Validator\Translator\TranslatorInterface as ValidatorTranslatorInterface;

class TranslatorDecoratorFactory
{
    public function __construct(ContainerInterface $container, string $serviceName, callable $factory)
    {
        return new class($factory()) implements I18nTranslatorInterface, ValidatorTranslatorInterface {
            /**
             * @var I18nTranslatorInterface
             */
            private $translator;
    
            /**
             * @param I18nTranslatorInterface $translator
             */
            public function __construct(I18nTranslatorInterface $translator)
            {
                $this->translator = $translator;
            }
    
            public function translate($message, $textDomain = 'default', $locale = null)
            {
                return $this->translator->translate($message, $textDomain, $locale);
            }
    
            public function translatePlural($singular, $plural, $number, $textDomain = 'default', $locale = null)
            {
                return $this->translator->translatePlural($singular, $plural, $number, $textDomain, $locale);
            }
        };
    }
}

Attaching it as a delegator looks like this:

// in config/autoload/dependencies.global.php:

use Zend\I18n\Translator\TranslatorInterface as I18nTranslatorInterface;

return [
    'dependencies' => [
        'delegators' => [
            I18nTranslatorInterface::class => [TranslatorFactory::class],
        ],
    ],
];

Working with it this way, you can still add translation file patterns via other delegators on the zend-i18n translator interface service (just make sure they occur BEFORE the one that decorates it). Alternately, you could add a __call() method to the implementation so that it can proxy any other method calls to the underlying translator instance (which is what the one on zend-mvc-i18n does).

from zend-validator.

bkilinc avatar bkilinc commented on August 31, 2024

I should simply create a translator object and assign it as default translator to abstract validator. This should be as simple thing. And this should be filed as a bug.
\Zend\Validator\AbstractValidator::setDefaultTranslator($translator) method
should accept \Zend\I18n\Translator\Translator() object.
Currently it does not, because it is an old Zend Framework 2 method which only recognizes a MVC component.
What you suggest is an ugly workaround. Sorry, I appreciate your time (for hiding a bug). But I am just trying to assign a static object to a class.
Anyway, I am not using Zend Framework way of translating things in my API. I am translating messages on clientside, using javascript.

from zend-validator.

weierophinney avatar weierophinney commented on August 31, 2024

@bkilinc This was a compromise we did for backwards compatibility purposes.

Contrary to your following statement:

I should simply create a translator object and assign it as default translator to abstract validator. This should be as simple thing. And this should be filed as a bug.
\Zend\Validator\AbstractValidator::setDefaultTranslator($translator) method
should accept \Zend\I18n\Translator\Translator() object.
Currently it does not, because it is an old Zend Framework 2 method which only recognizes a MVC component.
What you suggest is an ugly workaround.

Whether or not you consider it ugly is beside the point; there were very good reasons for this design.

Prior to splitting the components into their own development, we had a hard dependency on zend-i18n within zend-validator. We wanted to ensure that we could remove that dependency (many developers never use that functionality), but still keep the functionality. The way to do that was to create a segregated interface: an interface in zend-validator that fulfilled the translation functionality we consume within this component. From there, we could then adapt the zend-i18n translator to it, or, better, use something standalone if desired.

zend-mvc-i18n does this adaptation for zend-mvc projects. Note that it is an additional package on top of zend-i18n (and, really, zend-validator as well). Even in zend-mvc we have to adapt the zend-i18n translator to be used within zend-validator! (This is true for a few other components as well.)

We could do similarly for Expressive; nobody's proposed it prior to this. If you would like such functionality, feel free to propose it. However, in the meantime, the workaround detailed in my previous comment will work today.

from zend-validator.

bkilinc avatar bkilinc commented on August 31, 2024

Ok, thank you. I will use your solution for server-side translations. I thought it could be more simple. But it is OK right now.

from zend-validator.

bkilinc avatar bkilinc commented on August 31, 2024

I created following middleware, for setting default translator. You just need to put it in routes or in application pipe. Currently you can define defaultLanguage in middleware factory. And it does not detect accept-language from headers. but works for me.

namespace App\API;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

use Zend\I18n\Translator\Resources;
use \Zend\Validator\Translator\TranslatorInterface;
use \Zend\Validator\AbstractValidator;

class Translator implements TranslatorInterface  {
    protected $langData;
    protected $lang;
    function __construct($lang) {
        $this->lang = $lang;
        $path = $this->resourcePath($this->lang);
        if (! file_exists($path)) {            
            $this->lang = 'en';
            $path = $this->resourcePath($this->lang);
        }
        $this->langData =  require($path);
    }   

    function getLanguage()
    {
        return $this->lang;
    }

    function resourcePath($lang)
    {
        return realpath( Resources::getBasePath().'/'.$lang.'/Zend_Validate.php');
    }

    function translate($message, $textDomain = 'default', $locale = null) {
        return isset($this->langData[$message]) ? $this->langData[$message] : $message;
    }
}

class ValidatorTranslate implements MiddlewareInterface
{    
    protected $defaultLanguage;
    
    function __construct($defaultLanguage = 'en')
    {
        $this->defaultLanguage = $defaultLanguage;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
    {        
        $lang = $this->defaultLanguage;
        // TODO: get accept-language from header
        
        $translator = new Translator($lang);            
        AbstractValidator::setDefaultTranslator($translator);

        $response = $handler->handle($request);

        return $response;
    }
}

from zend-validator.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.