Kdyby\Translation uložení nepřeložené message do databáze
- serten
- Člen | 55
Zdravím,
řeším aktuálně situaci, kdy využívám pro překlad aplikace Kdyby\Translation a používám databázový loader pro Doctrine. Vše jede jak má, jen se v tuto chvíli snažím nepřeložené message nějak automaticky vložit do databáze. Pokaždé, kdy by se zjistilo, že daná message není v databázi, nebyl by tam záznam a nebo by záznam nebyl přeložený, tak by se vytvořil nový pro danou zprávu v konkrétním jazyce. Chci tím následně umožnit uživateli/administrátorovi překládat si aplikaci a navíc abych nemusel každou zprávu a text ručně zapisovat do databáze. Bohužel jsem nepřišel na způsob, jak přepsat nebo rozšířit tento Translator. Dokázal by jste mi někdo poradit, jak toto provést? Děkuji za jakoukoliv radu.
- Azathoth
- Člen | 495
Ahoj,
z Kdyby/Translation jde vytáhnout všechny překlady (např. pro češtinu a
angličtinu) tímhle
$catalogueCs = $this->translator->getCatalogue('cs');
$catalogueEn = $this->translator->getCatalogue('en');
s tím, že $this->translator je, podle očekávání,
Kdyby\Translation\Translator, a $catalogueCs
a
$catalogueEn
jsou katalogy, zapouzřující překlady do daného
jazyka.
Takže pokud vím, že mám všechny překlady v češtině a chci je doplnit
prázdný string do chybějících překladů v angličtině, udělám
to takhle
$allCsTranslations = $catalogueCs->all(); //tím vyytáhneš překlady do češtiny jako 2D pole
foreach ($allCsTranslations as $domain => $translations) {
foreach ($translations as $key => $value) {
if (!$catalogueEn->defines($key, $domain)) { //chybí překlad do angličtiny
$defautValue = '';
$catalogueEn->set($key, $defautValue, $domain); //doplním defaultní text
}
}
}
a uložit do databáze to můžeš pak přes Writer ze Symfony\Translation, na kterém Kdyby\Translation stojí, takhle
$this->writer->writeTranslations($catalogueCs, 'database');
$this->writer->writeTranslations($catalogueEn, 'database');
a writer se o všechno postará.
$this->writer
získáš pomocí DI v presenteru takhle (do
modelu si to pochopitelně injectuj přes konstruktor):
/** @var \Symfony\Component\Translation\Writer\TranslationWriter @inject */
public $writer;
Takže pokud bude někdo přidávat text do jednoho jazyka, pomocí té defines metody u katalogu pro jiný jazyk si můžeš ověřit, jestli v tom jazyku ten překlad je a pokud není, tak tam doplníš ten defaultní a je to.
Snad jsem pomohl, kdyby to nezabralo, ptej se.
Tohle je bohužel strašně špatně zdokumentované i u Symfony, tu práci
s katalogem a writerem jsem objevil tak nějak metodou pokus, omyl.
A tohle je obecné pro Kdyby\Translation, takže je jedno, jaké tam máš
úložiště překladů, poradí si to se vším, co má načtený Loader a
Dumper.
A to, kam se to uloží, řídíš tím stringem ‚database‘. Kdybys to
chtěl uložit jinam, třeba do neonu, yamlu nebo jinam, tak to stačí udělat
takhle:
$this->writer->writeTranslations($catalogueEn, 'neon');
$this->writer->writeTranslations($catalogueEn, 'yaml');
Tyhle modifikace jsem zkoušel pouze u ukládání do souborů, u databáze
jsem, myslím, tu modifikaci překladů na produkci ještě nezkoušel, ale
pokud by se nenačítaly nové překlady a zobrazovaly by se pořád ty staré,
tak to je tím, že se špatně invaliduje cache v Kdyby\Translation.
Cache v Kdyby\Translation vypneš takhle:
Nejdřív si injectuješ catalogueCompiler
/** @var \dyby\Translation\CatalogueCompiler @inject */
public $catalogueCompiler; //injectuješ si třídu zodpovědnou za tvorbu překladové cache
a pak mu nastavíš debug mode, kdy se nepoužívá cache
$this->catalogueCompiler->enableDebugMode();
- serten
- Člen | 55
Super, díky za pomoc. Vypadá to dobře. Jen mě teď napadlo, jde nějak zautomatizovat tady to ukládání do databáze? V případě že to ten klíč v databázi nenajde, tak ho tam rovnou uloží. Abych při přidání nějakého nového klíče nebo jazyka nemusel všechny klíče k danému jazyku zdlouhavě přidávat do databáze.
- martin.knor
- Člen | 17
Ahoj, zrovna jsem to resil, tak pridavam moje reseni. Potreboval jsem, aby kdyz se najde text, ktery neni v katalogu, tak se hodi do databaze – nebo kamkoliv jinam :)
Zaklad je prepsat translator tak, aby kdyz nema preklad, tak je hodi do katalogu:
<?php
namespace Makr\Translation;
use App\Model\Entity\Translation;
use App\Model\Entity\Translations;
use Kdyby\Doctrine\EntityManager;
use Kdyby\Translation\Helpers;
class Translator extends \Kdyby\Translation\Translator {
/** @var \Kdyby\Doctrine\EntityManager */
private $em;
public function __construct(\Kdyby\Translation\IUserLocaleResolver $localeResolver,
\Symfony\Component\Translation\MessageSelector $selector,
\Kdyby\Translation\CatalogueCompiler $catalogueCompiler,
\Kdyby\Translation\FallbackResolver $fallbackResolver,
\Kdyby\Translation\IResourceLoader $loader,
EntityManager $em
)
{
parent::__construct($localeResolver, $selector, $catalogueCompiler, $fallbackResolver, $loader);
$this->em = $em;
}
/**
* {@inheritdoc}
*/
public function translate($message, $count = null, $parameters = [], $domain = null, $locale = null)
{
$catalogue = $this->getCatalogue($locale);
if ($domain === null) {
list($domain, $message) = Helpers::extractMessageDomain($message);
}
if (!$catalogue->has($message, $domain)) {
$translation = new Translation();
$translation->setKey($domain . '.' . $message)->setLocale($locale ?: $this->getLocale());
$this->em->safePersist($translation);
}
return parent::translate($message, $count, $parameters, $domain, $locale);
}
}
Pak je potreba zaregistrovat ho v neonu – resp. prepsat puvodni
translation.default:
class: Makr\Translation\Translator(@translation.userLocaleResolver)
Editoval martin.knor (5. 11. 2016 12:06)