diff --git a/core/modules/locale/locale.api.php b/core/modules/locale/locale.api.php index 56bfbeb..f5e5955 100644 --- a/core/modules/locale/locale.api.php +++ b/core/modules/locale/locale.api.php @@ -27,22 +27,74 @@ function hook_locale_translation_projects_alter(&$projects) { 'interface translation server pattern' => 'http://example.com/files/translations/%core/%project/%project-%release.%language.po', ), ); +} + +/** + * Allows modules and themes to define or alter project definitions for + * interface translation. + * + * Themes can implement this hook too in their template.php file. + * + * @return + * Array of project defintions. + */ +function hook_locale_translation_additional_project_info() { + // If your custom module contains new strings the Locale interface translation + // can be configured to recognize and import the translations. + // The tanslations can be located in the local file system or remotely in a + // translation server (similar to localization.drupal.org). + // Required: type. "project" is required if the "example_project" is a custom + // module and not a contributed module. - // With this hook it is also possible to add a new project wich does not - // exist as a real module or theme project but is treated by the localization - // update module as one. The below data is the minumum to be specified. - // The 'interface translation server' elements are optional. - $projects['new_example_project'] = array( - 'project_type' => 'module', - 'name' => 'new_example_project', + // Po file located at a remote translation server. + $projects['example_module'] = array( + 'type' => 'module', 'info' => array( - 'version' => '8.x-1.5', - 'core' => '8.x', + '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-%release.%language.po', + 'interface translation server pattern' => 'http://example.com/files/translations/%core/%project/%project-%version.%language.po', + ), + ); + + // 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', ), ); + + // When multiple custom modules share the same po file, their project + // definitions should match. Both "project", "version" and "interface + // translation server" definitions are used as part of the po file format and + // should match. + // In this example the above example module and the other_example_module share + // the same po file. "project", "version" and "interface translation server + // pattern" are overridden to match the above po file name as provided by the + // example_module. + $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', + ), + ); + + // Themes can implement this hook too in their template.php file (but only + // in this file!). + $projects['zen'] = 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; } // @todo Remove this list. @@ -50,8 +102,5 @@ function hook_locale_translation_projects_alter(&$projects) { // ========== // Let the translation server provide the name and pattern details, instead // of defining it in the .info file or in code. -// ÀÀ Will this work if an installation profile or a custom module provides -// it's own info hook and needs to download translations from a remote server? -// Gracefull degradation if Update module is not available. Continue updating -// but ignore new enable and disabled modules. Notify the user on the -// missing Update module when applicable. +// Will this work if an installation profile or a custom module provides +// it's own info hook and needs to download translations from a remote server? diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc index fb68f27..8c35be1 100644 --- a/core/modules/locale/locale.compare.inc +++ b/core/modules/locale/locale.compare.inc @@ -26,7 +26,7 @@ const LOCALE_TRANSLATION_DEFAULT_SERVER_URL = 'http://localize.drupal.org/l10n_s * * @see locale_translation_default_translation_server(). */ -const LOCALE_TRANSLATION_DEFAULT_SERVER_PATTERN = 'http://ftp.drupal.org/files/translations/%core/%project/%project-%release.%language.po'; +const LOCALE_TRANSLATION_DEFAULT_SERVER_PATTERN = 'http://ftp.drupal.org/files/translations/%core/%project/%project-%version.%language.po'; use Drupal\Core\Cache; @@ -185,8 +185,8 @@ function locale_translation_project_list() { 'interface translation server pattern', 'interface translation project', ); - $module_data = _locale_translation_prepare_project_list($foo = system_rebuild_module_data()); - $theme_data = _locale_translation_prepare_project_list(system_rebuild_theme_data()); + $module_data = _locale_translation_prepare_project_list(system_rebuild_module_data(), 'module'); + $theme_data = _locale_translation_prepare_project_list(system_rebuild_theme_data(), 'theme'); update_process_info_list($projects, $module_data, 'module', TRUE, $additional_whitelist); update_process_info_list($projects, $theme_data, 'theme', TRUE, $additional_whitelist); if (variable_get('locale_translation_check_disabled', 0)) { @@ -213,21 +213,75 @@ function locale_translation_project_list() { * * @param $data * Array of .info file data. + * @param $type + * The project type. i.e. module, theme. * * @return * Array of .info file data. */ -function _locale_translation_prepare_project_list($data) { - foreach ($data as $name => $file) { - // Include interface translation projects. - if (isset($file->info['interface translation project'])) { - $data[$name]->info['project'] = $file->info['interface translation project']; +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']; + } } } return $data; } /** + * Fetch additional project definitions and definition overrides. + * + * @return + * Array of custom project. + * + * @see hook_locale_translation_additional_project_info(). + */ +function locale_translation_get_additional_projects() { + $projects = &drupal_static(__FUNCTION__, array()); + + // Call hook_locale_translation_additional_project_info for modules. + if (empty($projects)) { + $hook = 'locale_translation_additional_project_info'; + foreach (module_implements($hook) as $module) { + $projects = module_invoke($module, $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 @@ -327,7 +381,7 @@ function locale_translation_translation_servers($name = NULL, $url = NULL, $refr * @param $template * String containing place holders. Available place holders: * - "%project": Project name. - * - "%release": Poject version. + * - "%version": Poject version. * - "%core": Project core version. * - "%language": Language code. * - "%filename": Project file name. @@ -338,7 +392,7 @@ function locale_translation_translation_servers($name = NULL, $url = NULL, $refr function locale_translation_build_server_pattern($project, $template) { $variables = array( '%project' => $project->name, - '%release' => $project->version, + '%version' => $project->version, '%core' => $project->core, '%language' => isset($project->language) ? $project->language : '%language', '%filename' => isset($project->filename) ? $project->filename : '%filename', diff --git a/core/modules/locale/locale.info b/core/modules/locale/locale.info index 8b3e5f7..e0749db 100644 --- a/core/modules/locale/locale.info +++ b/core/modules/locale/locale.info @@ -4,4 +4,3 @@ package = Core version = VERSION core = 8.x dependencies[] = language -files[] = locale.test diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index 038ce21..2054320 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -178,7 +178,6 @@ function locale_schema() { 'not null' => TRUE, 'default' => '', ), - // @todo Is the status being used? 'status' => array( 'description' => 'Status flag. TBD', 'type' => 'int', @@ -621,13 +620,74 @@ function locale_update_8009() { } /** - * Add a cache table for the locale module. + * Add a cache table and locale_project table for the locale module. */ function locale_update_8010() { - // Add a 'locale' cache. - $schema['cache_locale'] = drupal_get_schema_unprocessed('system', 'cache'); - $schema['cache_locale']['description'] = 'Cache table for the locale module to store various data.'; - drupal_install_schema($schema); + // Add a 'locale' cache table. + $table = drupal_get_schema_unprocessed('system', 'cache'); + $table['description'] = 'Cache table for the locale module to store various data.'; + db_create_table('cache_locale', $table); + + // Add locale_project table. + db_create_table('locale_project', array( + 'description' => 'Update information for project translations.', + 'fields' => array( + 'name' => array( + 'description' => 'A unique short name to identify the project.', + 'type' => 'varchar', + 'length' => '50', + 'not null' => TRUE, + ), + 'project_type' => array( + 'description' => 'Project type, may be core, module, theme', + 'type' => 'varchar', + 'length' => '50', + 'not null' => TRUE, + ), + 'core' => array( + 'description' => 'Core compatibility string for this project.', + 'type' => 'varchar', + 'length' => '128', + 'not null' => TRUE, + 'default' => '', + ), + 'version' => array( + 'description' => 'Human readable name for project used on the interface.', + 'type' => 'varchar', + 'length' => '128', + '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', + 'length' => '255', + 'not null' => TRUE, + 'default' => '', + ), + 'status' => array( + 'description' => 'Status flag. TBD', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 1, + ), + ), + 'primary key' => array('name'), + )); } /**