View Issue Details

IDProjectCategoryView StatusLast Update
0004147mantisbtemailpublic2004-08-29 01:50
Reporterthraxisp Assigned Tothraxisp  
PriorityurgentSeveritymajorReproducibilityalways
Status closedResolutionfixed 
Product Version0.19.0a2 
Fixed in Version0.19.0rc1 
Summary0004147: Receiving emails in foreign languages
Description

Although it helps me learn a subset of other languages, I am receiving notifications in languages other than my preference.

TagsNo tags attached.
Attached Files
lang.diff (13,970 bytes)   
? test_mail.php
Index: core/email_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/email_api.php,v
retrieving revision 1.91
diff -u -r1.91 email_api.php
--- core/email_api.php	8 Aug 2004 20:30:19 -0000	1.91
+++ core/email_api.php	11 Aug 2004 15:58:12 -0000
@@ -22,9 +22,6 @@
 	# reusable object of class SMTP
 	$g_phpMailer_smtp = null;
 
-	# email language
-	$g_email_lang = NULL; # NULL = default
-
 	###########################################################################
 	# Email API
 	###########################################################################
@@ -297,7 +294,7 @@
 	# --------------------
 	# Send password to user
 	function email_signup( $p_user_id, $p_password ) {
-		global $g_mantis_user_table, $g_path, $g_email_lang;
+		global $g_mantis_user_table, $g_path;
 
 		$c_user_id = db_prepare_int( $p_user_id );
 
@@ -308,26 +305,26 @@
 		$row = db_fetch_array( $result );
 		extract( $row, EXTR_PREFIX_ALL, 'v' );
 
-		$g_email_lang = user_pref_get_language( $p_user_id );
+		lang_push( user_pref_get_language( $p_user_id ) );
 
 		# Build Welcome Message
 		$t_message = lang_get( 'new_account_greeting' ).
-						lang_get( 'new_account_url', $g_email_lang ) . $g_path . "\n".
-						lang_get( 'new_account_username', $g_email_lang ) . $v_username . "\n".
-						lang_get( 'new_account_password', $g_email_lang ) . $p_password . "\n\n".
-						lang_get( 'new_account_message', $g_email_lang ) .
-						lang_get( 'new_account_do_not_reply', $g_email_lang );
+						lang_get( 'new_account_url' ) . $g_path . "\n".
+						lang_get( 'new_account_username' ) . $v_username . "\n".
+						lang_get( 'new_account_password' ) . $p_password . "\n\n".
+						lang_get( 'new_account_message' ) .
+						lang_get( 'new_account_do_not_reply' );
 
 		# Send signup email regardless of mail notification pref
 		# or else users won't be able to sign up
-		email_send( $v_email, lang_get( 'new_account_subject', $g_email_lang ), $t_message );
+		email_send( $v_email, lang_get( 'new_account_subject' ), $t_message );
 
-		$g_email_lang = NULL;
+		lang_pop();
 	}
 	# --------------------
 	# Send new password when user forgets
 	function email_reset( $p_user_id, $p_password ) {
-		global 	$g_mantis_user_table, $g_path, $g_email_lang;
+		global 	$g_mantis_user_table, $g_path;
 
 		$c_user_id = db_prepare_int( $p_user_id );
 
@@ -338,19 +335,19 @@
 		$row = db_fetch_array( $result );
 		extract( $row, EXTR_PREFIX_ALL, 'v' );
 
-		$g_email_lang = user_pref_get_language( $p_user_id );
+		lang_push( user_pref_get_language( $p_user_id ) );
 
 		# Build Welcome Message
-		$t_message = lang_get( 'reset_request_msg', $g_email_lang ) . "\n\n".
-					lang_get( 'new_account_username', $g_email_lang ) . $v_username."\n".
-					lang_get( 'new_account_password', $g_email_lang ) . $p_password."\n\n".
+		$t_message = lang_get( 'reset_request_msg' ) . "\n\n".
+					lang_get( 'new_account_username' ) . $v_username."\n".
+					lang_get( 'new_account_password' ) . $p_password."\n\n".
 					$g_path."\n\n";
 
 		# Send password reset regardless of mail notification prefs
 		# or else users won't be able to receive their reset pws
-		email_send( $v_email, lang_get( 'news_password_msg', $g_email_lang ), $t_message );
+		email_send( $v_email, lang_get( 'news_password_msg' ), $t_message );
 
-		$g_email_lang = NULL;
+		lang_pop();
 	}
 	# --------------------
 	# send a generic email
@@ -491,7 +488,7 @@
 	# this function sends the actual email
 	# if $p_exit_on_error == true (default) - calls exit() on errors, else - returns true on success and false on errors
 	function email_send( $p_recipient, $p_subject, $p_message, $p_header='', $p_category='', $p_exit_on_error=true ) {
-		global $g_phpMailer_smtp, $g_email_lang;
+		global $g_phpMailer_smtp;
 
 		$t_recipient = trim( $p_recipient );
 		$t_subject   = string_email( trim( $p_subject ) );
@@ -519,7 +516,8 @@
 		$mail = new PHPMailer;
 
 		$mail->PluginDir = PHPMAILER_PATH;
-		$mail->SetLanguage( lang_get( 'phpmailer_language', $g_email_lang ), PHPMAILER_PATH . 'language' . DIRECTORY_SEPARATOR );
+		# @@@ should this be the current language (for the recipient) or the default one (for the user running the command) (thraxisp) 
+		$mail->SetLanguage( lang_get( 'phpmailer_language', lang_peek() ), PHPMAILER_PATH . 'language' . DIRECTORY_SEPARATOR );
 
 		# Select the method to send mail
 		switch ( config_get( 'phpMailer_method' ) ) {
@@ -550,7 +548,7 @@
 		$mail->IsHTML(false);              # set email format to plain text
 		$mail->WordWrap = 80;              # set word wrap to 50 characters
 		$mail->Priority = config_get( 'mail_priority' );               # Urgent = 1, Not Urgent = 5, Disable = 0
-		$mail->CharSet = lang_get( 'charset', $g_email_lang );
+		$mail->CharSet = lang_get( 'charset', lang_peek() );
 		$mail->Host     = config_get( 'smtp_host' );
 		$mail->From     = config_get( 'from_email' );
 		$mail->Sender   = config_get( 'return_path_email' );
@@ -683,7 +681,6 @@
 	# @@@ I'm not sure this shouldn't return an array of user ids... more work for
 	#  the caller but cleaner from an API point of view.
 	function email_bug_reminder( $p_recipients, $p_bug_id, $p_message ) {
-		global $g_email_lang;
 
 		if ( !is_array( $p_recipients ) ) {
 			$p_recipients = array( $p_recipients );
@@ -692,14 +689,14 @@
 		$result = array();
 		foreach ( $p_recipients as $t_recipient ) {
 
-			$g_email_lang = user_pref_get_language( $t_recipient, bug_get_field( $p_bug_id, 'project_id' ) );
+			lang_push( user_pref_get_language( $t_recipient, bug_get_field( $p_bug_id, 'project_id' ) ) );
 
 			$t_subject = email_build_subject( $p_bug_id );
 			$t_sender = current_user_get_field( 'username' ) . ' <' .
 						current_user_get_field( 'email' ) . '>' ;
 			$t_date = date( config_get( 'normal_date_format' ) );
-			$t_header = "\n" . lang_get( 'on', $g_email_lang ) . " $t_date, $t_sender " .
-						lang_get( 'sent_you_this_reminder_about', $g_email_lang ) . ":\n\n";
+			$t_header = "\n" . lang_get( 'on' ) . " $t_date, $t_sender " .
+						lang_get( 'sent_you_this_reminder_about' ) . ":\n\n";
 
 			$t_email = user_get_email( $t_recipient );
 			$result[] = user_get_name( $t_recipient );
@@ -711,7 +708,7 @@
 				email_send( $t_email, $t_subject, $t_contents );
 			}
 
-			$g_email_lang = NULL;
+			lang_pop();
 		}
 		return $result;
 	}
@@ -720,7 +717,6 @@
 	# Send bug info to given user
 	# return true on success
 	function email_bug_info_to_one_user( $p_visible_bug_data, $p_message_id, $p_project_id, $p_user_id ) {
-		global $g_email_lang;
 
 		$t_user_email = user_get_email( $p_user_id );
 
@@ -731,7 +727,7 @@
 		}
 
 		# load (push) user language
-		$g_email_lang = user_pref_get_language( $p_user_id, $p_project_id );
+		lang_push( user_pref_get_language( $p_user_id, $p_project_id ) );
 
 		# build subject
 		$t_subject = '['.$p_visible_bug_data['email_project'].' '
@@ -740,7 +736,7 @@
 
 		# build message
 
-		$t_message = lang_get_defaulted( $p_message_id, null, $g_email_lang );
+		$t_message = lang_get_defaulted( $p_message_id, null );
 		if ( ( $t_message !== null ) && ( !is_blank( $t_message ) ) ) {
 			$t_message .= "\n";
 		}
@@ -751,7 +747,7 @@
 		# PRINT '<br />email_bug_info::Sending email to :'.$t_user_email;
 		$t_ok = email_send( $t_user_email, $t_subject, $t_message, '', $p_visible_bug_data['set_category'], false );
 
-		$g_email_lang = NULL;
+		lang_pop();
 
 		return $t_ok;
 	}
@@ -759,7 +755,6 @@
 	# --------------------
 	# Build the bug info part of the message
 	function email_format_bug_message( $p_visible_bug_data ) {
-		global $g_email_lang;
 
 		$t_normal_date_format = config_get( 'normal_date_format' );
 		$t_complete_date_format = config_get( 'complete_date_format' );
@@ -800,7 +795,7 @@
 		# custom fields formatting
 		foreach( $p_visible_bug_data['custom_fields'] as $t_custom_field_name => $t_custom_field_data ) {
 
-			$t_message .= str_pad( lang_get_defaulted( $t_custom_field_name, null, $g_email_lang ) . ': ', $t_email_padding_length, ' ', STR_PAD_RIGHT );
+			$t_message .= str_pad( lang_get_defaulted( $t_custom_field_name, null ) . ': ', $t_email_padding_length, ' ', STR_PAD_RIGHT );
 
 			if ( CUSTOM_FIELD_TYPE_EMAIL === $t_custom_field_data['type'] ) {
 				$t_message .= 'mailto:'.$t_custom_field_data['value'];
@@ -825,7 +820,7 @@
 
 		$t_message .= email_format_attribute( $p_visible_bug_data, 'email_summary' );
 
-		$t_message .= lang_get( 'email_description', $g_email_lang ) . ": \n".wordwrap( $p_visible_bug_data['email_description'] )."\n";
+		$t_message .= lang_get( 'email_description' ) . ": \n".wordwrap( $p_visible_bug_data['email_description'] )."\n";
 
 		# MASC RELATIONSHIP
 		if ( ON == config_get( 'enable_relationship' ) ) {
@@ -838,7 +833,7 @@
 		# Sponsorship
 		if ( isset( $p_visible_bug_data['sponsorship_total'] ) && ( $p_visible_bug_data['sponsorship_total'] > 0 ) ) {
 			$t_message .= $t_email_separator1."\n";
-			$t_message .= sprintf( lang_get( 'total_sponsorship_amount', $g_email_lang ), sponsorship_format_amount( $p_visible_bug_data['sponsorship_total'] ) ) . "\n" . "\n";
+			$t_message .= sprintf( lang_get( 'total_sponsorship_amount' ), sponsorship_format_amount( $p_visible_bug_data['sponsorship_total'] ) ) . "\n" . "\n";
 
 			if ( isset( $p_visible_bug_data['sponsorships'] ) ) {
 				foreach ( $p_visible_bug_data['sponsorships'] as $t_sponsorship ) {
@@ -866,11 +861,11 @@
 
 		# format history
 		if ( array_key_exists( 'history', $p_visible_bug_data ) ) {
-			$t_message .=	lang_get( 'bug_history', $g_email_lang ) . "\n";
-			$t_message .=	str_pad( lang_get( 'date_modified', $g_email_lang ), 15 ) .
-							str_pad( lang_get( 'username', $g_email_lang ), 15 ) .
-							str_pad( lang_get( 'field', $g_email_lang ), 25 ) .
-							str_pad( lang_get( 'change', $g_email_lang ), 20 ). "\n";
+			$t_message .=	lang_get( 'bug_history' ) . "\n";
+			$t_message .=	str_pad( lang_get( 'date_modified' ), 15 ) .
+							str_pad( lang_get( 'username' ), 15 ) .
+							str_pad( lang_get( 'field' ), 25 ) .
+							str_pad( lang_get( 'change' ), 20 ). "\n";
 
 			$t_message .= $t_email_separator1."\n";
 
@@ -896,10 +891,9 @@
 	# returns concatenated translated attribute name and original
 	# attribute value. Else return empty string.
 	function email_format_attribute( $p_visible_bug_data, $attribute_id ) {
-		global $g_email_lang;
 
 		if ( array_key_exists( $attribute_id, $p_visible_bug_data ) ) {
-			return str_pad( lang_get( $attribute_id, $g_email_lang ) . ': ', config_get( 'email_padding_length' ), ' ', STR_PAD_RIGHT ).$p_visible_bug_data[$attribute_id]."\n";
+			return str_pad( lang_get( $attribute_id ) . ': ', config_get( 'email_padding_length' ), ' ', STR_PAD_RIGHT ).$p_visible_bug_data[$attribute_id]."\n";
 		}
 		return '';
 	}
Index: core/error_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/error_api.php,v
retrieving revision 1.32
diff -u -r1.32 error_api.php
--- core/error_api.php	3 Aug 2004 13:47:48 -0000	1.32
+++ core/error_api.php	11 Aug 2004 15:58:12 -0000
@@ -33,12 +33,16 @@
 	#
 	function error_handler( $p_type, $p_error, $p_file, $p_line, $p_context ) {
 		global $g_error_parameters, $g_error_handled, $g_error_proceed_url;
+		global $g_lang_overrides;
 
 		# check if errors were disabled with @ somewhere in this call chain
 		if ( 0 == error_reporting() ) {
 			return;
 		}
 
+		# flush any language overrides to return to user's natural default
+		$g_lang_overrides = array();
+		
 		$t_short_file	= basename( $p_file );
 		$t_method		= 'none';
 
Index: core/lang_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/lang_api.php,v
retrieving revision 1.28
diff -u -r1.28 lang_api.php
--- core/lang_api.php	10 Jul 2004 15:40:21 -0000	1.28
+++ core/lang_api.php	11 Aug 2004 15:58:12 -0000
@@ -15,6 +15,9 @@
 	# lang_load call
 	$g_lang_strings = array();
 
+	# stack for language overrides
+	$g_lang_overrides = array();
+
 	# To be used in custom_strings_inc.php :
 	$g_active_language  = '';
 
@@ -66,7 +69,7 @@
 			$t_lang = user_pref_get_language( auth_get_current_user_id() );
 		}
 
-		# Otherwise fall back to defaule
+		# Otherwise fall back to default
 		if ( false === $t_lang ) {
 			$t_lang = config_get( 'default_language' );
 		}
@@ -128,6 +131,47 @@
 		}
 	}
 
+  # push a language onto the stack
+  function lang_push( $p_lang=null ) {
+		global $g_lang_overrides;
+
+  	# If no specific language is requested, we'll
+		#  try to determine the language from the users
+		#  preferences
+
+		$t_lang = $p_lang;
+
+		if ( null === $t_lang ) {
+			$t_lang = lang_get_default();
+		}
+
+		$g_lang_overrides[] = $t_lang;
+  }
+
+  # pop a language onto the stack and return it
+  function lang_pop( ) {
+		global $g_lang_overrides;
+
+		return array_pop( $g_lang_overrides );
+  }
+
+  # return value on top of the language stack
+  #  return default if stack is empty
+  function lang_peek( ) {
+		global $g_lang_overrides;
+
+		if (count($g_lang_overrides) > 0 ) {
+			$t_lang = $g_lang_overrides[ count( $g_lang_overrides ) - 1];
+		}else{
+			$t_lang = lang_get_default();
+		}
+		
+		return $t_lang;
+  }
+
+  
+
+
 	# ------------------
 	# Retrieves an internationalized string
 	#  This function will return one of (in order of preference):
@@ -143,11 +187,7 @@
 		$t_lang = $p_lang;
 
 		if ( null === $t_lang ) {
-			$t_lang = lang_get_default();
-		}
-
-		if ( 'auto' == $t_lang ) {
-			$t_lang = lang_map_auto();
+			$t_lang = lang_peek();
 		}
 
 		# Now we'll make sure that the requested language is loaded
@@ -186,11 +226,7 @@
 		$t_lang = $p_lang;
 
 		if ( null === $t_lang ) {
-			$t_lang = lang_get_default();
-		}
-
-		if ( 'auto' == $t_lang ) {
-			$t_lang = lang_map_auto();
+			$t_lang = lang_peek();
 		}
 
 		# Now we'll make sure that the requested language is loaded
lang.diff (13,970 bytes)   
lang.tar.gz (14,029 bytes)

Relationships

has duplicate 0004017 closedint2str Random translations popping up 
child of 0003987 closedvboctor Mantis 0.19.0 Release 

Activities

goemon1

goemon1

2004-07-20 16:37

reporter   ~0006187

seconded. this is very annoying! i am getting all updates to 0003969 in italian, even though my preferences in mantis are english.

vboctor

vboctor

2004-07-20 17:43

manager   ~0006190

I am getting them too.

vboctor

vboctor

2004-08-01 03:31

manager   ~0006516

A string was applied to calls to lang_get_defaulted() in email_api.php which fixed part of the problem. However, currently there is still a problem with enumerations being included in emails in the wrong language.

vboctor

vboctor

2004-08-02 06:03

manager   ~0006547

Also relationship information is sometimes in the wrong language.

jlatour

jlatour

2004-08-06 11:27

reporter   ~0006713

How difficult is it to fix this?

thraxisp

thraxisp

2004-08-09 14:39

reporter   ~0006885

I took a quick look at cause. It seems that the translation of the enums doesn't handle languages well. I expect it to be a few hours work. I'll probably have time tomorrow to work on it.

thraxisp

thraxisp

2004-08-10 18:00

reporter   ~0006916

I've attached a patch that I have tested to the best of my ability since I generally only use english.

The patch allowes the email formatting to override the language settings at a lower level that was originally being done. There were several other routines like get_enum_element that needed language bypassing. The patch to lang_api seemed most efficient.

jlatour

jlatour

2004-08-10 18:27

reporter   ~0006917

Ugh, that seems ugly. We can do it as a temporary solution for 0.19.0, but leave this issue open until we can do it the proper way? Let's set it for 0.20.0 if it's that big of a rewrite.

By the way, take another look at spacing in the patch and use 'null !== ' instead of 'NULL <>'?

thraxisp

thraxisp

2004-08-10 20:01

reporter   ~0006919

I started down an alternative path patching all calls to get_enum_element, history_localize_item, ... to pass in the local language. The change was quite extensive.

jlatour

jlatour

2004-08-11 03:23

reporter   ~0006920

Still, that might be the way to go. This seems very much like a hack to me.

Any other opinions?

thraxisp

thraxisp

2004-08-11 11:09

reporter   ~0006942

The new language stack implementation is attached. Most of the code is in lang_api.php. The changes in email_api.php are to use the new api. The change in error_api.php is to flust any language overrides before printing the errors.

Please review and I'll commit the changes.

thraxisp

thraxisp

2004-08-15 17:20

reporter   ~0006994

fixed in CVS.