diff --git a/core/modules/locale/locale.api.php b/core/modules/locale/locale.api.php index e073630..81a8a6b 100644 --- a/core/modules/locale/locale.api.php +++ b/core/modules/locale/locale.api.php @@ -14,17 +14,11 @@ * Alter the list of projects to be updated by locale's interface translation. * * Locale module attempts to update the translation of those modules returned - * by update_get_projects(). Using this hook this data can be altered or - * extended. - * - * Custom modules can be added using this hook to let Locale module import - * the translations. This can be used a part of a translation staging solution. + * by update_get_projects(). Using this hook the data returned by + * update_get_projects() can be altered or extended. * * Modules or distributions that use a dedicated translation server should use * this hook to specify the translation sever parameters. These parameters are: - * - "interface translation server": server name for the user interface. - * - "interface translation server url": URL of the xml file containing - * tranlation server parameters. * - "interface translation server pattern": URL of the .po translation files * used to download the files from. The URL contains tokens which will be * replaced by appropriate values. @@ -40,18 +34,24 @@ * @see locale_project_list(). */ function hook_locale_translation_projects_alter(&$projects) { - // Use of a custom translation sever. - $projects['existing_example_project'] = array( + // The translations are located at a custom translation sever. + $projects['existing_project'] = array( 'info' => array( - 'interface translation server' => 'example.com', - 'interface translation server url' => 'http://example.com/files/translations/l10n_server.xml', 'interface translation server pattern' => 'http://example.com/files/translations/%core/%project/%project-%release.%language.po', ), ); } +function hook_locale_translation_translation_servers() { + +} + +/** + * @} End of "addtogroup hooks". + */ + /** - * Allows to define or alter project definitions for interface translation. + * .info file properties for interface translation settings. * * Modules hosted on drupal.org, a project definition is automatically added to * the .info file. Only modules with this project defintion are discovered by @@ -63,90 +63,48 @@ function hook_locale_translation_projects_alter(&$projects) { * * Custom module which contain new strings should provide po file(s) containing * source strings and string translations in gettext format. The translation - * file can be located both local and remote. The following defintion is - * required by the Locale module to recognize and import the translations. - * Example: - * @code - * // Po file located in local file system. - * $projects['example_module'] = array( - * 'type' => 'module', - * 'info' => array( - * 'project' => 'example_module', - * 'interface translation server pattern' => 'sites/example.com/modules/custom/example_module/%project-%version.%language.po', - * ), - * ); + * file can be located both local and remote. Use the following .info file + * properties to inform Locale module to load and import the translations. * - * // Po file located at a remote translation server. - * $projects['example_module'] = array( - * 'type' => 'module', - * 'info' => array( - * 'project' => 'example_module', - * 'interface translation server' => 'example.com', - * 'interface translation server url' => 'http://example.com/files/translations/l10n_server.xml', - * 'interface translation server pattern' => 'http://example.com/files/translations/%core/%project/%project-%version.%language.po', - * ), - * ); + * Example .info file properties for a custom module with a po file located in + * the module's folder. + * @code + * interface translation project = example_module + * interface translation server pattern = sites/example.com/modules/custom/example_module/%project-%version.%language.po * @endcode * - * Multiple custom modules sharing the same po file should have matching - * definitions. Such as modules and sub-modules or multiple modules in the same - * project/code tree. Both "project", "version" and "interface translation - * server" definitions should match. + * Multiple custom modules or themes sharing the same po file should have + * matching definitions. Such as modules and sub-modules or multiple modules in + * the same project/code tree. Both "interface translation project" and + * "interface translation server pattern" definitions of these modules should match. + * + * Example .info file properties for a custom module with a po file located on + * a remote translation server. * @code - * $projects['other_example_module'] = array( - * 'type' => 'module', - * 'info' => array( - * 'project' => 'example_module', - * 'version' => '1.1', - * 'interface translation server pattern' => 'sites/example.com/modules/custom/example_module/%project-%version.%language.po', - * ), - * ); + * interface translation project = example_module + * interface translation server pattern = http://example.com/files/translations/%core/%project/%project-%version.%language.po * @endcode * - * The following parameters are available: - * - "project": project or module name of the module. Required. - * - "interface translation server": server name for the user interface. - * - "interface translation server url": URL of the xml file containing - * tranlation server parameters. + * Custom themes, features and distributions can implement these .info file + * properties in their .info file too. + * + * To change the interface translation settings of modules and themes hosted at + * drupal.org use hook_locale_translation_projects_alter(). Possible changes + * include changing the po file location (server pattern) or removing the + * project from the translation update list. + * + * Available .info file properties: + * - "interface translation project": project name. Required. + * Name of the project a (sub-)module belongs to. Multiple modules sharing + * the same project name will be listed as one the translation status list. * - "interface translation server pattern": URL of the .po translation files * used to download the files from. The URL contains tokens which will be - * replaced by appropriate values. + * replaced by appropriate values. The file can be locate both at a local + * relateve path, a local absolute path and a remote server location. + * * The following tokens are available for the server pattern: * - "%core": Core version. Value example: "8.x". * - "%project": Project name. Value examples: "drupal", "media_gallery". - * - "%release": Project version release. Value examples: "8.1", "8.x-1.0". + * - "%version": Project version release. Value examples: "8.1", "8.x-1.0". * - "%language": Language code. Value examples: "fr", "pt-pt". - * - * Themes can implement this hook too in their template.php file. - * - * @return - * Array of project defintions. - */ -function hook_locale_translation_additional_project_info() { - // Custom module with translation on a remote translation server. - $projects['example_module'] = array( - 'type' => 'module', - 'info' => array( - 'project' => 'example_module', - 'interface translation server' => 'example.com', - 'interface translation server url' => 'http://example.com/files/translations/l10n_server.xml', - 'interface translation server pattern' => 'http://example.com/files/translations/%core/%project/%project-%version.%language.po', - ), - ); - - // Custom theme with translation on a remote translation server. - $projects['example_theme'] = array( - 'type' => 'theme', - 'info' => array( - 'interface translation server' => 'example.com', - 'interface translation server url' => 'http://example.com/files/translations/l10n_server.xml', - 'interface translation server pattern' => 'http://example.com/files/translations/%core/%project/%project-%version.%language.po', - ), - ); - - return $projects; -} - -/** - * @} End of "addtogroup hooks". */ diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc index 670136a..56b701a 100644 --- a/core/modules/locale/locale.compare.inc +++ b/core/modules/locale/locale.compare.inc @@ -6,20 +6,6 @@ */ /** - * Default translation server name. - * - * @see locale_translation_default_translation_server(). - */ -const LOCALE_TRANSLATION_DEFAULT_SERVER = "localize.drupal.org"; - -/** - * Default location of xml available language list on the translation server. - * - * @see locale_translation_default_translation_server(). - */ -const LOCALE_TRANSLATION_DEFAULT_SERVER_URL = 'http://localize.drupal.org/l10n_server.xml'; - -/** * Default location of gettext file on the translation server. * * @see locale_translation_default_translation_server(). @@ -30,6 +16,21 @@ use Drupal\Core\Cache; /** * Get array of projects which are available for interface translation. + * + * This project data contains all projects which will be checked for available + * interface translations. + * + * For full functionality this function depends on Update module. + * When Update module is enabled the project data will contain the most recent + * module status; both in enabled status as in version. When Update module is + * disabled this function will return the last known module state. The status + * will only be updated once Update module is enabled. + * + * @see locale_translation_build_projects(). + * + * @return array + * Array of project data for translation update. See + * locale_translation_build_projects() for details. */ function locale_translation_get_projects() { $projects = &drupal_static(__FUNCTION__, array()); @@ -39,7 +40,7 @@ function locale_translation_get_projects() { $projects = array(); $result = db_query('SELECT * FROM {locale_project}'); - if ($result->rowCount() == 0) { + if ($result->rowCount() == 0 && module_exists('update')) { // At least the core project should be in the database, so we build the // data if none are found. locale_translation_build_projects(); @@ -62,6 +63,22 @@ function locale_translation_flush_projects() { /** * Builds list of projects and stores the result in the database. + * + * The project data is based on the project list supplied by the Update module. + * Only the properties required by Locale module is included and additional + * (custom) modules and translation server data is added. + * + * In case the Update module is disabled this function will return an empty + * array. + * + * @return array + * Array of project data: + * - "name": Project system name. + * - "project_type": Project type, e.g. 'module', 'theme'. + * - "core": Core release version, e.g. 8.x + * - "version": Project release version, e.g. 8.x-1.0 + * - "server_pattern": Translation server po file pattern. + * - "status": Project status, 1 = enabled. */ function locale_translation_build_projects() { // This function depends on Update module. We degrade gracefully. @@ -114,32 +131,12 @@ function locale_translation_build_projects() { $data += array( 'version' => isset($data['info']['version']) ? $data['info']['version'] : '', 'core' => isset($data['info']['core']) ? $data['info']['core'] : DRUPAL_CORE_COMPATIBILITY, - // The project can have its own interface translation server, we use - // default if not. - 'server' => isset($data['info']['interface translation server']) ? $data['info']['interface translation server'] : '', - // A project can provide the server url to fetch metadata, or the path and - // filename pattern to download the gettext file. - 'server_url' => isset($data['info']['interface translation server url']) ? $data['info']['interface translation server url'] : '', - 'server_pattern' => isset($data['info']['interface translation server pattern']) ? $data['info']['interface translation server pattern'] : '', + // A project can provide the path and filename pattern to download the + // gettext file. Use the default if not. + 'server_pattern' => isset($data['info']['interface translation server pattern']) ? $data['info']['interface translation server pattern'] : $default_server['pattern'], 'status' => $data['project_status'] ? 1 : 0, ); $project = (object) $data; - // Unless the project provides a full filename pattern, we try to build one. - if (!isset($project->server_pattern)) { - $server = NULL; - if ($project->server || $project->server_url) { - $server = locale_translation_translation_server($project->server, $project->server_url); - } - else { - // Use the default server. - $server = locale_translation_translation_server($default_server['server'], $default_server['server_url']); - } - if ($server) { - // Build the update path for this project, with project name and release - // replaced. - $project->server_pattern = locale_translation_build_server_pattern($project, $server['update_url']); - } - } $projects[$name] = $project; // Create or update the project record. @@ -150,8 +147,6 @@ function locale_translation_build_projects() { 'project_type' => $project->project_type, 'core' => $project->core, 'version' => $project->version, - 'server' => $project->server, - 'server_url' => $project->server_url, 'server_pattern' => $project->server_pattern, 'status' => $project->status, )) @@ -178,10 +173,8 @@ function locale_translation_project_list() { $projects = array(); $additional_whitelist = array( - 'interface translation server', - 'interface translation server url', - 'interface translation server pattern', 'interface translation project', + 'interface translation server pattern', ); $module_data = _locale_translation_prepare_project_list(system_rebuild_module_data(), 'module'); $theme_data = _locale_translation_prepare_project_list(system_rebuild_theme_data(), 'theme'); @@ -218,160 +211,35 @@ function locale_translation_project_list() { * Array of .info file data. */ function _locale_translation_prepare_project_list($data, $type) { - $default = array( - 'name' => '', - 'description' => '', - 'type' => '', - 'version' => '', - 'core' => '', - 'status' => '0', - ); - - $projects = locale_translation_get_additional_projects(); - // Merge and add additional project data into the system data. - foreach ($projects as $name => $project) { - if ($type == $project['type']) { - if (isset($data[$name])) { - $data[$name] = (object)array_merge($project, (array)$data[$name]); - $data[$name]->info = array_merge($project['info'], $data[$name]->info); - } - else { - $default['status'] = module_exists($name) ? '1' : '0'; - $data[$name] = (object)array_merge($default, $project); - $data[$name]->info = $project['info']; - } + foreach ($data as $name => $file) { + // Include interface translation projects. + // Custom modules can bring their own gettext translation file. + // To enable import of this file the module must define + // 'interface translation project = myproject' in its .info file. + // To allow update_process_info_list() to identify this as a project + // the 'project' property is filled with the 'interface translation project' + // value. + if (isset($file->info['interface translation project'])) { + $data[$name]->info['project'] = $file->info['interface translation project']; } } return $data; } /** - * Fetch additional project definitions and definition overrides. - * - * @return array - * Array of custom projects. - * - * @see hook_locale_translation_additional_project_info(). - */ -function locale_translation_get_additional_projects() { - $projects = &drupal_static(__FUNCTION__, array()); - - if (empty($projects)) { - $hook = 'locale_translation_additional_project_info'; - - // Call hook_locale_translation_additional_project_info for modules. - $projects = module_invoke_all($hook); - - // Call hook_locale_translation_additional_project_info for themes. - foreach (list_themes() as $theme => $info) { - $path = drupal_get_path('theme', $theme) . '/template.php'; - if (is_file($path)) { - include_once $path; - $function = $theme . '_' . $hook; - if (function_exists($function)) { - $projects += $function(); - } - } - } - } - - return $projects; -} - -/** * Retrieve data for default server. * * @return array * Array of server parameters: - * - "server": Localization server name - * - "server_url": Localization server URL where language list can be - * retrieved. * - "server_pattern": URL containing po file pattern. */ -// @todo: Rework the individual vars to a hook_locale_translation_server_info() with sets of server definitions? function locale_translation_default_translation_server() { return array( - 'server' => variable_get('locale_translation_default_server', LOCALE_TRANSLATION_DEFAULT_SERVER), - 'server_url' => variable_get('locale_translation_default_server_url', LOCALE_TRANSLATION_DEFAULT_SERVER_URL), - 'server_pattern' => variable_get('locale_translation_default_server_pattern', LOCALE_TRANSLATION_DEFAULT_SERVER_PATTERN), + 'pattern' => variable_get('locale_translation_default_server_pattern', LOCALE_TRANSLATION_DEFAULT_SERVER_PATTERN), ); } /** - * Get server information, that can come from different sources. - * - * Possible server sources: - * - From server list provided by modules. They can provide full server - * information or just the URL. - * - From server_url in a project, we'll fetch the latest data from the server. - * - * @param string $name - * Server name e.g. localize.drupal.org - * @param string $url - * Server url - * @param bool $refresh - * TRUE = refresh the server data. - * - * @return array - * Array of server data. - */ -function locale_translation_translation_servers($name = NULL, $url = NULL, $refresh = FALSE) { - $info = &drupal_static(__FUNCTION__, array()); - $server_list = &drupal_static(__FUNCTION__ . ':server_list', array()); - - // Retrieve server list from modules. - if (!isset($server_list) || $refresh) { - $server_list = module_invoke_all('locale_translation_translation_servers'); - } - // We need at least the server url to fetch all the information. - if (!$url && $name && isset($server_list[$name])) { - $url = $server_list[$name]['server_url']; - } - // If we still don't have a URL, cannot find this server, return false. - if (!$url) { - return FALSE; - } - // Cache server information based on the URL, refresh if asked. - $cid = 'interface_translation_server:' . $url; - if ($refresh) { - unset($info); - cache('locale')->delete($cid); - } - if (!isset($info[$url])) { - if ($cache = cache('locale')->get($cid)) { - $info[$url] = $cache->data; - } - else { - module_load_include('fetch.inc', 'locale'); - if ($name && !empty($server_list[$name])) { - // The name is in our list, it can be full data or just an url. - $server = $server_list[$name]; - } - else { - // This may be a new server provided by a module / package. - $server = array('name' => $name, 'server_url' => $url); - // If searching by name, store the name => url mapping. - if ($name) { - $server_list[$name] = $server; - } - } - // Now fetch server meta information form the server itself. - module_load_include('fetch.inc', 'locale'); - if ($server = locale_translation_get_server($server)) { - cache('locale')->set($cid, $server); - $info[$url] = $server; - } - else { - // If no server information, this will be FALSE. We won't search a - // server twice. - $info[$url] = FALSE; - } - } - } - return $info[$url]; -} - -/** * Build path to translation source, out of a server path replacement pattern. * * @param stdClass $project diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index 726f224..ed77dda 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -34,8 +34,6 @@ function locale_uninstall() { variable_del('locale_translation_javascript'); variable_del('locale_translation_test_system_info_alter'); variable_del('locale_translation_check_disabled'); - variable_del('locale_translation_default_server'); - variable_del('locale_translation_default_server_url'); variable_del('locale_translation_default_server_pattern'); // Remove all node type language variables. Node module might have been @@ -193,20 +191,6 @@ function locale_schema() { 'not null' => TRUE, 'default' => '', ), - 'server' => array( - 'description' => 'Translation server for this project. If empty, the default is used.', - 'type' => 'varchar', - 'length' => '255', - 'not null' => TRUE, - 'default' => '', - ), - 'server_url' => array( - 'description' => 'URL of the xml file at the translation server containing all available languages.', - 'type' => 'varchar', - 'length' => '255', - 'not null' => TRUE, - 'default' => '', - ), 'server_pattern' => array( 'description' => 'Pattern of path and name of the gettext file at the translation server.', 'type' => 'varchar', @@ -227,10 +211,6 @@ function locale_schema() { $schema['cache_locale'] = drupal_get_schema_unprocessed('system', 'cache'); $schema['cache_locale']['description'] = 'Cache table for the locale module to store various data.'; - // @todo Enable if required. - //$schema['cache_locale_update'] = drupal_get_schema_unprocessed('system', 'cache'); - //$schema['cache_locale_update']['description'] = 'Cache table for the Localization Update module to store information about available releases, fetched from central server.'; - return $schema; } @@ -733,20 +713,6 @@ function locale_update_8011() { 'not null' => TRUE, 'default' => '', ), - 'server' => array( - 'description' => 'Translation server for this project. If empty, the default is used.', - 'type' => 'varchar', - 'length' => '255', - 'not null' => TRUE, - 'default' => '', - ), - 'server_url' => array( - 'description' => 'URL of the xml file at the translation server containing all available languages.', - 'type' => 'varchar', - 'length' => '255', - 'not null' => TRUE, - 'default' => '', - ), 'server_pattern' => array( 'description' => 'Pattern of path and name of the gettext file at the translation server.', 'type' => 'varchar', diff --git a/core/modules/locale/tests/modules/locale_test/locale_test.info b/core/modules/locale/tests/modules/locale_test/locale_test.info index 7cf4200..1ec7508 100644 --- a/core/modules/locale/tests/modules/locale_test/locale_test.info +++ b/core/modules/locale/tests/modules/locale_test/locale_test.info @@ -4,3 +4,7 @@ package = Testing version = 1.2 core = 8.x hidden = TRUE + +; Definitions for interface translations. +interface translation project = locale_test +interface translation server pattern = core/modules/locale/test/modules/locale_test/%project-%version.%language.po diff --git a/core/modules/locale/tests/modules/locale_test/locale_test.module b/core/modules/locale/tests/modules/locale_test/locale_test.module index c16eea7..6044a07 100644 --- a/core/modules/locale/tests/modules/locale_test/locale_test.module +++ b/core/modules/locale/tests/modules/locale_test/locale_test.module @@ -25,20 +25,3 @@ function locale_test_system_info_alter(&$info, $file, $type) { $info['hidden'] = FALSE; } } - -/** - * Implements hook_locale_translation_additional_project_info(). - * - * Overrides interface translation settings for locale_test module. - */ -function locale_test_locale_translation_additional_project_info() { - $projects['locale_test'] = array( - 'type' => 'module', - 'info' => array( - 'project' => 'locale_test', - 'interface translation server pattern' => 'core/modules/locale/test/modules/locale_test/%project-%version.%language.po', - ), - ); - - return $projects; -} diff --git a/core/modules/locale/tests/modules/locale_test_disabled/locale_test_disabled.info b/core/modules/locale/tests/modules/locale_test_disabled/locale_test_disabled.info index 9c0c04f..7eddf25 100644 --- a/core/modules/locale/tests/modules/locale_test_disabled/locale_test_disabled.info +++ b/core/modules/locale/tests/modules/locale_test_disabled/locale_test_disabled.info @@ -5,3 +5,6 @@ version = VERSION core = 8.x hidden = TRUE project = locale_test_disabled + +; Definitions for interface translation. +interface translation project = locale_test_disabled