Acessando objetos i18n de diferentes escopos


10

Eu tenho construído uma estrutura pessoal minha que começou como uma maneira de aprender o padrão MVC e agora evoluiu para algo que eu gosto mais do que a maioria das estruturas por aí (provavelmente porque adiciono o que gosto e mudo o que uso) gosto, mas mesmo assim) e para o bem ou para o mal, eu o uso em alguns projetos.

O problema que tenho agora é que não consigo encontrar uma maneira decente de acessar minha funcionalidade i18n (não é realmente i18n, são apenas traduções, não inclui suporte completo ao i18n, pelo menos ainda não).

A maneira como funciona é que eu uso arquivos de configuração como arquivos de idioma, porque achei que seria bastante conveniente usar a Configclasse para carregá-los, pois no meu framework os arquivos de configuração são carregados dinamicamente - não carregados, a menos que seja necessário, você pode dar uma olhada aqui

class Config {

    private static $settings = array();

    private function __construct() {

    }

    public static function load($file) {
        $path = PROJECT_PATH . '/config/' . $file . '.php';
        if (is_file($path)) {
            $settings = require($path);
        } else {
            throw new Exception('Configuration file [' . $file . '] doesn\'t exist', 500);
        }

        self::$settings[$file] = $settings;
        return true;
    }

    public static function get($file = null) {
        if ($file === null) {
            return self::$settings;
        } elseif (isset(self::$settings[$file]) || self::load($file)) {
            return self::$settings[$file];
        }
    }
}

Onde um único arquivo de configuração seria semelhante a este

<?php return array(
    'setting0' => 'value',
    'setting1' => 'value',
    ....
);

Isso permite que o PHP armazene em cache esses arquivos e carregá-los se torna muito rápido.

Agora, langvamos para as traduções, como eu disse que são arquivos de configuração em um diretório diferente chamado , mas não posso simplesmente ligar Config::get('lang/en/myLangFile')sempre que preciso acessar uma tradução, então inventei (inventei) a Translationsclasse, que representa um arquivo de traduções únicas

class Translations {

    protected $data = [];

    public function __construct(array $translations) {
        $this->data = $translations;
    }

    public function __get($name) {
        return isset($this->data[$name]) ? $this->data[$name] : $name;
    }

}

Agora é super conveniente e bonito acessar traduções

$t = new Translations([...]);

echo $t->translationKey;

Eu tenho uma Langclasse que é usada para configurar o idioma preferido do usuário, entre outras pequenas coisas, então achei que usaria isso como uma fábrica para minhas Translationsaulas

class Lang {

    public static function get($file) {
        return new Translations(Config::get('lang/' . self::$lang . '/' . $file));
    }

}

Então agora tudo o que tenho que fazer para pegar algumas traduções é

$t = Lang::get('myLangFile');

echo $t->translationKey;

Caso você esteja se perguntando por que eu tenho tanta coisa estática, é porque essas classes não fazem sentido para serem instanciadas e eu não gosto do padrão de design singleton, prefiro ter "classes estáticas", mesmo que elas não sejam suportadas no PHP (ainda?).

Até agora tudo bem, eu tenho as traduções em andamento, mas vamos ao problema (finalmente).

Quando uma exibição é renderizada, é provável que você imprima algum texto para o usuário e, para isso, preciso ter um objeto de tradução disponível, mas é bastante inconveniente passar isso do controlador, porque eu precisaria ir e coloque isso em cada método e isso seria um inferno, além disso, se eu fizer isso, algum outro controlador chamará a mesma visualização sem as traduções corretas que o material vai quebrar, o que faz sentido, mas acrescenta complexidade ao programa.

O que venho fazendo até este ponto está no topo de todas as visualizações que construo meu objeto de traduções

<?php $t = Lang::get('myLangFile') ?>

<div><?= $t->helloWorld ?></div>

Isso funciona e me garante que meus pontos de vista funcionarão independentemente de quem os está chamando e basicamente não custam quase nada em termos de desempenho, porque instanciar um Translationsnão copiará o array que contém as informações, a menos que uma alteração seja introduzida, pois o código no construtor é apenas uma atribuição, então acho que não há problema com isso, mas está me incomodando por algum motivo que não é a coisa certa a se fazer.

Além disso, precisarei usar uma Translationsclasse em um modelo ou validador ocasionalmente e precisaria instancia-la também, portanto, em uma única execução, posso instanciar o mesmo Translationsobjeto várias vezes. Para resolver esse problema, eu precisaria começar a colocar esses objetos no registro e acho que isso estaria indo longe demais.

Gostaria de ver algumas reflexões sobre essa abordagem, já que eu poderia ficar cego por conta própria e possivelmente obter alguns conselhos e outras coisas úteis. Agradecemos antecipadamente a quem escolheu poupar seu tempo com o meu problema!

Respostas:


0

<?php $t = Lang::get('myLangFile') ?>

<div><?= $t->helloWorld ?></div>

Isso funciona e me garante que meus pontos de vista funcionarão independentemente de quem os está chamando e basicamente não custam quase nada em termos de desempenho, porque a instanciação de um Translations não copiará o array que contém as informações, a menos que uma alteração seja introduzida, já que o código no construtor é apenas uma atribuição , então acho que não há problema com isso, mas está me incomodando por algum motivo que não é a coisa certa a fazer.

Entendo o que você quer dizer ...
acho que uma coisa que pode estar incomodando você é que, adicionando à visualização a responsabilidade de carregar os arquivos de idioma, você está quebrando o padrão de design da Inversão do Controle.
Por isso, se, por exemplo, seu 'myLangFile' fica muito grande e você deseja dividi-lo em 2 arquivos separados, não pode fazê-lo sem alterar o código de exibição.
O que você acha?


1
Exatamente, esse é um motivo absolutamente válido.
Php_nub_qq

1
Mesmo? O arquivo de idioma não pode incluir outros arquivos em si? Ou ler de um banco de dados?
precisa saber é

@svidgen com design extremamente ruim #
php_nub_qq
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.