#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) {
// 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"
@ -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
* Language code to generate the output for, or NULL if generating
* Language object to generate the output for, or NULL if generating
* translation template.
* @param $group
* Text group to export PO file from (eg. 'default' for interface translations)
*/
function _locale_export_po($language = NULL, $group = 'default') {
global $user;
$header = '';
// Get language specific strings, or all strings
function _locale_export_get_strings($language = NULL, $group = 'default') {
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, $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->language, $group);
}
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);
}
// Build array out of the database results
$parent = array();
$strings = array();
while ($child = db_fetch_object($result)) {
if ($child->source != '') {
$parent[$child->lid]['comment'] = $child->location;
$parent[$child->lid]['msgid'] = $child->source;
$parent[$child->lid]['translation'] = isset($child->translation) ? $child->translation : '';
if ($child->plid) {
$parent[$child->lid]['child'] = 1;
$parent[$child->plid]['plural'] = $child->lid;
$string = array(
'comment' => $child->location,
'source' => $child->source,
'translation' => isset($child->translation) ? $child->translation : ''
);
if ($child->plid) {
// 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";
}
}
}
// Generating Portable Object file for a language
if (isset($language)) {
$filename = $language .'.po';
$header = "# $meta->name translation of ". variable_get('site_name', 'Drupal') ."\n";
$header .= '# Copyright (c) '. date('Y') .' '. $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: ". $user->name .' <'. $user->mail .">\\n\"\n";
$header .= "\"Language-Team: ". $meta->name .' <'. $user->mail .">\\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";
else {
$header = "# LANGUAGE translation of PROJECT\n";
$header .= "# Copyright (c) YEAR NAME <EMAIL@ADDRESS>\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: 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 %locale translation file: %filename.', array('%locale' => $meta->name, '%filename' => $filename));
}
// Generating Portable Object Template
else {
$filename = 'drupal.pot';
$header = "# LANGUAGE translation of PROJECT\n";
$header .= "# Copyright (c) YEAR NAME <EMAIL@ADDRESS>\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: 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";
$output = $header ."\n";
foreach ($strings as $lid => $string) {
// Only process non-children, children are output below their parent.
if (!isset($string['child'])) {
if ($string['comment']) {
$output .= '#: '. $string['comment'] ."\n";
}
print 'msgid '. _locale_export_print($message['msgid']);
if (!empty($message['plural'])) {
$plural = $message['plural'];
print 'msgid_plural '. _locale_export_print($parent[$plural]['msgid']);
$output .= 'msgid '. _locale_export_string($string['source']);
if (!empty($string['plural'])) {
$plural = $string['plural'];
$output .= 'msgid_plural '. _locale_export_string($strings[$plural]['source']);
if (isset($language)) {
$translation = $message['translation'];
for ($i = 0; $i < $meta->plurals; $i++) {
print 'msgstr['. $i .'] '. _locale_export_print($translation);
$translation = $string['translation'];
for ($i = 0; $i < $language->plurals; $i++) {
$output .= 'msgstr['. $i .'] '. _locale_export_string($translation);
if ($plural) {
$translation = $parent[$plural]['translation'];
if ($i > 1) {
$translation = _locale_export_remove_plural($translation);
}
$plural = $parent[$plural]['plural'];
$translation = _locale_export_remove_plural($strings[$plural]['translation']);
$plural = isset($strings[$plural]['plural']) ? $strings[$plural]['plural'] : 0;
}
else {
$translation = '';
@ -1793,28 +1804,50 @@ function _locale_export_po($language = NULL, $group = 'default') {
}
}
else {
print 'msgstr[0] ""'."\n";
print 'msgstr[1] ""'."\n";
$output .= 'msgstr[0] ""'."\n";
$output .= 'msgstr[1] ""'."\n";
}
}
else {
if (isset($language)) {
print 'msgstr '. _locale_export_print($message['translation']);
}
else {
print 'msgstr ""'."\n";
}
$output .= 'msgstr '. _locale_export_string($string['translation']);
}
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();
}
/**
* Print out a string on multiple lines
*/
function _locale_export_print($str) {
function _locale_export_string($str) {
$stri = addcslashes($str, "\0..\37\\\"");
$parts = array();