Files
grzanieplus.pl/plugins/stLanguagePlugin/lib/stLanguageModelTranslator.class.php
2025-03-12 17:06:23 +01:00

201 lines
5.4 KiB
PHP

<?php
class stLanguageModelTranslator
{
const BASE_LANGUAGE = 'en_US';
/**
* Wersja językowa
*
* @var string
*/
protected $language;
/**
* Temat graficzny
*
* @var Theme
*/
protected $theme;
public function __construct(string $language, ?Theme $theme = null)
{
$this->language = $language;
$this->theme = $theme;
}
public function getLastModifiedTime(): ?int
{
$translationFiles = $this->getTranslationFiles();
if (null === $translationFiles)
{
return null;
}
$lastModifiedTime = [];
foreach ($translationFiles as $file)
{
$lastModifiedTime[] = filemtime($file);
}
return max($lastModifiedTime);
}
public function translate(string $language): bool
{
$translationFiles = $this->getTranslationFiles();
if (null === $translationFiles)
{
return false;
}
$this->translateModels($language, $translationFiles);
return true;
}
protected function getTranslationFiles(): ?array
{
$translationFiles = $this->findTranslationFiles($this->language);
if (null === $translationFiles)
{
return null;
}
if (null !== $this->theme)
{
$themeTranslationFiles = $this->findTranslationFiles($this->language, $this->theme->getTheme());
if (null !== $themeTranslationFiles)
{
$translationFiles = array_merge($translationFiles, $themeTranslationFiles);
}
}
return $translationFiles;
}
protected function findTranslationFiles(string $language, ?string $theme = null): ?array
{
$path = sfConfig::get('sf_data_dir') . '/translation/' . $language;
$path .= null !== $theme ? '/' . $theme : '/all';
if (!is_dir($path))
{
return null;
}
return glob($path . '/*yml');
}
protected function translateModels(string $language, array $translationFiles)
{
$logging = sfConfig::get('sf_logging_enabled');
// wyłączamy logowanie, aby nie przekroczyć dozwolonej pamięci przy tylu operacjach odczytu i zapisu
sfConfig::set('sf_logging_enabled', false);
foreach ($translationFiles as $file)
{
$modelClass = basename($file, '.yml');
$modelClassPeer = $modelClass . 'Peer';
$fieldTranslations = sfYaml::load($file);
if (!class_exists($modelClass))
{
throw new sfException(sprintf('Model class "%s" does not exist', $modelClass));
}
$offset = 0;
$count = $this->getFieldTranslationCount($fieldTranslations, $modelClassPeer);
$c = $this->getModelCriteria($modelClass);
do
{
$c->setOffset($offset);
$c->setLimit(20);
$models = call_user_func([$modelClassPeer, 'doSelectWithI18n'], $c, self::BASE_LANGUAGE);
foreach ($models as $model)
{
$update = false;
foreach ($fieldTranslations as $fieldName => $translations)
{
$phpName = sfInflector::camelize($fieldName);
$getter = 'get' . $phpName;
$setter = 'set' . $phpName;
$optGetter = 'getOpt' . $phpName;
$model->setCulture(self::BASE_LANGUAGE);
$value = $model->$getter();
$model->setCulture($language);
if (isset($translations[$value]) && (!method_exists($model, $optGetter) || $model->$getter() == $model->$optGetter()))
{
$model->$setter($translations[$value]);
$update = true;
}
}
if ($update)
{
$model->save();
}
}
$offset += count($models);
}
while($offset > 0 && $offset < $count);
}
sfConfig::set('sf_logging_enabled', $logging);
}
protected function getFieldTranslationCount(array $fieldTranslations, string $modelClassPeer): int
{
$count = [];
foreach ($fieldTranslations as $translations)
{
$count[] = count($translations);
}
$c = new Criteria();
$this->addThemeCriteria($modelClassPeer, $c);
$entityCount = call_user_func([$modelClassPeer, 'doCount'], $c);
return min(max($count), $entityCount);
}
protected function getModelCriteria(string $modelClass): Criteria
{
$c = new Criteria();
$entity = new $modelClass();
foreach ($entity->getPrimaryKeyFields(BasePeer::TYPE_COLNAME) as $column)
{
$c->addAscendingOrderByColumn($column);
}
$this->addThemeCriteria($modelClass . 'Peer', $c);
return $c;
}
protected function addThemeCriteria(string $modelClassPeer, Criteria $c)
{
$themeIdField = "{$modelClassPeer}::THEME_ID";
if (defined($themeIdField))
{
$c->add(constant($themeIdField), $this->theme->getId());
}
}
}