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 Config
classe 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, lang
vamos 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 Translations
classe, 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 Lang
classe 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 Translations
aulas
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 Translations
nã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 Translations
classe em um modelo ou validador ocasionalmente e precisaria instancia-la também, portanto, em uma única execução, posso instanciar o mesmo Translations
objeto 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!
fonte