Loading l10n_community/l10n_community.services.yml +3 −0 Original line number Diff line number Diff line Loading @@ -8,3 +8,6 @@ services: l10n_community.access: class: Drupal\l10n_community\L10nAccess arguments: ['@current_route_match', '@module_handler'] l10n_community.translator: class: Drupal\l10n_community\L10nTranslator arguments: ['@database'] l10n_community/src/L10nTranslator.php 0 → 100644 +199 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); namespace Drupal\l10n_community; use Drupal\Core\Database\Connection; use Drupal\Core\Database\Query\Condition; /** * Service description. */ class L10nTranslator { /** * The database connection. * * @var \Drupal\Core\Database\Connection */ protected Connection $connection; /** * Constructs a L10nTranslator object. * * @param \Drupal\Core\Database\Connection $connection * The database connection. */ public function __construct( Connection $connection ) { $this->connection = $connection; } /** * Get strings under some conditions. * * @param string $langcode * Language code to use for the lookup. * @param array $filters * - 'project' * Project object to look up strings for. * - 'status' * Filter strings by status. See L10N_STATUS_ALL, * L10N_STATUS_UNTRANSLATED, L10N_STATUS_HAS_SUGGESTION and * L10N_STATUS_TRANSLATED. * - 'release' * Release id of the particular project release to filter with. * Use NULL to not filter on releases. * - 'search' * Substring to search for in all source and translation strings. * - 'context' * From Drupal 7, separate contexts are supported. POTX_CONTEXT_NONE is * the default, if the code does not specify a context otherwise. * @param int|null $pager * Number of strings to be returned in a pager. Should be NULL if * no pager should be used. * * @return array * An array of string records from database. */ function getStrings(string $langcode, array $filters, int $pager = NULL): array { $query = $this->connection ->select('l10n_server_string', 's') ->distinct(); $query ->leftJoin('l10n_server_status_flag', 'ts', 's.sid = ts.sid AND ts.language = :language', [ ':language' => $langcode, ]); $query ->leftJoin('l10n_server_translation', 't', 'ts.sid = t.sid AND ts.language = t.language AND t.status = 1'); $query ->leftJoin('users_field_data', 'u', 'u.uid = t.uid'); $query ->fields('s', ['sid', 'value', 'context']) ->fields('t', [ 'tid', 'language', 'translation', 'uid', 'created', 'changed', 'suggestion', 'status', ]) ->fields('ts', ['has_suggestion', 'has_translation']); $query ->addField('u', 'name', 'username'); // Add sid filtering. if (!empty($filters['sid'])) { $query->condition('s.sid', $filters['sid']); } // Add submitted by condition if (!empty($filters['author'])) { $query->condition('t.uid', $filters['author']->id()); } // Release restriction. $release = empty($filters['release']) || $filters['release'] === 'all' ? NULL : $filters['release']; $project = $filters['project']; if ($release || $project) { $query->innerJoin('l10n_server_line', 'l', 's.sid = l.sid'); // If we have a release we ignore the project. if ($release) { // Release restriction. $query->condition('l.rid', $release); } elseif ($project) { $query->condition('l.pid', $project->pid); } } // Context based filtering. if (isset($filters['context']) && $filters['context'] != 'all') { // We use 'none' for no context, so '' can be the defaut (for all contexts). $context = $filters['context'] == 'none' ? '' : $filters['context']; $query->condition('s.context', $context); } if (!empty($filters['search'])) { // Search in the source or target strings. $search = $filters['search']; $query->condition((new Condition('OR')) ->condition('s.value', '%' . db_like($search) . '%', 'LIKE') ->condition('t.translation', '%' . db_like($search) . '%', 'LIKE') ); } // Restriction based on string status by translation / suggestions. if (isset($filters['status'])) { if ($filters['status'] & L10N_STATUS_UNTRANSLATED) { $query->condition((new Condition('OR')) ->condition('ts.has_translation', 0) ->isNull('ts.has_translation') ); } elseif ($filters['status'] & L10N_STATUS_TRANSLATED) { $query->condition('ts.has_translation', '1'); } elseif ($filters['status'] & L10N_STATUS_IS_TRANSLATION) { $query->condition('t.is_suggestion', '0'); } if ($filters['status'] & L10N_STATUS_HAS_SUGGESTION) { $query->condition('ts.has_suggestion', '1'); } elseif ($filters['status'] & L10N_STATUS_NO_SUGGESTION) { $query->condition((new Condition('OR')) ->condition('ts.has_suggestion', 0) ->isNull('ts.has_suggestion') ); } elseif ($filters['status'] & L10N_STATUS_IS_SUGGESTION) { $query->condition('t.is_suggestion', '1'); } } // We either need a pager or a full result. if (isset($pager)) { $strings = $query ->extend('Drupal\Core\Database\Query\PagerSelectExtender') ->limit($pager) ->execute(); } else { $strings = $query->execute(); } $result = []; foreach ($strings as $string) { if ($string->suggestion) { // This string is not a translation, but we need that as a "parent" to display. if (!$string->has_translation) { // No parent translation. Pretend this does not exist. // The display code will call for the suggestions. $string->translation = ''; } else { $q = $this->connection ->select('l10n_server_translation', 't'); $q->leftJoin('users', 'u', 'u.uid = t.uid'); $q->fields('t', [ 'tid', 'translation', 'uid', 'created', 'changed', 'suggestion', 'status', ]); $q->addField('u', 'name', 'username'); $q->condition('t.language', $string->language) ->condition('t.sid', $string->sid) ->condition('t.status', 1) ->condition('t.suggestion', 0); $translation = $q ->execute() ->fetchAssoc(); if (!empty($translation)) { // It does have a translation however, so let's load it, and override. foreach ($translation as $key => $value) { $string->$key = $value; } } } } $result[] = $string; } return $result; } } Loading
l10n_community/l10n_community.services.yml +3 −0 Original line number Diff line number Diff line Loading @@ -8,3 +8,6 @@ services: l10n_community.access: class: Drupal\l10n_community\L10nAccess arguments: ['@current_route_match', '@module_handler'] l10n_community.translator: class: Drupal\l10n_community\L10nTranslator arguments: ['@database']
l10n_community/src/L10nTranslator.php 0 → 100644 +199 −0 Original line number Diff line number Diff line <?php declare(strict_types=1); namespace Drupal\l10n_community; use Drupal\Core\Database\Connection; use Drupal\Core\Database\Query\Condition; /** * Service description. */ class L10nTranslator { /** * The database connection. * * @var \Drupal\Core\Database\Connection */ protected Connection $connection; /** * Constructs a L10nTranslator object. * * @param \Drupal\Core\Database\Connection $connection * The database connection. */ public function __construct( Connection $connection ) { $this->connection = $connection; } /** * Get strings under some conditions. * * @param string $langcode * Language code to use for the lookup. * @param array $filters * - 'project' * Project object to look up strings for. * - 'status' * Filter strings by status. See L10N_STATUS_ALL, * L10N_STATUS_UNTRANSLATED, L10N_STATUS_HAS_SUGGESTION and * L10N_STATUS_TRANSLATED. * - 'release' * Release id of the particular project release to filter with. * Use NULL to not filter on releases. * - 'search' * Substring to search for in all source and translation strings. * - 'context' * From Drupal 7, separate contexts are supported. POTX_CONTEXT_NONE is * the default, if the code does not specify a context otherwise. * @param int|null $pager * Number of strings to be returned in a pager. Should be NULL if * no pager should be used. * * @return array * An array of string records from database. */ function getStrings(string $langcode, array $filters, int $pager = NULL): array { $query = $this->connection ->select('l10n_server_string', 's') ->distinct(); $query ->leftJoin('l10n_server_status_flag', 'ts', 's.sid = ts.sid AND ts.language = :language', [ ':language' => $langcode, ]); $query ->leftJoin('l10n_server_translation', 't', 'ts.sid = t.sid AND ts.language = t.language AND t.status = 1'); $query ->leftJoin('users_field_data', 'u', 'u.uid = t.uid'); $query ->fields('s', ['sid', 'value', 'context']) ->fields('t', [ 'tid', 'language', 'translation', 'uid', 'created', 'changed', 'suggestion', 'status', ]) ->fields('ts', ['has_suggestion', 'has_translation']); $query ->addField('u', 'name', 'username'); // Add sid filtering. if (!empty($filters['sid'])) { $query->condition('s.sid', $filters['sid']); } // Add submitted by condition if (!empty($filters['author'])) { $query->condition('t.uid', $filters['author']->id()); } // Release restriction. $release = empty($filters['release']) || $filters['release'] === 'all' ? NULL : $filters['release']; $project = $filters['project']; if ($release || $project) { $query->innerJoin('l10n_server_line', 'l', 's.sid = l.sid'); // If we have a release we ignore the project. if ($release) { // Release restriction. $query->condition('l.rid', $release); } elseif ($project) { $query->condition('l.pid', $project->pid); } } // Context based filtering. if (isset($filters['context']) && $filters['context'] != 'all') { // We use 'none' for no context, so '' can be the defaut (for all contexts). $context = $filters['context'] == 'none' ? '' : $filters['context']; $query->condition('s.context', $context); } if (!empty($filters['search'])) { // Search in the source or target strings. $search = $filters['search']; $query->condition((new Condition('OR')) ->condition('s.value', '%' . db_like($search) . '%', 'LIKE') ->condition('t.translation', '%' . db_like($search) . '%', 'LIKE') ); } // Restriction based on string status by translation / suggestions. if (isset($filters['status'])) { if ($filters['status'] & L10N_STATUS_UNTRANSLATED) { $query->condition((new Condition('OR')) ->condition('ts.has_translation', 0) ->isNull('ts.has_translation') ); } elseif ($filters['status'] & L10N_STATUS_TRANSLATED) { $query->condition('ts.has_translation', '1'); } elseif ($filters['status'] & L10N_STATUS_IS_TRANSLATION) { $query->condition('t.is_suggestion', '0'); } if ($filters['status'] & L10N_STATUS_HAS_SUGGESTION) { $query->condition('ts.has_suggestion', '1'); } elseif ($filters['status'] & L10N_STATUS_NO_SUGGESTION) { $query->condition((new Condition('OR')) ->condition('ts.has_suggestion', 0) ->isNull('ts.has_suggestion') ); } elseif ($filters['status'] & L10N_STATUS_IS_SUGGESTION) { $query->condition('t.is_suggestion', '1'); } } // We either need a pager or a full result. if (isset($pager)) { $strings = $query ->extend('Drupal\Core\Database\Query\PagerSelectExtender') ->limit($pager) ->execute(); } else { $strings = $query->execute(); } $result = []; foreach ($strings as $string) { if ($string->suggestion) { // This string is not a translation, but we need that as a "parent" to display. if (!$string->has_translation) { // No parent translation. Pretend this does not exist. // The display code will call for the suggestions. $string->translation = ''; } else { $q = $this->connection ->select('l10n_server_translation', 't'); $q->leftJoin('users', 'u', 'u.uid = t.uid'); $q->fields('t', [ 'tid', 'translation', 'uid', 'created', 'changed', 'suggestion', 'status', ]); $q->addField('u', 'name', 'username'); $q->condition('t.language', $string->language) ->condition('t.sid', $string->sid) ->condition('t.status', 1) ->condition('t.suggestion', 0); $translation = $q ->execute() ->fetchAssoc(); if (!empty($translation)) { // It does have a translation however, so let's load it, and override. foreach ($translation as $key => $value) { $string->$key = $value; } } } } $result[] = $string; } return $result; } }