[I18N] Added ability to call _m_dynamic from any class, allowing it to define translations for dynamic-valued calls to _m

This commit is contained in:
Hugo Sales 2020-06-05 23:04:49 +00:00 committed by Hugo Sales
parent 5be901f9ce
commit 711af58dcd
Signed by: someonewithpc
GPG Key ID: 7D0C7EAFC9D835A0
3 changed files with 68 additions and 15 deletions

View File

@ -32,6 +32,7 @@
namespace App\Core\DB;
use function App\Core\I18n\_m;
use App\Core\I18n\I18nHelper;
use App\Util\Common;
@ -304,4 +305,18 @@ abstract class DefaultSettings
DB::getConnection()->executeQuery($sql);
}
}
public static function _m_dynamic(): array
{
self::setDefaults();
$m = [];
$m['domain'] = 'core';
foreach (self::$defaults as $key => $inner) {
$m[] = _m($key);
foreach (array_keys($inner) as $inner_key) {
$m[] = _m($inner_key);
}
}
return $m;
}
}

View File

@ -47,7 +47,7 @@ abstract class I18nHelper
/**
* Looks for which plugin we've been called from to get the gettext domain;
* if not in a plugin subdirectory, we'll use the default 'Core'.
* if not in a plugin subdirectory, we'll use the default 'core'.
*
* @return string
*/
@ -68,7 +68,7 @@ abstract class I18nHelper
$path = Formatting::normalizePath($path);
$cached[$path] = Formatting::pluginFromPath($path);
}
return $cached[$path] ?? 'Core';
return $cached[$path] ?? 'core';
}
/**

View File

@ -34,6 +34,7 @@
namespace App\Core\I18n;
use App\Util\Formatting;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Translation\Extractor\AbstractFileExtractor;
use Symfony\Component\Translation\Extractor\ExtractorInterface;
@ -51,19 +52,26 @@ class TransExtractor extends AbstractFileExtractor implements ExtractorInterface
* @var array
*/
protected $sequences = [
// [
// '_m',
// '(',
// self::MESSAGE_TOKEN,
// ',',
// self::METHOD_ARGUMENTS_TOKEN,
// ',',
// self::DOMAIN_TOKEN,
// ],
[
'_m',
'(',
self::MESSAGE_TOKEN,
',',
self::METHOD_ARGUMENTS_TOKEN,
',',
self::DOMAIN_TOKEN,
],
[
'_m',
'(',
self::MESSAGE_TOKEN,
// Special case: when we have calls to _m with a dynamic
// value, we need to handle them seperately
'function',
'_m_dynamic',
self::M_DYNAMIC,
],
];
@ -72,6 +80,7 @@ class TransExtractor extends AbstractFileExtractor implements ExtractorInterface
const MESSAGE_TOKEN = 300;
const METHOD_ARGUMENTS_TOKEN = 1000;
const DOMAIN_TOKEN = 1001;
const M_DYNAMIC = 1002;
/**
* Prefix for new found message.
@ -258,22 +267,51 @@ class TransExtractor extends AbstractFileExtractor implements ExtractorInterface
if ('' !== $domainToken) {
$domain = $domainToken;
}
break;
} elseif (self::M_DYNAMIC === $item) {
// Special case
self::storeDynamic($catalog, $filename);
} else {
break;
}
}
if ($message) {
$catalog->set($message, $this->prefix . $message, $domain);
$metadata = $catalog->getMetadata($message, $domain) ?? [];
$normalizedFilename = preg_replace('{[\\\\/]+}', '/', $filename);
$metadata['sources'][] = $normalizedFilename . ':' . $tokens[$key][2];
$catalog->setMetadata($message, $metadata, $domain);
self::store($catalog, $message, $domain, $filename, $tokens[$key][2]); // Line no.
break;
}
}
}
}
private function store(MessageCatalogue $mc, string $message,
string $domain, string $filename, ?int $line_no = null)
{
$mc->set($message, $this->prefix . $message, $domain);
$metadata = $mc->getMetadata($message, $domain) ?? [];
$metadata['sources'][] = Formatting::normalizePath($filename) . (!empty($line_no) ? ":{$line_no}" : '');
$mc->setMetadata($message, $metadata, $domain);
}
private function storeDynamic(MessageCatalogue $mc, string $filename)
{
require_once $filename;
$class = preg_replace('/.*\/([A-Za-z]*)\.php/', '\1', $filename);
$classes = get_declared_classes();
// Find FQCN of $class
foreach ($classes as $c) {
if (strstr($c, $class) !== false) {
$class = $c;
break;
}
}
$messages = $class::_m_dynamic();
$domain = $messages['domain'];
unset($messages['domain']);
foreach ($messages as $m) {
self::store($mc, $m, $domain, $filename);
}
}
}