[LON-CAPA-cvs] cvs: loncom /homework structuretags.pm

foxr foxr at source.lon-capa.org
Tue Dec 27 15:13:22 EST 2011


foxr		Tue Dec 27 20:13:22 2011 EDT

  Modified files:              
    /loncom/homework	structuretags.pm 
  Log:
  BZ6490 - Merged back in to Trunk...fixed error as well that would emit 
  \selectlanguage after a translation block even with web targets.
  
  
  
-------------- next part --------------
Index: loncom/homework/structuretags.pm
diff -u loncom/homework/structuretags.pm:1.499 loncom/homework/structuretags.pm:1.500
--- loncom/homework/structuretags.pm:1.499	Tue Dec 20 22:46:40 2011
+++ loncom/homework/structuretags.pm	Tue Dec 27 20:13:22 2011
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA 
 # definition of tags that give a structure to a document
 #
-# $Id: structuretags.pm,v 1.499 2011/12/20 22:46:40 raeburn Exp $
+# $Id: structuretags.pm,v 1.500 2011/12/27 20:13:22 foxr Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -61,6 +61,7 @@
 use Apache::lonxml;
 use Apache::londefdef;
 use Apache::lonenc();
+use Apache::loncommon();
 use Time::HiRes qw( gettimeofday tv_interval );
 use lib '/home/httpd/lib/perl/';
 use LONCAPA;
@@ -69,6 +70,105 @@
     &Apache::lonxml::register('Apache::structuretags',('block','languageblock','translated','instructorcomment','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','problemtype','startpartmarker','startouttext','endpartmarker','endouttext','simpleeditbutton','definetag'));
 }
 
+
+#---------------------------------------------------------------------------------
+# 
+#  This section of code deals with hyphenation management.
+#  We must do three things:
+#  - keep track fo the desired languages to alter the header.
+#  - provide hyphenation selection as needed by each language that appears in the
+#    text.
+#  - Provide the header text needed to make available the desired hyphenations.
+#
+#
+
+# Hash whose keys are the languages encountered in the document/resource.
+#
+
+my %languages_required;
+##
+#   Given a language selection as input returns a chunk of LaTeX that
+#   selects the required hyphenator.
+#
+#  @param language - the language being selected.
+#  @return string
+#  @retval The LaTeX needed to select the hyphenation appropriate to the language. 
+#   
+sub select_hyphenation {
+    my $language  = shift;
+
+    $language = &Apache::loncommon::latexlanguage($language); # Translate -> latex language.
+
+    # If there is no latex language there's not much we can do:
+
+    if ($language) {
+	&require_language($language);
+	my $babel_hyphenation = "\\selectlanguage{$language}";
+	
+	return $babel_hyphenation;
+    } else {
+	return '';
+    }
+}
+##
+# Selects hyphenation based on the current problem metadata.
+# This requires that
+# - There is a language metadata item set for the problem.
+# - The language has a latex/babel hyphenation.
+#
+# @note: Uses &Apache::lonxml::request to locate the Uri associated with
+#        this problem.
+# @return string (possibly empty).
+# @retval If not empty an appropriate \selectlanguage{} directive.
+#
+sub select_metadata_hyphenation {
+    my $uri      = $Apache::lonxml::request->uri;
+    my $language = &Apache::lonnet::metadata($uri, 'language'); 
+    my $latex_language = &Apache::loncommon::latexhyphenation($language);
+    if ($latex_language) {
+	return '\selectlanguage{'.$latex_language."}\n";
+    }
+    return '';			# no latex hyphenation or no lang metadata.
+}
+
+
+##
+#  Clears the set of languages required by the document being rendered.
+#
+sub clear_required_languages {
+    %languages_required = ();
+}
+##
+# Allows an external client of this module to register a need for a language:
+#
+# @param LaTeX language required:
+#
+sub require_language {
+    my $language = shift;
+    $languages_required{$language} = 1;
+}
+
+##
+# Provides the header for babel that indicates the languages
+# the document requires.
+# @return string
+# @retval \usepackage[lang1,lang2...]{babel}
+# @retval ''   if there are no languages_required.
+sub languages_header {
+    my $header    ='';
+    my @languages = (keys(%languages_required));
+
+    # Only generate the header if there are languages:
+
+    if (scalar @languages) {
+	my $language_list = join(',', (@languages));
+	$header  = '\usepackage['.$language_list."]{babel}\n";
+    }
+    return $header;
+}
+
+#----------------------------------------------------------------------------------
+
 sub start_web {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     if ($target ne 'edit' && $target ne 'modified') {
@@ -1228,6 +1328,8 @@
             }
 	} elsif ($target eq 'tex') {
 	    $result .= 'INSERTTEXFRONTMATTERHERE';
+	    $result .= &select_metadata_hyphenation();
+	    
 
 	}
     } elsif ($target eq 'edit') {
@@ -1284,6 +1386,7 @@
 	}
 	my $name_of_resourse= &Apache::lonxml::latex_special_symbols(&get_resource_name($parstack,$safeeval),'header');
 	my $begin_doc=' \typeout{STAMPOFPASSEDRESOURCESTART Resource <h2>"'.$name_of_resourse.'"</h2> located in <br /><small><b>'.$env{'request.uri'}.'</b></small><br /> STAMPOFPASSEDRESOURCEEND} \noindent ';
+	&clear_required_languages();
 	my $toc_line='\vskip 1 mm\noindent '.$startminipage.
 	    '\addcontentsline{toc}{subsection}{'.$name_of_resourse.'}';
 	
@@ -1558,54 +1661,101 @@
     }
     return $result;
 }
-
+#
+#  <languageblock [include='lang1,lang2...'] [exclude='lang1,lang2...']>
+#  ...
+#  </languageblock>
+#
+#   This declares the intent to provide content that can be rendered in the
+#   set of languages in the include specificatino but not in the exclude
+#   specification.  If a currently preferred language is in the include list
+#   the content in the <languageblock>...</languageblock> is rendered
+#   If the currently preferred language is in the exclude list,
+#   the content in the <languageblock>..></languageblock is not rendered.
+#
+#   Pathalogical case handling:
+#     - Include specified, without the preferred language but exclude  specified
+#       also without the preferred langauge results in rendering the block.
+#     - Exclude specified without include and excluden not containing a 
+#       preferred language renders the block.
+#     - Include and exclude both specifying the preferred language does not
+#       render the block.
+#     - If neither include/exclude is specified, the block gets rendered.
+#
+#  This tag has no effect when target is in {edit, modified}
+#
 sub start_languageblock {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
 
-    my $result;
+    my $result = '';
 
     if ($target eq 'web' || $target eq 'grade'   || $target eq 'answer' ||
 	$target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') {
 	my $include = $token->[2]->{'include'};
 	my $exclude = $token->[2]->{'exclude'};
         my @preferred_languages=&Apache::lonlocal::preferred_languages();
-# This should not even happen, since we should at least have the server language
-        if (!$preferred_languages[0]) { $preferred_languages[0]='en'; }
-# Now loop over all languages in order of preference
+
+        # This should not even happen, since we should at least have the server language
+
+        if (!$preferred_languages[0]) { 
+	    $preferred_languages[0]='en'; 
+	}
+
+        # Now loop over all languages in order of preference
+
+	my $render;
         foreach my $preferred_language (@preferred_languages) {
-# If the languageblock has no arguments, show the contents
-           $result=1;
+
+	    # If neither include/nor exlude is present the block is going
+	    # to get rendered.
+
            my $found=0;
-# Do we have an include argument?
+           $render=1;
+
+	   #  If include is specified,  don't render the block
+	   #  unless the preferred language is included in the set.
+
 	   if ($include) {
-# If include is specified, by default, don't render the block
-              $result=0;
+              $render=0;
               foreach my $included_language (split(/\,/,$include)) {
-# ... but if my preferred language is included, render it
                  if ($included_language eq $preferred_language) {
-                    $result=1; 
+                    $render=1; 
                     $found=1; 
+		    last;	# Only need to find the first.
                  }
               }
 	   }
-# Do we have an exclude argument?
+           # Do we have an exclude argument?
+	   # If so, and one of the languages matches a preferred language
+	   # inhibit rendering the block.  Note that in the pathalogical case the
+	   # author has specified a preferred language in both the include and exclude
+	   # attribte exclude is preferred.  
+
            if ($exclude) {
-              $result=1;
+              $render=1;
               foreach my $excluded_language (split(/\,/,$exclude)) {
                  if ($excluded_language eq $preferred_language) {
-                    $result=0;
+                    $render=0;
                     $found=1;
+		    last;	# Only need to find the first.
                  }
               }
 	   }
-           if ($found) { last; }
+           if ($found) { 
+	       last; 		# Done on any match of include or exclude.
+	   }
         }
-	if ( ! $result ) {
+	# If $render not true skip the entire block until </languageblock>
+	#
+
+	if ( ! $render ) {
 	    my $skip=&Apache::lonxml::get_all_text("/languageblock",$parser,
 						   $style);
 	    &Apache::lonxml::debug("skipping ahead :$skip: $$parser[-1]");
 	}
-	$result='';
+	# If $render is true, we've not skipped the contents of the <languageglock>
+	# and the normal loncapa processing flow will render it as a matter of course.
+
     } elsif ($target eq 'edit') {
 	$result .=&Apache::edit::tag_start($target,$token);
 	$result .=&Apache::edit::text_arg(&mt('Include Language:'),'include',
@@ -1630,9 +1780,47 @@
     }
     return $result;
 }
-
+#  languagblock specific tags:
 {
-    my %available_texts;
+    # For chunks of a resource that has translations, this hash contains
+    # the translations available indexed by language name.
+    #
+
+    my %available_texts;       
+
+    # <translated> starts a block of a resource that has multiple translations.
+    # See the <lang> tag as well.
+    # When </translated> is encountered if there is a translation for the 
+    # currently preferred language, that is rendered inthe web/tex/webgrade
+    # targets.  Otherwise, the default text is rendered.
+    #
+    # Note that <lang> is only registered for the duration of the 
+    #  <translated>...</translated> block 
+    #
+    # Pathalogical case handling:
+    #   - If there is no <lang> that specifies a 'default' and there is no
+    #     translation that matches a preferred language, nothing is rendered.
+    #   - Nested <translated>...</translated> might be linguistically supported by
+    #     XML due to the stack nature of tag registration(?) however the rendered
+    #     output will be incorrect because there is only one %available_texts
+    #     has and end_translated clears it.
+    #   - Material outside of a <lang>...</lang> block within the
+    #     <translated>...<translated> block won't render either e.g.:
+    #    <translated>
+    #      The following will be in your preferred langauge:
+    #      <lang which='en'>
+    #         This section in english
+    #      </lang>
+    #      <lang which='sgeiso'>
+    #         Hier es ist auf Deutsch.
+    #      </lang>
+    #      <lang which='sfriso'>
+    #         En Francais
+    #      </lang>
+    #    </translated>
+    #
+    #    The introductory text prior to the first <lang> tag is not rendered.
+    #
     sub start_translated {
 	my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
 	&Apache::lonxml::register('Apache::structuretags',('lang'));
@@ -1651,14 +1839,55 @@
 	    my @possibilities = keys(%available_texts);
 	    my $which = 
 		&Apache::loncommon::languages(\@possibilities) || 'default';
-	    $result = $available_texts{$which};
+	    if ($target eq 'tex') {
+		$result = &select_hyphenation($which);
+	    }
+	    $result .= $available_texts{$which};
+	    if ($target eq 'tex') {
+		$result .= &select_metadata_hyphenation(); # Restore original language.
+	    }
 	}
 	undef(%available_texts);
 	&Apache::lonxml::deregister('Apache::structuretags',('lang'));
 	return $result;
     }
 
-
+    # <lang [which='language-name'] [other='lang1,lang2...']>  
+    #  Specifies that the block contained within it is a translation 
+    #  for a specific language specified by the 'which' attribute. The
+    #   'other' attribute can be used by itself or in conjunction with
+    #   which to specify this tag _may_ be used as a translation for some
+    #   list of languages. e.g.:  <lang which='senisoUS' other='senisoCA,senisoAU,seniso'>
+    #   specifying that the block provides a translation for US (primary)
+    #   Canadian, Australian and UK Englush.
+    #   
+    # Comment: this seems a bit silly why not just support a list of languages
+    #           e.g. <lang which='l1,l2...'> and ditch the other attribute?
+    #
+    #  Effect:
+    #    The material within the <lang>..</lang> block is stored in the
+    #    specified set of $available_texts hash entries, the appropriate one
+    #    is selected at </translated> time.
+    #
+    #  Pathalogical case handling:
+    #    If a language occurs multiple times within a <translated> block,
+    #    only the last one is rendered e.g.:
+    #
+    #    <translated>
+    #       <lang which='senisoUS', other='senisoCA,senisoAU,seniso'>
+    #          Red green color blindness is quite common affecting about 7.8% of 
+    #          the male population, but onloy about .65% of the female population.
+    #       </lang>
+    #          Red green colour blindness is quite common affecting about 7.8% of 
+    #          the male population, but onloy about .65% of the female population.
+    #       <lang which='seniso', other='senisoCA,senisoAU'>
+    #     </translated>
+    #
+    #    renders the correct spelling of color (colour) for people who have specified
+    #    a preferred language that is one of the British Commonwealth languages
+    #    even though those are also listed as valid selections for the US english
+    #    <lang> block.
+    #
     sub start_lang {
 	my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
 	if ($target eq 'web' || $target eq 'grade'   || $target eq 'answer' ||
@@ -1689,7 +1918,8 @@
 	}
 	return '';
     }
-}
+}				# end langauge block specific tags.
+
 
 sub start_instructorcomment {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;


More information about the LON-CAPA-cvs mailing list