Issue #2575945 by Sutharsan, mstrelan, tobiasb, ranjith_kumar_k_u, andypost, ericdsd, smustgrave, Ammaletu: A new module version is not recognized by interface translation update
parent
3e49eeb716
commit
9e290d8cc7
|
@ -23,6 +23,43 @@ use Psr\Http\Message\UriInterface;
|
||||||
// Follow-up issue: https://www.drupal.org/node/1834298.
|
// Follow-up issue: https://www.drupal.org/node/1834298.
|
||||||
require_once __DIR__ . '/locale.translation.inc';
|
require_once __DIR__ . '/locale.translation.inc';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements callback_batch_operation().
|
||||||
|
*
|
||||||
|
* Checks for changed project versions, and cleans-up data from the old version.
|
||||||
|
* For example when a module is updated. This will make the translation import
|
||||||
|
* system use translations that match the current version.
|
||||||
|
*
|
||||||
|
* @param string $project
|
||||||
|
* Machine name of the project for which to check the translation status.
|
||||||
|
* @param string $langcode
|
||||||
|
* Language code of the language for which to check the translation.
|
||||||
|
* @param array|\ArrayAccess $context
|
||||||
|
* The batch context.
|
||||||
|
*/
|
||||||
|
function locale_translation_batch_version_check(string $project, string $langcode, array|\ArrayAccess &$context) {
|
||||||
|
$locale_project = \Drupal::service('locale.project')->get($project);
|
||||||
|
|
||||||
|
if (empty($locale_project)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = \Drupal::keyValue('locale.translation_status')->get($project);
|
||||||
|
if (!isset($status[$langcode])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($locale_project['version'] == $status[$langcode]->version) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
\Drupal::moduleHandler()->loadInclude('locale', 'bulk.inc');
|
||||||
|
locale_translation_status_delete_projects([$project]);
|
||||||
|
locale_translate_delete_translation_files([$project]);
|
||||||
|
|
||||||
|
$context['message'] = t('Checked version of %project.', ['%project' => $project]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements callback_batch_operation().
|
* Implements callback_batch_operation().
|
||||||
*
|
*
|
||||||
|
|
|
@ -267,7 +267,8 @@ function _locale_translation_batch_status_operations($projects, $langcodes, $opt
|
||||||
|
|
||||||
foreach ($projects as $project) {
|
foreach ($projects as $project) {
|
||||||
foreach ($langcodes as $langcode) {
|
foreach ($langcodes as $langcode) {
|
||||||
// Check status of local and remote translation sources.
|
// Check version and status translation sources.
|
||||||
|
$operations[] = ['locale_translation_batch_version_check', [$project, $langcode]];
|
||||||
$operations[] = ['locale_translation_batch_status_check', [$project, $langcode, $options]];
|
$operations[] = ['locale_translation_batch_status_check', [$project, $langcode, $options]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Drupal\Tests\locale\Functional;
|
||||||
|
|
||||||
|
use Drupal\Core\StreamWrapper\PublicStream;
|
||||||
|
use Drupal\language\Entity\ConfigurableLanguage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests how translations are handled when a project gets updated.
|
||||||
|
*
|
||||||
|
* @group locale
|
||||||
|
*/
|
||||||
|
class LocaleTranslationChangeProjectVersionTest extends LocaleUpdateBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected $defaultTheme = 'stark';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function setUp(): void {
|
||||||
|
parent::setUp();
|
||||||
|
\Drupal::moduleHandler()->loadInclude('locale', 'inc', 'locale.batch');
|
||||||
|
ConfigurableLanguage::createFromLangcode('de')->save();
|
||||||
|
|
||||||
|
\Drupal::state()->set('locale.test_projects_alter', TRUE);
|
||||||
|
\Drupal::state()->set('locale.remove_core_project', TRUE);
|
||||||
|
|
||||||
|
// Setup the environment.
|
||||||
|
$config = $this->config('locale.settings');
|
||||||
|
$public_path = PublicStream::basePath();
|
||||||
|
$this->setTranslationsDirectory($public_path . '/local');
|
||||||
|
$config
|
||||||
|
->set('translation.default_filename', '%project-%version.%language._po')
|
||||||
|
->set('translation.use_source', LOCALE_TRANSLATION_USE_SOURCE_LOCAL)
|
||||||
|
->save();
|
||||||
|
|
||||||
|
// This test uses .po files for the old translation file instead of the ._po
|
||||||
|
// files because locale_translate_get_interface_translation_files() (used to
|
||||||
|
// delete old translation files) only works with .po files.
|
||||||
|
// The new translation file uses _po.
|
||||||
|
// Old version: 8.x-1.0; New version: 8.x-1.1.
|
||||||
|
$this->makePoFile('remote/all/contrib_module_one', 'contrib_module_one-8.x-1.0.de.po', $this->timestampOld, []);
|
||||||
|
$this->makePoFile('remote/all/contrib_module_one', 'contrib_module_one-8.x-1.1.de._po', $this->timestampNew, []);
|
||||||
|
$this->makePoFile('local', 'contrib_module_one-8.x-1.0.de.po', $this->timestampOld, []);
|
||||||
|
|
||||||
|
// Initialize the projects status and change the project version to the old
|
||||||
|
// version. This makes the code update the module translation to the new
|
||||||
|
// version when the (batch) update script is triggered.
|
||||||
|
$status = locale_translation_get_status();
|
||||||
|
$status['contrib_module_one']['de']->version = '8.x-1.0';
|
||||||
|
\Drupal::keyValue('locale.translation_status')->setMultiple($status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests update translations when project version changes.
|
||||||
|
*/
|
||||||
|
public function testUpdateImportSourceRemote() {
|
||||||
|
|
||||||
|
// Verify that the project status has the old version.
|
||||||
|
$status = locale_translation_get_status(['contrib_module_one']);
|
||||||
|
$this->assertEquals('8.x-1.0', $status['contrib_module_one']['de']->version);
|
||||||
|
|
||||||
|
// Verify that the old translation file exists and the new does not exist.
|
||||||
|
$this->assertFileExists('translations://contrib_module_one-8.x-1.0.de.po');
|
||||||
|
$this->assertFileDoesNotExist('translations://contrib_module_one-8.x-1.1.de._po');
|
||||||
|
|
||||||
|
// Run batch tasks.
|
||||||
|
$context = [];
|
||||||
|
locale_translation_batch_version_check('contrib_module_one', 'de', $context);
|
||||||
|
locale_translation_batch_status_check('contrib_module_one', 'de', [], $context);
|
||||||
|
locale_translation_batch_fetch_download('contrib_module_one', 'de', $context);
|
||||||
|
|
||||||
|
// Verify that the project status has the new version.
|
||||||
|
$status = locale_translation_get_status(['contrib_module_one']);
|
||||||
|
$this->assertEquals('8.x-1.1', $status['contrib_module_one']['de']->version);
|
||||||
|
|
||||||
|
// Verify that the old translation file was removed and the new was
|
||||||
|
// downloaded.
|
||||||
|
$this->assertFileDoesNotExist('translations://contrib_module_one-8.x-1.0.de.po');
|
||||||
|
$this->assertFileExists('translations://contrib_module_one-8.x-1.1.de._po');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -135,10 +135,11 @@ EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
\Drupal::service('file_system')->prepareDirectory($path, FileSystemInterface::CREATE_DIRECTORY);
|
\Drupal::service('file_system')->prepareDirectory($path, FileSystemInterface::CREATE_DIRECTORY);
|
||||||
|
$fileUri = $path . '/' . $filename;
|
||||||
$file = File::create([
|
$file = File::create([
|
||||||
'uid' => 1,
|
'uid' => 1,
|
||||||
'filename' => $filename,
|
'filename' => $filename,
|
||||||
'uri' => $path . '/' . $filename,
|
'uri' => $fileUri,
|
||||||
'filemime' => 'text/x-gettext-translation',
|
'filemime' => 'text/x-gettext-translation',
|
||||||
'timestamp' => $timestamp,
|
'timestamp' => $timestamp,
|
||||||
]);
|
]);
|
||||||
|
@ -146,6 +147,9 @@ EOF;
|
||||||
file_put_contents($file->getFileUri(), $po_header . $text);
|
file_put_contents($file->getFileUri(), $po_header . $text);
|
||||||
touch(\Drupal::service('file_system')->realpath($file->getFileUri()), $timestamp);
|
touch(\Drupal::service('file_system')->realpath($file->getFileUri()), $timestamp);
|
||||||
$file->save();
|
$file->save();
|
||||||
|
|
||||||
|
$this->assertTrue(file_exists($fileUri));
|
||||||
|
$this->assertEquals($timestamp, filemtime($fileUri));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -98,8 +98,12 @@ class LocaleUpdateCronTest extends LocaleUpdateBase {
|
||||||
locale_cron();
|
locale_cron();
|
||||||
|
|
||||||
// Check whether tasks are added to the queue.
|
// Check whether tasks are added to the queue.
|
||||||
|
// Expected tasks:
|
||||||
|
// - locale_translation_batch_version_check
|
||||||
|
// - locale_translation_batch_status_check
|
||||||
|
// - locale_translation_batch_status_finished.
|
||||||
$queue = \Drupal::queue('locale_translation', TRUE);
|
$queue = \Drupal::queue('locale_translation', TRUE);
|
||||||
$this->assertEquals(2, $queue->numberOfItems(), 'Queue holds tasks for one project.');
|
$this->assertEquals(3, $queue->numberOfItems(), 'Queue holds tasks for one project.');
|
||||||
$item = $queue->claimItem();
|
$item = $queue->claimItem();
|
||||||
$queue->releaseItem($item);
|
$queue->releaseItem($item);
|
||||||
$this->assertEquals('contrib_module_two', $item->data[1][0], 'Queue holds tasks for contrib module one.');
|
$this->assertEquals('contrib_module_two', $item->data[1][0], 'Queue holds tasks for contrib module one.');
|
||||||
|
@ -110,7 +114,7 @@ class LocaleUpdateCronTest extends LocaleUpdateBase {
|
||||||
|
|
||||||
// Check whether no more tasks are added to the queue.
|
// Check whether no more tasks are added to the queue.
|
||||||
$queue = \Drupal::queue('locale_translation', TRUE);
|
$queue = \Drupal::queue('locale_translation', TRUE);
|
||||||
$this->assertEquals(2, $queue->numberOfItems(), 'Queue holds tasks for one project.');
|
$this->assertEquals(3, $queue->numberOfItems(), 'Queue holds tasks for one project.');
|
||||||
|
|
||||||
// Ensure last checked is updated to a greater time than the initial value.
|
// Ensure last checked is updated to a greater time than the initial value.
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
Loading…
Reference in New Issue