It is really a big deal to manage translations of custom module in Drupal 7 expecially if you have a multisite installation.
Problem
We want use a .po file to translate a custom module programmatically, i.e. without forcing a redactor to do dangerous manual operations.
Furthermore we want have our module always accompained by its translations.
Solution
First of all we need to have l10n_update module installed.
Than we can declare the hook “l10n_update_projects_alter” which allow to set a remote path where the .po file is hosted.
Normally the path should be a remote, indipendent one, but in most cases we would like to have the .po file inside the website itself (i.e. not a separeted environment).
Take a look to the code below in which I declare a .po file that is in the module folder, in particular in “translations” subfolder.
As you can see the file name contains the parameter %language. In this case the filename would be ModuleName.LanguageCode.po.
/**
* Alter the list of project to be updated by Localization Update.
*
* L10n_update uses the same list of projects as update module. Using this hook
* the list can be altered. This hook is typically used to alter the following
* values from the .info file:
* - interface translation project
* - l10n path.
*
* @param array $projects
* Array of projects.
*/
function my_module_name_l10n_update_projects_alter(array &$projects) {
// Setting module name.
$name = 'my_module_name';
// Setting the path of .po files.
$pathToModule = drupal_get_path('module', $name);
$pathToPo = $pathToModule . '/translations/';
$poFileName = $name . '.%language.po';
// Getting url to po
$urlToPoFolder = file_create_url($pathToPo);
$urlToPoFile = $urlToPoFolder . $poFileName;
/**
* In case of S3 filesystem uncomment the code below.
*/
// Instead of the default ftp.drupal.org we use the file system of the test
// instance to simulate a remote file location.
//$wrapper = file_stream_wrapper_get_instance_by_uri('public://');
//$remote_url = $wrapper->getExternalUrl() . '/remote/';
// With this hook it is also possible to add a new project which 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 minimum to be specified.
// As in the previous example the 'l10n path' element is optional.
$projects[$name] = array(
'project_type' => 'module',
'name' => $name,
'info' => array(
'name' => 'My Module name',
'interface translation project' => $name,
'version' => '7.x-1.0',
'core' => '7.x',
'l10n path' => $urlToPoFile,
),
);
}
Furthermore with the following snippet, I have manually (i.e. programmatically) forced the module to update its translations.
// Getting dependencies.
module_load_include('inc','l10n_update','l10n_update.translation');
module_load_include('inc','l10n_update','l10n_update.fetch');
$projects = ['my_module_name'];
$options = _l10n_update_default_update_options();
$options['customized'] = true;
$options['use_remote'] = true;
$options['overwrite_options']['customized'] = true;
l10n_update_clear_status();
$batch = l10n_update_batch_update_build($projects, [], $options);
batch_set($batch);
The .po files have been extracted thanks to Translation Template Extractor.

