#152670 by myself: refactor PO generation to decouple data collection, file generation and HTTP download; fix a bug with plural exports along the way

6.x
Gábor Hojtsy 2007-06-23 20:45:36 +00:00
parent 17e97036ae
commit bedf78d558
1 changed files with 128 additions and 95 deletions

View File

@ -731,7 +731,12 @@ function locale_translate_export_pot_form() {
*/ */
function locale_translate_export_po_form_submit($form, &$form_state) { function locale_translate_export_po_form_submit($form, &$form_state) {
// If template is required, language code is not given. // If template is required, language code is not given.
_locale_export_po(isset($form_state['values']['langcode']) ? $form_state['values']['langcode'] : NULL, $form_state['values']['group']); $language = NULL;
if (isset($form_state['values']['langcode'])) {
$languages = language_list();
$language = $languages[$form_state['values']['langcode']];
}
_locale_export_po($language, _locale_export_po_generate($language, _locale_export_get_strings($language, $form_state['values']['group'])));
} }
/** /**
* @} End of "locale-translate-export" * @} End of "locale-translate-export"
@ -1683,109 +1688,115 @@ function _locale_parse_js_file($filepath) {
*/ */
/** /**
* Exports a Portable Object (Template) file for a language * Generates a structured array of all strings with translations in
* $language, if given. This array can be used to generate an export
* of the string in the database.
* *
* @param $language * @param $language
* Language code to generate the output for, or NULL if generating * Language object to generate the output for, or NULL if generating
* translation template. * translation template.
* @param $group * @param $group
* Text group to export PO file from (eg. 'default' for interface translations) * Text group to export PO file from (eg. 'default' for interface translations)
*/ */
function _locale_export_po($language = NULL, $group = 'default') { function _locale_export_get_strings($language = NULL, $group = 'default') {
global $user;
$header = '';
// Get language specific strings, or all strings
if (isset($language)) { if (isset($language)) {
$meta = db_fetch_object(db_query("SELECT * FROM {languages} WHERE language = '%s'", $language)); $result = db_query("SELECT s.lid, s.source, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE t.language = '%s' AND s.textgroup = '%s' ORDER BY t.plid, t.plural", $language->language, $group);
$result = db_query("SELECT s.lid, s.source, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE t.language = '%s' AND s.textgroup = '%s' ORDER BY t.plid, t.plural", $language, $group);
} }
else { else {
$result = db_query("SELECT s.lid, s.source, s.location, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.textgroup = '%s' ORDER BY t.plid, t.plural", $group); $result = db_query("SELECT s.lid, s.source, s.location, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.textgroup = '%s' ORDER BY t.plid, t.plural", $group);
} }
$strings = array();
// Build array out of the database results
$parent = array();
while ($child = db_fetch_object($result)) { while ($child = db_fetch_object($result)) {
if ($child->source != '') { $string = array(
$parent[$child->lid]['comment'] = $child->location; 'comment' => $child->location,
$parent[$child->lid]['msgid'] = $child->source; 'source' => $child->source,
$parent[$child->lid]['translation'] = isset($child->translation) ? $child->translation : ''; 'translation' => isset($child->translation) ? $child->translation : ''
if ($child->plid) { );
$parent[$child->lid]['child'] = 1; if ($child->plid) {
$parent[$child->plid]['plural'] = $child->lid; // Has a parent lid. Since we process in the order of plids,
// we already have the parent in the array, so we can add the
// lid to the next plural version to it. This builds a linked
// list of plurals.
$string['child'] = TRUE;
$strings[$child->plid]['plural'] = $child->lid;
}
$strings[$child->lid] = $string;
}
return $strings;
}
/**
* Generates the PO(T) file contents for given strings.
*
* @param $language
* Language object to generate the output for, or NULL if generating
* translation template.
* @param $strings
* Array of strings to export. See _locale_export_get_strings()
* on how it should be formatted.
* @param $header
* The header portion to use for the output file. Defaults
* are provided for PO and POT files.
*/
function _locale_export_po_generate($language = NULL, $strings = array(), $header = NULL) {
global $user;
if (!isset($header)) {
if (isset($language)) {
$header = '# '. $language->name .' translation of '. variable_get('site_name', 'Drupal') ."\n";
$header .= '# Generated by '. $user->name .' <'. $user->mail .">\n";
$header .= "#\n";
$header .= "msgid \"\"\n";
$header .= "msgstr \"\"\n";
$header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
$header .= "\"POT-Creation-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
$header .= "\"PO-Revision-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
$header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
$header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
$header .= "\"MIME-Version: 1.0\\n\"\n";
$header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
$header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
if ($language->formula && $language->plurals) {
$header .= "\"Plural-Forms: nplurals=". $language->plurals ."; plural=". strtr($language->formula, array('$' => '')) .";\\n\"\n";
} }
} }
} else {
$header = "# LANGUAGE translation of PROJECT\n";
// Generating Portable Object file for a language $header .= "# Copyright (c) YEAR NAME <EMAIL@ADDRESS>\n";
if (isset($language)) { $header .= "#\n";
$filename = $language .'.po'; $header .= "msgid \"\"\n";
$header = "# $meta->name translation of ". variable_get('site_name', 'Drupal') ."\n"; $header .= "msgstr \"\"\n";
$header .= '# Copyright (c) '. date('Y') .' '. $user->name .' <'. $user->mail .">\n"; $header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
$header .= "#\n"; $header .= "\"POT-Creation-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
$header .= "msgid \"\"\n"; $header .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
$header .= "msgstr \"\"\n"; $header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
$header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n"; $header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
$header .= "\"POT-Creation-Date: ". date("Y-m-d H:iO") ."\\n\"\n"; $header .= "\"MIME-Version: 1.0\\n\"\n";
$header .= "\"PO-Revision-Date: ". date("Y-m-d H:iO") ."\\n\"\n"; $header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
$header .= "\"Last-Translator: ". $user->name .' <'. $user->mail .">\\n\"\n"; $header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
$header .= "\"Language-Team: ". $meta->name .' <'. $user->mail .">\\n\"\n"; $header .= "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n";
$header .= "\"MIME-Version: 1.0\\n\"\n";
$header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
$header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
if ($meta->formula && $meta->plurals) {
$header .= "\"Plural-Forms: nplurals=". $meta->plurals ."; plural=". strtr($meta->formula, array('$' => '')) .";\\n\"\n";
} }
$header .= "\n";
watchdog('locale', 'Exported %locale translation file: %filename.', array('%locale' => $meta->name, '%filename' => $filename));
} }
// Generating Portable Object Template $output = $header ."\n";
else {
$filename = 'drupal.pot'; foreach ($strings as $lid => $string) {
$header = "# LANGUAGE translation of PROJECT\n"; // Only process non-children, children are output below their parent.
$header .= "# Copyright (c) YEAR NAME <EMAIL@ADDRESS>\n"; if (!isset($string['child'])) {
$header .= "#\n"; if ($string['comment']) {
$header .= "msgid \"\"\n"; $output .= '#: '. $string['comment'] ."\n";
$header .= "msgstr \"\"\n";
$header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
$header .= "\"POT-Creation-Date: ". date("Y-m-d H:iO") ."\\n\"\n";
$header .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
$header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
$header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
$header .= "\"MIME-Version: 1.0\\n\"\n";
$header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
$header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
$header .= "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n";
$header .= "\n";
watchdog('locale', 'Exported translation file: %filename.', array('%filename' => $filename));
}
// Start download process
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: text/plain; charset=utf-8");
print $header;
foreach ($parent as $lid => $message) {
if (!isset($message['child'])) {
if ($message['comment']) {
print '#: '. $message['comment'] ."\n";
} }
print 'msgid '. _locale_export_print($message['msgid']); $output .= 'msgid '. _locale_export_string($string['source']);
if (!empty($message['plural'])) { if (!empty($string['plural'])) {
$plural = $message['plural']; $plural = $string['plural'];
print 'msgid_plural '. _locale_export_print($parent[$plural]['msgid']); $output .= 'msgid_plural '. _locale_export_string($strings[$plural]['source']);
if (isset($language)) { if (isset($language)) {
$translation = $message['translation']; $translation = $string['translation'];
for ($i = 0; $i < $meta->plurals; $i++) { for ($i = 0; $i < $language->plurals; $i++) {
print 'msgstr['. $i .'] '. _locale_export_print($translation); $output .= 'msgstr['. $i .'] '. _locale_export_string($translation);
if ($plural) { if ($plural) {
$translation = $parent[$plural]['translation']; $translation = _locale_export_remove_plural($strings[$plural]['translation']);
if ($i > 1) { $plural = isset($strings[$plural]['plural']) ? $strings[$plural]['plural'] : 0;
$translation = _locale_export_remove_plural($translation);
}
$plural = $parent[$plural]['plural'];
} }
else { else {
$translation = ''; $translation = '';
@ -1793,28 +1804,50 @@ function _locale_export_po($language = NULL, $group = 'default') {
} }
} }
else { else {
print 'msgstr[0] ""'."\n"; $output .= 'msgstr[0] ""'."\n";
print 'msgstr[1] ""'."\n"; $output .= 'msgstr[1] ""'."\n";
} }
} }
else { else {
if (isset($language)) { $output .= 'msgstr '. _locale_export_string($string['translation']);
print 'msgstr '. _locale_export_print($message['translation']);
}
else {
print 'msgstr ""'."\n";
}
} }
print "\n"; $output .= "\n";
} }
} }
return $output;
}
/**
* Write a generated PO or POT file to the output.
*
* @param $language
* Language object to generate the output for, or NULL if generating
* translation template.
* @param $output
* The PO(T) file to output as a string. See _locale_export_generate_po()
* on how it can be generated.
*/
function _locale_export_po($language = NULL, $output = NULL) {
// Log the export event.
if (isset($language)) {
$filename = $language->language .'.po';
watchdog('locale', 'Exported %locale translation file: %filename.', array('%locale' => $language->name, '%filename' => $filename));
}
else {
$filename = 'drupal.pot';
watchdog('locale', 'Exported translation file: %filename.', array('%filename' => $filename));
}
// Download the file fo the client.
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: text/plain; charset=utf-8");
print $output;
die(); die();
} }
/** /**
* Print out a string on multiple lines * Print out a string on multiple lines
*/ */
function _locale_export_print($str) { function _locale_export_string($str) {
$stri = addcslashes($str, "\0..\37\\\""); $stri = addcslashes($str, "\0..\37\\\"");
$parts = array(); $parts = array();