timestamp_old = REQUEST_TIME - 300; $this->timestamp_medium = REQUEST_TIME - 200; $this->timestamp_new = REQUEST_TIME - 100; $this->timestamp_now = REQUEST_TIME; } /** * Sets the value of the default translations directory. * * @param string $path * Path of the translations directory relative to the drupal installation * directory. */ protected function setTranslationsDirectory($path) { file_prepare_directory($path, FILE_CREATE_DIRECTORY); variable_set('l10n_update_download_store', $path); } /** * Adds a language. * * @param $langcode * The language code of the language to add. */ protected function addLanguage($langcode) { $edit = array('langcode' => $langcode); $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language')); drupal_static_reset('language_list'); $languages = language_list(); $this->assertTrue(isset($languages[$langcode]), format_string('Language %langcode added.', array('%langcode' => $langcode))); } /** * Creates a translation file and tests its timestamp. * * @param string $path * Path of the file relative to the public file path. * @param string $filename * Name of the file to create. * @param integer $timestamp * Timestamp to set the file to. Defaults to current time. * @param array $translations * Array of source/target value translation strings. Only singular strings * are supported, no plurals. No double quotes are allowed in source and * translations strings. */ protected function makePoFile($path, $filename, $timestamp = NULL, $translations = array()) { $timestamp = $timestamp ? $timestamp : REQUEST_TIME; $path = 'public://' . $path; $text = ''; $po_header = << 1);\\n" EOF; // Convert array of translations to Gettext source and translation strings. if ($translations) { foreach ($translations as $source => $target) { $text .= 'msgid "'. $source . '"' . "\n"; $text .= 'msgstr "'. $target . '"' . "\n"; } } file_prepare_directory($path, FILE_CREATE_DIRECTORY); $file = (object) array( 'uid' => 1, 'filename' => $filename, 'uri' => $path . '/' . $filename, 'filemime' => 'text/x-gettext-translation', 'timestamp' => $timestamp, 'status' => FILE_STATUS_PERMANENT, ); file_put_contents($file->uri, $po_header . $text); touch(drupal_realpath($file->uri), $timestamp); file_save($file); } /** * Setup the environment containing local and remote translation files. * * Update tests require a simulated environment for local and remote files. * Normally remote files are located at a remote server (e.g. ftp.drupal.org). * For testing we can not rely on this. A directory in the file system of the * test site is designated for remote files and is addressed using an absolute * URL. Because Drupal does not allow files with a po extension to be accessed * (denied in .htaccess) the translation files get a _po extension. Another * directory is designated for local translation files. * * The environment is set up with the following files. File creation times are * set to create different variations in test conditions. * contrib_module_one * - remote file: timestamp new * - local file: timestamp old * - current: timestamp medium * contrib_module_two * - remote file: timestamp old * - local file: timestamp new * - current: timestamp medium * contrib_module_three * - remote file: timestamp old * - local file: timestamp old * - current: timestamp medium * custom_module_one * - local file: timestamp new * - current: timestamp medium * Time stamp of current translation set by setCurrentTranslations() is always * timestamp medium. This makes it easy to predict which translation will be * imported. */ protected function setTranslationFiles() { // A flag is set to let the l10n_update_test module replace the project data with // a set of test projects which match the below project files. variable_set('l10n_update_test_projects_alter', TRUE); // Setup the environment. $public_path = drupal_realpath('public://'); $this->setTranslationsDirectory($public_path . '/local'); variable_set('l10n_update_default_filename', '%project-%release.%language._po'); // Setting up sets of translations for the translation files. $translations_one = array('January' => 'Januar_1', 'February' => 'Februar_1', 'March' => 'Marz_1'); $translations_two = array( 'February' => 'Februar_2', 'March' => 'Marz_2', 'April' => 'April_2'); $translations_three = array('April' => 'April_3', 'May' => 'Mai_3', 'June' => 'Juni_3'); // Add a number of files to the local file system to serve as remote // translation server and match the project definitions set in // l10n_update_test_l10n_update_projects_alter(). $this->makePoFile('remote/7.x/contrib_module_one', 'contrib_module_one-7.x-1.1.de._po', $this->timestamp_new, $translations_one); $this->makePoFile('remote/7.x/contrib_module_two', 'contrib_module_two-7.x-2.0-beta4.de._po', $this->timestamp_old, $translations_two); $this->makePoFile('remote/7.x/contrib_module_three', 'contrib_module_three-7.x-1.0.de._po', $this->timestamp_old, $translations_three); // Add a number of files to the local file system to serve as local // translation files and match the project definitions set in // l10n_update_test_l10n_update_projects_alter(). $this->makePoFile('local', 'contrib_module_one-7.x-1.1.de._po', $this->timestamp_old, $translations_one); $this->makePoFile('local', 'contrib_module_two-7.x-2.0-beta4.de._po', $this->timestamp_new, $translations_two); $this->makePoFile('local', 'contrib_module_three-7.x-1.0.de._po', $this->timestamp_old, $translations_three); $this->makePoFile('local', 'custom_module_one.de.po', $this->timestamp_new); } /** * Setup existing translations in the database and set up the status of * existing translations. */ protected function setCurrentTranslations() { // Setup to add German translations to the database. $langcode = 'de'; $writer = new PoDatabaseWriter(); $writer->setLangcode($langcode); $writer->setOptions(array( 'overwrite_options' => array( 'not_customized' => TRUE, 'customized' => TRUE, ), )); // Add non customized translations to the database. $writer->setOptions(array('customized' => L10N_UPDATE_NOT_CUSTOMIZED)); $non_customized_translations = array( 'March' => 'Marz', 'June' => 'Juni', ); foreach ($non_customized_translations as $source => $translation) { $poItem = new PoItem(); $poItem->setFromArray(array( 'source' => $source, 'translation' => $translation, )); $writer->writeItem($poItem); } // Add customized translations to the database. $writer->setOptions(array('customized' => L10N_UPDATE_CUSTOMIZED)); $customized_translations = array( 'January' => 'Januar_customized', 'February' => 'Februar_customized', 'May' => 'Mai_customized', ); foreach ($customized_translations as $source => $translation) { $poItem = new PoItem(); $poItem->setFromArray(array( 'source' => $source, 'translation' => $translation, )); $writer->writeItem($poItem); } // Add a state of current translations in l10n_update_files. $default = array( 'language' => $langcode, 'uri' => '', 'timestamp' => $this->timestamp_medium, 'last_checked' => $this->timestamp_medium, ); $data[] = array( 'project' => 'contrib_module_one', 'filename' => 'contrib_module_one-7.x-1.1.de._po', 'version' => '7.x-1.1', ); $data[] = array( 'project' => 'contrib_module_two', 'filename' => 'contrib_module_two-7.x-2.0-beta4.de._po', 'version' => '7.x-2.0-beta4', ); $data[] = array( 'project' => 'contrib_module_three', 'filename' => 'contrib_module_three-7.x-1.0.de._po', 'version' => '7.x-1.0', ); $data[] = array( 'project' => 'custom_module_one', 'filename' => 'custom_module_one.de.po', 'version' => '', ); foreach ($data as $file) { $file = (object) array_merge($default, $file); drupal_write_record('l10n_update_file', $file); } } /** * Checks the translation of a string. * * @param string $source * Translation source string * @param string $translation * Translation to check. Use empty string to check for a not existing * translation. * @param string $langcode * Language code of the language to translate to. * @param string $message * (optional) A message to display with the assertion. */ protected function assertTranslation($source, $translation, $langcode, $message = '') { $db_translation = db_query('SELECT translation FROM {locales_target} lt INNER JOIN {locales_source} ls ON ls.lid = lt.lid WHERE ls.source = :source AND lt.language = :langcode', array(':source' => $source, ':langcode' => $langcode))->fetchField(); $db_translation = $db_translation == FALSE ? '' : $db_translation; $this->assertEqual($translation, $db_translation, $message ? $message : format_string('Correct translation of %source (%language)', array('%source' => $source, '%language' => $langcode))); } }