? balloon ? content_type.php ? locale.php ? select.html ? misc/theme.js ? modules/user/access_control.js ? sites/all/modules ? sites/all/modules_repository ? themes/garland/script.js Index: includes/locale.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/locale.inc,v retrieving revision 1.124 diff -u -d -F^\s*function -r1.124 locale.inc --- includes/locale.inc 15 May 2007 15:29:47 -0000 1.124 +++ includes/locale.inc 15 May 2007 17:27:20 -0000 @@ -776,7 +776,11 @@ function locale_translate_edit_form_subm else { db_query("INSERT INTO {locales_target} (lid, translation, language) VALUES (%d, '%s', '%s')", $lid, $value, $key); } + + // Refresh the JS file for this language. + _locale_rebuild_js($key); } + drupal_set_message(t('The string has been saved.')); // Refresh the locale cache. @@ -800,8 +804,12 @@ function locale_translate_edit_form_subm * Delete a language string. */ function locale_translate_delete($lid) { + $language = db_fetch_object(db_query('SELECT language FROM {locales_source} WHERE lid = %d', $lid)); db_query('DELETE FROM {locales_source} WHERE lid = %d', $lid); db_query('DELETE FROM {locales_target} WHERE lid = %d', $lid); + if ($language && $language->language) { + _locale_rebuild_js($language->language); + } locale_refresh_cache(); drupal_set_message(t('The string has been removed.')); drupal_goto('admin/build/translate/search'); @@ -1855,6 +1863,111 @@ function _locale_translate_seek_query() } /** + * (Re-)Creates the JavaScript translation file for a language. + * + * @param $language + * The language, the translation file should be (re)created for. + */ +function _locale_rebuild_js($language) { + // Get information about the locale. + $languages = language_list(); + $language = $languages[$language]; + + // Construct the array for JavaScript translations. + // We sort on plural so that we have all plural forms before singular forms. + $result = db_query("SELECT s.lid, s.source, t.plid, t.plural, t.translation FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid WHERE t.language = '%s' AND s.textgroup = 'javascript' ORDER BY t.plural DESC", $language->language); + + $translations = $plurals = array(); + while ($data = db_fetch_object($result)) { + // Only add this to the translations array when there is actually a translation. + if (!empty($data->translation)) { + if ($data->plural) { + // When the translation is a plural form, first add it to another array and + // wait for the singular (parent) translation. + if (!isset($plurals[$data->plid])) { + $plurals[$data->plid] = array($data->plural => $data->translation); + } + else { + $plurals[$data->plid] += array($data->plural => $data->translation); + } + } + elseif (isset($plurals[$data->lid])) { + // There are plural translations for this translation, so get them from + // the plurals array and add them to the final translations array. + $translations[$data->source] = array($data->plural => $data->translation) + $plurals[$data->lid]; + unset($plurals[$data->lid]); + } + else { + // There are no plural forms for this translation, so just add it to + // the translations array. + $translations[$data->source] = $data->translation; + } + } + } + + // Only operate when there are translations. + if (!empty($translations)) { + // Construct the JavaScript file. + $data = "Drupal.locale = { "; + + if (!empty($language->formula)) { + $data .= "'pluralFormula': function(\$n) { return Number({$language->formula}); }, "; + } + + $data .= "'strings': ". drupal_to_js($translations) ." };"; + + $data_hash = md5($data); + + // Construct the directory where JS translation files are stored. + // There is (on purpose) no front end to edit that variable. + $dir = file_create_path(variable_get('locale_js_directory', 'languages')); + + // Only create a new file if the content has changed. + if ($language->javascript != $data_hash) { + if (!empty($language->javascript)) { + // We are recreating the new file, so delete the old one. + file_delete(file_create_path($dir .'/'. $language->language .'_'. $language->javascript .'.js')); + $language->javascript = ''; + } + else { + // The directory might not exist when there has not been a translation + // file before, so create it. + file_check_directory($dir, TRUE); + } + + // The file name of the new JavaScript translation file. + $dest = $dir .'/'. $language->language .'_'. $data_hash .'.js'; + $path = file_save_data($data, $dest); + + db_query("UPDATE {languages} SET javascript = '%s' WHERE locale = '%s'", $path ? $data_hash : '', $language->language); + + // Only report updated or creation when there is actually a file created. + if ($path) { + // There has already been a translation file before. + if (!empty($language->javascript)) { + watchdog('locale', t('Updated JavaScript translation file for the language %language.', array('%language' => t($language->name)))); + } + else { + watchdog('locale', t('Created JavaScript translation file for the language %language.', array('%language' => t($language->name)))); + } + } + else { + watchdog('locale', t('An error occured during creation of the JavaScript translation file for the language %language.', array('%language' => t($language->name)))); + } + } + } + + // There are no strings for JavaScript translation. However, if there is a file, + // delete it and reset the database. + elseif (!empty($language->javascript)) { + // Delete the old JavaScript file + file_delete(file_create_path(variable_get('locale_js_directory', 'languages') .'/'. $language->language .'_'. $language->javascript .'.js')); + db_query("UPDATE {languages} SET javascript = '' WHERE locale = '%s'", $language->language); + watchdog('locale', t('Deleted JavaScript translation file for the locale %language.', array('%language' => t($language->name)))); + } +} + +/** * List languages in search result table */ function _locale_translate_language_list($translation) { Index: misc/drupal.js =================================================================== RCS file: /cvs/drupal/drupal/misc/drupal.js,v retrieving revision 1.31 diff -u -d -F^\s*function -r1.31 drupal.js --- misc/drupal.js 4 May 2007 09:41:36 -0000 1.31 +++ misc/drupal.js 15 May 2007 17:27:20 -0000 @@ -1,6 +1,6 @@ // $Id: drupal.js,v 1.31 2007/05/04 09:41:36 goba Exp $ -var Drupal = Drupal || {}; +var Drupal = Drupal || { 'settings': {}, 'themes': {}, 'locale' {} }; /** * Set the variable that indicates if JavaScript behaviors should be applied @@ -22,6 +22,96 @@ }; /** + * Encode special characters in a plain-text string for display as HTML. + */ +Drupal.checkPlain = function(str) { + str = String(str); + var replace = { '&': '&', '"': '"', '<': '<', '>': '>' }; + for (var character in replace) { + str = str.replace(character, replace[character]); + } + return str; +} + +/** + * Translate strings to the current locale. + */ +Drupal.t = function(str, args) { + if (typeof str == 'object') { + if (Drupal.locale.strings[str[0]]) { + str = Drupal.locale.strings[str[0]]; + } + if (args && args['@count']) { + if (Drupal.locale.pluralFormula) { + str = str[Drupal.locale.pluralFormula(args['@count'])]; + } + else { + str = str[(args['@count'] == 1) ? 0 : 1]; + } + } + else { + str = str[0]; + } + } + else if (Drupal.locale[str]) { + str = Drupal.locale[str] + } + + if (args) { + // Transform arguments before inserting them + for (var key in args) { + switch (key[0]) { + // Escaped only + case '@': + args[key] = Drupal.checkPlain(args[key]); + break; + // Pass-through + case '!': + break; + // Escaped and placeholder + case '%': + default: + args[key] = Drupal.theme('placeholder', args[key]); + break; + } + str = str.replace(key, args[key]); + } + } + return str; +} + +Drupal.formatPlural(count, singular, plural) { + return Drupal.t([ singular, plural ], { '@count': count }); +} + +/** + * Generate the themed representation of a Drupal object. + * + * All requests for themed output must go through this function. It examines + * the request and routes it to the appropriate theme function. If the current + * theme does not provide an override function, the generic theme function is + * called. + * + * For example, to retrieve the HTML that is output by theme_placeholder(text), + * call Drupal.theme('placeholder', text). + * + * @param func + * The name of the theme function to call. + * @param ... + * Additional arguments to pass along to the theme function. + * @return + * Any data the theme function returns. This could be a plain HTML string, + * but also a complex object. + */ +Drupal.theme = function(func) { + for (var i = 1, args = []; i < arguments.length; i++) { + args.push(arguments[i]); + } + + return (Drupal.theme[func] || Drupal.theme.prototype[func]).apply(this, args); +}; + +/** * Redirects a button's form submission to a hidden iframe and displays the result * in a given wrapper. The iframe should contain a call to * window.parent.iframeHandler() after submission. @@ -227,3 +317,21 @@ // 'js enabled' cookie document.cookie = 'has_js=1'; } + +/** + * The default themes. + */ +Drupal.theme.prototype = { + + /** + * Formats text for emphasized display in a placeholder inside a sentence. + * + * @param str + * The text to format (plain-text). + * @return + * The formatted text (html). + */ + placeholder: function(str) { + return '' + Drupal.checkPlain(str) + ''; + } +}; Index: misc/progress.js =================================================================== RCS file: /cvs/drupal/drupal/misc/progress.js,v retrieving revision 1.15 diff -u -d -F^\s*function -r1.15 progress.js --- misc/progress.js 4 May 2007 09:41:36 -0000 1.15 +++ misc/progress.js 15 May 2007 17:27:20 -0000 @@ -86,7 +86,7 @@ pb.timer = setTimeout(function() { pb.sendPing(); }, pb.delay); }, error: function (xmlhttp) { - pb.displayError('An HTTP error '+ xmlhttp.status +' occured.\n'+ pb.uri); + pb.displayError(Drupal.t('An HTTP error @status occured.', { '@status': xmlhttp.status }) +'\n'+ pb.uri); } }); } Index: misc/upload.js =================================================================== RCS file: /cvs/drupal/drupal/misc/upload.js,v retrieving revision 1.11 diff -u -d -F^\s*function -r1.11 upload.js --- misc/upload.js 31 Aug 2006 23:31:25 -0000 1.11 +++ misc/upload.js 15 May 2007 17:27:20 -0000 @@ -33,7 +33,7 @@ Drupal.jsUpload.prototype.onsubmit = function () { // Insert progressbar and stretch to take the same space. this.progress = new Drupal.progressBar('uploadprogress'); - this.progress.setProgress(-1, 'Uploading file'); + this.progress.setProgress(-1, Drupal.t('Uploading file')); var hide = this.hide; var el = this.progress.element; @@ -98,7 +98,7 @@ * Handler for the form redirection error. */ Drupal.jsUpload.prototype.onerror = function (error) { - alert('An error occurred:\n\n'+ error); + alert(Drupal.t('An error occurred:\n\n@error', { '@error': error })); // Remove progressbar $(this.progress.element).remove(); this.progress = null; Index: modules/locale/locale.install =================================================================== RCS file: /cvs/drupal/drupal/modules/locale/locale.install,v retrieving revision 1.9 diff -u -d -F^\s*function -r1.9 locale.install --- modules/locale/locale.install 3 May 2007 09:51:08 -0000 1.9 +++ modules/locale/locale.install 15 May 2007 17:27:21 -0000 @@ -22,6 +22,7 @@ function locale_install() { domain varchar(128) NOT NULL default '', prefix varchar(128) NOT NULL default '', weight int NOT NULL default '0', + javascript varchar(32) NOT NULL default '', PRIMARY KEY (language) ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); @@ -59,6 +60,7 @@ function locale_install() { domain varchar(128) NOT NULL default '', prefix varchar(128) NOT NULL default '', weight int NOT NULL default '0', + javascript varchar(32) NOT NULL default '', PRIMARY KEY (language) )"); @@ -84,7 +86,7 @@ function locale_install() { db_query("CREATE INDEX {locales_source}_source_idx ON {locales_source} (source)"); break; } - db_query("INSERT INTO {languages} (language, name, native, direction, enabled, weight) VALUES ('en', 'English', 'English', '0', '1', '0')"); + db_query("INSERT INTO {languages} (language, name, native, direction, enabled, weight, javascript) VALUES ('en', 'English', 'English', '0', '1', '0', '')"); } /** @@ -164,6 +166,23 @@ function locale_update_6002() { } /** + * Adds a column to store the filename of the JavaScript translation file. + */ +function locale_update_6003() { + $ret = array(); + switch ($GLOBALS['db_type']) { + case 'mysql': + case 'mysqli': + $ret[] = update_sql("ALTER TABLE {languages} ADD javascript varchar(32) NOT NULL default ''"); + break; + case 'pgsql': + db_add_column($ret, 'languages', 'javascript', 'varchar(32)', array('default' => "''", 'not null' => TRUE)); + break; + } + return $ret; +} + +/** * @} End of "defgroup updates-5.x-to-6.x" */ @@ -171,6 +190,14 @@ function locale_update_6002() { * Implementation of hook_uninstall(). */ function locale_uninstall() { + // Delete all JavaScript translation files + $files = db_query('SELECT javascript FROM {languages}'); + while ($file = db_fetch_object($files)) { + if (!empty($file)) { + file_delete(file_create_path($file->javascript)); + } + } + db_query('DROP TABLE {languages}'); db_query('DROP TABLE {locales_source}'); db_query('DROP TABLE {locales_target}');