(struct MInputContext): Fix typo in comment.
[m17n/m17n-lib.git] / src / language.c
index c27fd29..b31eeeb 100644 (file)
@@ -1,5 +1,5 @@
 /* language.c -- language (and script) module.
-   Copyright (C) 2003, 2004, 2006
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    02111-1307, USA.  */
 
 #include <config.h>
 #include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <locale.h>
 #include "m17n.h"
 #include "m17n-misc.h"
 #include "internal.h"
@@ -34,6 +37,7 @@
 
 static MPlist *language_list;
 static MPlist *script_list;
+static MPlist *langname_list;
 
 static MPlist *
 load_lang_script_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
@@ -45,18 +49,18 @@ load_lang_script_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
       || ! (plist = mdatabase_load (mdb)))
     return NULL;
   /* Check at least if the plist is ((SYMBOL ...) ...).  */
-  MPLIST_DO (pl, plist)
+  for (pl = plist; ! MPLIST_TAIL_P (pl);)
     {
       if (! MPLIST_PLIST_P (pl))
-       break;
-      p = MPLIST_PLIST (pl);
-      if (! MPLIST_SYMBOL_P (p))
-       break;
-    }
-  if (! MPLIST_TAIL_P (pl))
-    {
-      M17N_OBJECT_UNREF (plist);
-      return NULL;
+       mplist__pop_unref (pl);
+      else
+       {
+         p = MPLIST_PLIST (pl);
+         if (! MPLIST_SYMBOL_P (p))
+           mplist__pop_unref (pl);
+         else
+           pl = MPLIST_NEXT (pl);
+       }
     }
   return plist;
 }
@@ -88,21 +92,71 @@ init_script_list (void)
   return 0;
 }
 
+static MPlist *
+load_lang_name (MSymbol target3, MSymbol target2)
+{
+  MPlist *plist, *pl, *p;
+
+  plist = mplist ();
+  mplist_add (plist, Msymbol, target3);
+  pl = mdatabase_list (Mlanguage, Mname, target3, Mnil);
+  if (! pl && target2 != Mnil)
+    pl = mdatabase_list (Mlanguage, Mname, target2, Mnil);
+  if (pl)
+    {
+      MPLIST_DO (p, pl)
+       {
+         MDatabase *mdb = MPLIST_VAL (p);
+         MPlist *p0 = mdatabase_load (mdb), *p1, *territories;
+         MSymbol script = mdatabase_tag (mdb)[3];
+         
+         if (MPLIST_PLIST_P (p0))
+           {
+             p1 = MPLIST_PLIST (p0);
+             if (MPLIST_SYMBOL_P (p1) && MPLIST_SYMBOL (p1) == Mlanguage)
+               {
+                 p1 = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (p1))));
+                 territories = p1;
+                 while (! MPLIST_TAIL_P (p1))
+                   {
+                     if (MPLIST_SYMBOL_P (p1))
+                       p1 = MPLIST_NEXT (p1);
+                     else
+                       mplist__pop_unref (p1);
+                   }
+                 M17N_OBJECT_REF (territories);
+                 mplist__pop_unref (p0);
+               }
+             else
+               territories = mplist ();
+             mplist_push (p0, Mplist, territories);
+             M17N_OBJECT_UNREF (territories);
+             mplist_push (p0, Msymbol, script);
+             mplist_add (plist, Mplist, p0);
+             M17N_OBJECT_UNREF (p0);
+           }
+       }
+      M17N_OBJECT_UNREF (pl);
+    }
+  mplist_push (langname_list, Mplist, plist);
+  M17N_OBJECT_UNREF (plist);
+  return plist;
+}
+
 \f
 /* Internal API */
 
 int
 mlang__init ()
 {
-  Mlanguage = msymbol ("language");
-  msymbol_put (Mlanguage, Mtext_prop_serializer,
-              (void *) msymbol__serializer);
-  msymbol_put (Mlanguage, Mtext_prop_deserializer,
-              (void *) msymbol__deserializer);
+  msymbol_put_func (Mlanguage, Mtext_prop_serializer,
+                   M17N_FUNC (msymbol__serializer));
+  msymbol_put_func (Mlanguage, Mtext_prop_deserializer,
+                   M17N_FUNC (msymbol__deserializer));
   Miso639_2 = msymbol ("iso639-2");
   Miso639_1 = msymbol ("iso639-1");
 
-  language_list = script_list = NULL;
+  language_list = script_list = langname_list = NULL;
   return 0;
 }
 
@@ -110,9 +164,8 @@ void
 mlang__fini (void)
 {
   M17N_OBJECT_UNREF (language_list);
-  language_list = NULL;
   M17N_OBJECT_UNREF (script_list);
-  script_list = NULL;
+  M17N_OBJECT_UNREF (langname_list);
 }
 
 /*=*/
@@ -164,19 +217,25 @@ mlanguage__info (MSymbol language)
     {
       MPlist *pl = MPLIST_PLIST (plist);
 
+      if (MPLIST_SYMBOL (pl) == language)
+       return pl;
+      if (MPLIST_TAIL_P (pl))
+       continue;
+      pl = MPLIST_NEXT (pl);
       if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == language)
        return MPLIST_PLIST (plist);
-      if (! MPLIST_TAIL_P (pl))
+      if (MPLIST_TAIL_P (pl))
+       continue;
+      pl = MPLIST_NEXT (pl);
+      if (MPLIST_MTEXT_P (pl))
        {
-         pl = MPLIST_NEXT (pl);
-         if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == language)
+         MText *mt = MPLIST_MTEXT (pl);
+
+         if (mtext_nbytes (mt) == MSYMBOL_NAMELEN (language)
+             && strncasecmp ((char *) MTEXT_DATA (MPLIST_MTEXT (pl)),
+                             MSYMBOL_NAME (language),
+                             MSYMBOL_NAMELEN (language)) == 0)
            return MPLIST_PLIST (plist);
-         if (! MPLIST_TAIL_P (pl))
-           {
-             pl = MPLIST_NEXT (pl);
-             if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == language)
-               return MPLIST_PLIST (plist);
-           }
        }
     }
   return NULL;
@@ -258,11 +317,21 @@ mscript__from_otf_tag (MSymbol otf_tag)
          && (p = MPLIST_NEXT (p)) /* char list */
          && ! MPLIST_TAIL_P (p)
          && (p = MPLIST_NEXT (p)) /* otf tag */
-         && MPLIST_SYMBOL_P (p)
-         && otf_tag == MPLIST_SYMBOL (p))
+         && ! MPLIST_TAIL_P (p))
        {
-         script = MPLIST_SYMBOL (pl);
-         break;
+         if (MPLIST_SYMBOL_P (p))
+           {
+             if (otf_tag == MPLIST_SYMBOL (p))
+                 return MPLIST_SYMBOL (pl);
+           }
+         else if (MPLIST_PLIST (p))
+           {
+             MPlist *p0;
+
+             MPLIST_DO (p0, MPLIST_PLIST (p))
+               if (MPLIST_SYMBOL_P (p0) && otf_tag == MPLIST_SYMBOL (p0))
+                 return MPLIST_SYMBOL (pl);
+           }
        }
     }
   return script;
@@ -292,15 +361,15 @@ MSymbol Miso639_1, Miso639_2;
     mscript_list ().  */
 
 /***ja
-    @brief 3\e$BJ8;z8@8l%3!<%I$r%j%9%H$9$k\e(B.
+    @brief 3ʸ»ú¸À¸ì¥³¡¼¥É¤ò¥ê¥¹¥È¤¹¤ë.
 
-    \e$B4X?t\e(B mlanguage_list () \e$B$O!"@07A<0\e(B (well-formed) plist \e$B$rJV$9!#3F%-!<\e(B
-    \e$B$O\e(B #Msymbol \e$B$G$"$j!"8D!9$NCM$O\e(B ISO639-2 \e$B$KDj$a$i$l$?\e(B3\e$BJ8;z8@8l%3!<\e(B
-    \e$B%I$rL>A0$H$9$k%7%s%\%k$G$"$k!#\e(B
+    ´Ø¿ô mlanguage_list () ¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼
+    ¤Ï #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϠISO639-2 ¤ËÄê¤á¤é¤ì¤¿3ʸ»ú¸À¸ì¥³¡¼
+    ¥É¤ò̾Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
 
     @return
-    \e$B$3$N4X?t$,JV$9\e(B plist \e$B$O!"8F$S=P$7B&$,\e(B m17n_object_unref () \e$B$r;H$C\e(B
-    \e$B$F2rJ|$9$kI,MW$,$"$k!#\e(B
+    ¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ plist ¤Ï¡¢¸Æ¤Ó½Ð¤·Â¦¤¬ m17n_object_unref () ¤ò»È¤Ã
+    ¤Æ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£
 
     @seealso
     mscript_list ().  */
@@ -343,25 +412,25 @@ mlanguage_list (void)
     symbol.  Otherwise, it returns #Mnil.
 
     @seealso
-    mlanguage_name (), mlanguage_text ().  */
+    mlanguage_name_list (), mlanguage_text ().  */
 
 /***ja
-    @brief \e$B8@8l%3!<%I$rF@$k\e(B.
+    @brief ¸À¸ì¥³¡¼¥É¤òÆÀ¤ë.
 
-    \e$B4X?t\e(B mlanguage_code () \e$B$O!"\e(B$LANGUAGE \e$B$KBP1~$7$?\e(B ISO-639 \e$B8@8l%3!<%I\e(B
-    \e$B$,L>A0$G$"$k$h$&$J%7%s%\%k$rJV$9!#\e(B$LANGUAGE \e$B$O%7%s%\%k$G$"$j!"$=$N\e(B
-    \e$BL>A0$O!"\e(BISO639-2 3\e$BJ8;z8@8l%3!<%I!"\e(BISO639-1 2\e$BJ8;z8@8l%3!<%I!"1Q8lL>!"\e(B
-    \e$B$N$$$:$l$+$G$"$k!#\e(B
+    ´Ø¿ô mlanguage_code () ¤Ï¡¢$LANGUAGE ¤ËÂбþ¤·¤¿ ISO-639 ¸À¸ì¥³¡¼¥É
+    ¤¬Ì¾Á°¤Ç¤¢¤ë¤è¤¦¤Ê¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£$LANGUAGE ¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¤½¤Î
+    Ì¾Á°¤Ï¡¢ISO639-2 3ʸ»ú¸À¸ì¥³¡¼¥É¡¢ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¡¢±Ñ¸ì̾¡¢
+    ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
 
-    $LEN \e$B$OJV$5$l$k8@8l%3!<%I$N<oN`$r7hDj$9$k!#\e(B$LEN \e$B$,\e(B3\e$B$N>l9g$O\e(B 
-    ISO639-2 3\e$BJ8;z8@8l%3!<%I$,JV$5$l$k!#\e(B2\e$B$N>l9g$O!"$b$7Dj5A$5$l$F$$$l\e(B
-    \e$B$P\e(B ISO639-1 2\e$BJ8;z8@8l%3!<%I$,!"$=$&$G$J$1$l$P\e(B #Mnil \e$B$,JV$5$l$k!#\e(B0 
-    \e$B$N>l9g$O!"$b$7Dj5A$5$l$F$$$l$P\e(B2\e$BJ8;z%3!<%I$,!"$=$&$G$J$1$l$P\e(B3\e$BJ8;z%3!<\e(B
-    \e$B%I$,JV$5$l$k!#\e(B
+    $LEN ¤ÏÊÖ¤µ¤ì¤ë¸À¸ì¥³¡¼¥É¤Î¼ïÎà¤ò·èÄꤹ¤ë¡£$LEN ¤¬3¤Î¾ì¹ç¤Ï 
+    ISO639-2 3ʸ»ú¸À¸ì¥³¡¼¥É¤¬ÊÖ¤µ¤ì¤ë¡£2¤Î¾ì¹ç¤Ï¡¢¤â¤·ÄêµÁ¤µ¤ì¤Æ¤¤¤ì
+    ¤Ð ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¤¬¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤¬ÊÖ¤µ¤ì¤ë¡£0 
+    ¤Î¾ì¹ç¤Ï¡¢¤â¤·ÄêµÁ¤µ¤ì¤Æ¤¤¤ì¤Ð2ʸ»ú¥³¡¼¥É¤¬¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð3ʸ»ú¥³¡¼
+    ¥É¤¬ÊÖ¤µ¤ì¤ë¡£
 
     @return
-    \e$B$b$7>pJs$,F@$i$l$l$P!"$3$N4X?t$O\e(B #Mnil \e$B0J30$N%7%s%\%k$rJV$9!#$=$&\e(B
-    \e$B$G$J$1$l$P\e(B #Mnil \e$B$rJV$9!#\e(B
+    ¤â¤·¾ðÊó¤¬ÆÀ¤é¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï #Mnil °Ê³°¤Î¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦
+    ¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤¹¡£
 
     @seealso
     mlanguage_name (), mlanguage_text ().  */
@@ -388,48 +457,156 @@ mlanguage_code (MSymbol language, int len)
 /*=*/
 
 /***en
-    @brief Get an English language name.
+    @brief Return the language names written in the specified language.
 
-    The mlanguage_name () function returns a symbol whose name is an
-    English name of $LANGUAGE.  $LANGUAGE is a symbol whose name is an
-    ISO639-2 3-letter language code, an ISO639-1 2-letter language
-    codes, or an English word.
+    The mlanguage_name_list () function returns a plist of LANGUAGE's
+    names written in TARGET language.  SCRIPT and TERRITORY, if not #Mnil,
+    specifies which script and territory to concern at first.
 
-    @return
-    If the information is available, this function returns a non-#Mnil
-    symbol.  Otherwise, it returns #Mnil.
+    LANGUAGE and TARGET must be a symbol whose name is an ISO639-2
+    3-letter language code or an ISO639-1 2-letter language codes.
+    TARGET may be #Mnil, in which case, the language of the current
+    locale is used.  If locale is not set or is C, English is used.
 
-    @seealso
-    mlanguage_code (), mlanguage_text ().  */
+    SCRIPT and TERRITORY must be a symbol whose name is a script and
+    territory name of a locale (e.g. "TW", "SG") respectively.
 
-/***ja
-    @brief \e$B8@8l$N1Q8lL>$rF@$k\e(B.
+    @return
+    If the translation is available, this function returns a non-empty
+    plist.  The first element has key #MText and the value is an
+    M-text of a translated language name.  If the succeeding elements
+    also have key #MText, their values are M-texts of alternate
+    translations.
 
-    \e$B4X?t\e(B mlanguage_name () \e$B$O!"\e(B$LANGUAGE \e$B$N1Q8lL>$rL>A0$H$9$k$h$&$J%7\e(B
-    \e$B%s%\%k$rJV$9!#\e(B$LANGUAGE \e$B$O%7%s%\%k$G$"$j!"$=$NL>A0$O!"\e(BISO639-2 3\e$BJ8\e(B
-    \e$B;z8@8l%3!<%I!"\e(BISO639-1 2\e$BJ8;z8@8l%3!<%I!"1Q8lL>!"$N$$$:$l$+$G$"$k!#\e(B
+    If no translation is available, @c NULL is returned.
 
-    @return
-    \e$B5a$a$F$$$k>pJs$,F@$i$l$k$J$i!"$3$N4X?t$O\e(B #Mnil \e$B0J30$N%7%s%\%k$rJV\e(B
-    \e$B$9!#$=$&$G$J$1$l$P\e(B #Mnil \e$B$rJV$9!#\e(B
+    The returned plist should not be modified nor freed.
 
     @seealso
     mlanguage_code (), mlanguage_text ().  */
 
-MSymbol
-mlanguage_name (MSymbol language)
+MPlist *
+mlanguage_name_list (MSymbol language, MSymbol target,
+                    MSymbol script, MSymbol territory)
 {
-  MPlist *plist = mlanguage__info (language);
+  MPlist *plist, *pl;
+  MSymbol language2, target2;
 
-  if (! plist)                 /* 3-letter code */
-    return Mnil;
-  plist = MPLIST_NEXT (plist); /* 2-letter code */
+  plist = mlanguage__info (language);
+  if (! plist)
+    return NULL;
+  language = MPLIST_SYMBOL (plist);
+  language2 = MPLIST_SYMBOL (MPLIST_NEXT (plist));
+  if (target != Mnil)
+    {
+      plist = mlanguage__info (target);
+      if (! plist)
+       return NULL;
+      target = MPLIST_SYMBOL (plist);
+      target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist));
+    }
+  else
+    {
+      MLocale *locale = mlocale_set (LC_MESSAGES, NULL);
+
+      if (! locale)
+       {
+         target = msymbol ("eng");
+         target2 = msymbol ("en");
+         script = territory = Mnil;
+       }
+      else
+       {
+         target = mlocale_get_prop (locale, Mlanguage);
+         plist = mlanguage__info (target);
+         if (! plist)
+           return NULL;
+         target = MPLIST_SYMBOL (plist);
+         target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist));
+         script = mlocale_get_prop (locale, Mscript);
+         territory = mlocale_get_prop (locale, Mterritory);
+       }
+    }
+
+  /* Now both LANGUAGE and TARGET are 3-letter codes.  */
+  if (! langname_list)
+    langname_list = mplist ();
+  plist = mplist__assq (langname_list, target);
+  if (plist)
+    plist = MPLIST_PLIST (plist);
+  else
+    plist = load_lang_name (target, target2);
+
+  /* PLIST = (TARGET (SCRIPT (TERRITORY ...) (LANG-CODE NAME ...) ...) ...) */
+  plist = MPLIST_NEXT (plist);
   if (MPLIST_TAIL_P (plist))
-    return Mnil;
-  plist = MPLIST_NEXT (plist); /* english name */
-  if (! MPLIST_SYMBOL_P (plist))
-    return Mnil;
-  return MPLIST_SYMBOL (plist);
+    return NULL;
+
+  MPLIST_DO (pl, plist)
+    {
+      MPlist *p = MPLIST_PLIST (pl), *p0;
+
+      if (MPLIST_SYMBOL (p) == script
+         && (territory == Mnil
+             || mplist_find_by_value (MPLIST_PLIST (MPLIST_NEXT (p)),
+                                      territory))
+         && (p = MPLIST_NEXT (MPLIST_NEXT (p)))
+         && ((p0 = mplist__assq (p, language))
+             || (p0 = mplist__assq (p, language2))))
+       {
+         plist = p0;
+         break;
+       }
+    }
+  if (MPLIST_TAIL_P (pl))
+    {
+      MPLIST_DO (pl, plist)
+       {
+         MPlist *p = MPLIST_NEXT (MPLIST_PLIST (pl)), *p0;
+
+         if ((territory == Mnil
+              || mplist_find_by_value (MPLIST_VAL (p), territory))
+             && (p = MPLIST_NEXT (MPLIST_NEXT (p)))
+             && ((p0 = mplist__assq (p, language))
+                 || (p0 = mplist__assq (p, language2))))
+           {
+             plist = p0;
+             break;
+           }
+       }
+      if (MPLIST_TAIL_P (pl))
+       {
+         MPLIST_DO (pl, plist)
+           {
+             MPlist *p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (pl))), *p0;
+
+             if ((p0 = mplist__assq (p, language))
+                 || (p0 = mplist__assq (p, language2)))
+               {
+                 plist = p0;
+                 break;
+               }
+           }
+         if (MPLIST_TAIL_P (pl))
+           return NULL;
+       }
+    }
+
+  plist = MPLIST_NEXT (MPLIST_PLIST (plist));
+  if (territory != Mnil)
+    {
+      MPLIST_DO (pl, MPLIST_NEXT (plist))
+       if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == territory)
+         break;
+      if (! MPLIST_TAIL_P (pl)
+         && (pl = MPLIST_NEXT (pl))
+         && MPLIST_MTEXT_P (pl))
+       return pl;
+    }
+  MPLIST_DO (plist, plist)
+    if (MPLIST_MTEXT_P (plist))
+      break;
+  return (MPLIST_MTEXT_P (plist) ? plist : NULL);
 }
 
 /*=*/
@@ -453,16 +630,16 @@ mlanguage_name (MSymbol language)
     mlanguage_code (), mlanguage_name ().  */
 
 /***ja
-    @brief \e$BM?$($i$l$?8@8l<+?H$G=q$+$l$?8@8lL>$rJV$9\e(B.
+    @brief Í¿¤¨¤é¤ì¤¿¸À¸ì¼«¿È¤Ç½ñ¤«¤ì¤¿¸À¸ì̾¤òÊÖ¤¹.
 
-    \e$B4X?t\e(B mlanguage_text () \e$B$O!"8@8l\e(B $LANGUAGE \e$B$G=q$+$l$?\e(B $LANGUAGE \e$B$N\e(B
-    \e$BL>A0$r\e(B M-text \e$B$N7A<0$GJV$9!#$=$N8@8l$NBeI=E*$JJ8;z$,$o$+$C$F$$$k>l\e(B
-    \e$B9g$O!"JV$5$l$k\e(B M-text \e$B$N3FJ8;z$K!"%-!<$,\e(B #Mtext \e$B$GCM$,$=$NBeI=E*$J\e(B
-    \e$BJ8;z$r4^$`\e(B M-text \e$B$G$"$k$h$&$J%F%-%9%H%W%m%Q%F%#$,IU2C$5$l$k!#\e(B
+    ´Ø¿ô mlanguage_text () ¤Ï¡¢¸À¸ì $LANGUAGE ¤Ç½ñ¤«¤ì¤¿ $LANGUAGE ¤Î
+    Ì¾Á°¤ò M-text ¤Î·Á¼°¤ÇÊÖ¤¹¡£¤½¤Î¸À¸ì¤ÎÂåɽŪ¤Êʸ»ú¤¬¤ï¤«¤Ã¤Æ¤¤¤ë¾ì
+    ¹ç¤Ï¡¢ÊÖ¤µ¤ì¤ë M-text ¤Î³Æʸ»ú¤Ë¡¢¥­¡¼¤¬ #Mtext ¤ÇÃͤ¬¤½¤ÎÂåɽŪ¤Ê
+    Ê¸»ú¤ò´Þ¤à M-text ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬Éղ䵤ì¤ë¡£
 
     @return
-    \e$B5a$a$k>pJs$,F@$i$l$?>l9g!"$3$N4X?t$,JV$9\e(B M-text \e$B$rJQ99$7$?$j2rJ|$7\e(B
-    \e$B$?$j$7$F$O$$$1$J$$!#>pJs$,F@$i$l$J$+$C$?>l9g$O\e(B @c NULL \e$B$,JV$5$l$k!#\e(B
+    µá¤á¤ë¾ðÊó¤¬ÆÀ¤é¤ì¤¿¾ì¹ç¡¢¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ M-text ¤òÊѹ¹¤·¤¿¤ê²òÊü¤·
+    ¤¿¤ê¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¡£¾ðÊó¤¬ÆÀ¤é¤ì¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤¬ÊÖ¤µ¤ì¤ë¡£
 
     @seealso
     mlanguage_code (), mlanguage_name ().  */
@@ -509,15 +686,15 @@ mlanguage_text (MSymbol language)
     mscript_language_list (), mlanguage_list ().  */
 
 /***ja
-    @brief \e$B%9%/%j%W%HL>$r%j%9%H$9$k\e(B.
+    @brief ¥¹¥¯¥ê¥×¥È̾¤ò¥ê¥¹¥È¤¹¤ë.
 
-    \e$B4X?t\e(B mscript_list () \e$B$O!"@07A<0\e(B (well-formed) plist \e$B$rJV$9!#3F%-!<\e(B
-    \e$B$O\e(B #Msymbol \e$B$G$"$j!"8D!9$NCM$O%9%/%j%W%HL>$rL>A0$H$9$k%7%s%\%k$G$"\e(B
-    \e$B$k!#\e(B
+    ´Ø¿ô mscript_list () ¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼
+    ¤Ï #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϥ¹¥¯¥ê¥×¥È̾¤ò̾Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢
+    ¤ë¡£
 
     @return
-    \e$B$3$N4X?t$,JV$9\e(B plist \e$B$O!"8F$S=P$7B&$,\e(B m17n_object_unref () \e$B$r;H$C\e(B
-    \e$B$F2rJ|$9$kI,MW$,$"$k!#\e(B
+    ¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ plist ¤Ï¡¢¸Æ¤Ó½Ð¤·Â¦¤¬ m17n_object_unref () ¤ò»È¤Ã
+    ¤Æ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£
 
     @seealso
     mscript_language_list (), mlanguage_list ().  */
@@ -561,17 +738,18 @@ mscript_list (void)
     mscript_list (), mlanguage_list ().  */
 
 /***ja
-    @brief \e$BM?$($i$l$?%9%/%j%W%H$rMQ$$$k8@8l$r%j%9%H$9$k\e(B.
+    @brief Í¿¤¨¤é¤ì¤¿¥¹¥¯¥ê¥×¥È¤òÍѤ¤¤ë¸À¸ì¤ò¥ê¥¹¥È¤¹¤ë.
 
-    \e$B4X?t\e(B mscript_language_list () \e$B$O!"\e(B$SCRIPT \e$B$rMQ$$$k8@8l$r%j%9%H$9$k!#\e(B
-    $SCRIPT \e$B$O%7%s%\%k$G!"$=$NL>A0$O\e(B Unicode Character Database \e$B$K<($5\e(B
-    \e$B$l$F$$$k%9%/%j%W%HL>$r$9$Y$F>.J8;z$K$7$?$b$N$G$"$k!#\e(B
+    ´Ø¿ô mscript_language_list () ¤Ï¡¢$SCRIPT ¤òÍѤ¤¤ë¸À¸ì¤ò¥ê¥¹¥È¤¹¤ë¡£
+    $SCRIPT ¤Ï¥·¥ó¥Ü¥ë¤Ç¡¢¤½¤Î̾Á°¤Ï Unicode Character Database ¤Ë¼¨¤µ
+    ¤ì¤Æ¤¤¤ë¥¹¥¯¥ê¥×¥È̾¤ò¤¹¤Ù¤Æ¾®Ê¸»ú¤Ë¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£
 
-    @return \e$B$3$N4X?t$O!"@07A<0\e(B (well-formed) plist \e$B$rJV$9!#3F%-!<$O\e(B 
-    #Msymbol \e$B$G$"$j!"8D!9$NCM$O\e(B ISO639-1 \e$B$KDj$a$i$l$?\e(B2\e$BJ8;z8@8l%3!<%I\e(B
-    (\e$BDj5A$5$l$F$$$J$$>l9g$O\e(B ISO639-2 \e$B$KDj$a$i$l$?\e(B3\e$BJ8;z8@8l%3!<%I\e(B) \e$B$rL>\e(B
-    \e$BA0$H$9$k%7%s%\%k$G$"$k!#JV$5$l$k\e(B plist \e$B$OJQ99$7$?$j2rJ|$7$?$j$7$F\e(B
-    \e$B$O$J$i$J$$!#\e(B$SCRIPT \e$B$,L$CN$N>l9g$O\e(B @c NULL \e$B$,JV$5$l$k!#\e(B
+    @return 
+    ¤³¤Î´Ø¿ô¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼¤Ï 
+    #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϠISO639-1 ¤ËÄê¤á¤é¤ì¤¿2ʸ»ú¸À¸ì¥³¡¼¥É
+    (ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï ISO639-2 ¤ËÄê¤á¤é¤ì¤¿3ʸ»ú¸À¸ì¥³¡¼¥É) ¤ò̾
+    Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ÊÖ¤µ¤ì¤ë plist ¤ÏÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ
+    ¤Ï¤Ê¤é¤Ê¤¤¡£$SCRIPT ¤¬Ì¤ÃΤξì¹ç¤Ï @c NULL ¤¬ÊÖ¤µ¤ì¤ë¡£
 
     @seealso
     mscript_list (), mlanguage_list ().  */
@@ -588,3 +766,74 @@ mscript_language_list (MSymbol script)
     return MPLIST_PLIST (plist);
   return NULL;
 }
+
+/*** @} */
+/*=*/
+/***en
+    @name Obsolete functions
+*/
+/***ja
+    @name Obsolete ¤Ê´Ø¿ô
+*/
+/*** @{ */
+
+/***en
+    @brief Get an English language name.
+
+    This function is obsolete.  Use mlanguage_name_list () instead.
+
+    The mlanguage_name () function returns a symbol whose name is an
+    English name of $LANGUAGE.  $LANGUAGE is a symbol whose name is an
+    ISO639-2 3-letter language code, an ISO639-1 2-letter language
+    codes, or an English word.
+
+    @return
+    If the information is available, this function returns a non-#Mnil
+    symbol.  Otherwise, it returns #Mnil.
+
+    @seealso
+    mlanguage_code (), mlanguage_text ().  */
+
+/***ja
+    @brief ¸À¸ì¤Î±Ñ¸ì̾¤òÆÀ¤ë.
+
+    ´Ø¿ô mlanguage_name () ¤Ï¡¢$LANGUAGE ¤Î±Ñ¸ì̾¤ò̾Á°¤È¤¹¤ë¤è¤¦¤Ê¥·
+    ¥ó¥Ü¥ë¤òÊÖ¤¹¡£$LANGUAGE ¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¤½¤Î̾Á°¤Ï¡¢ISO639-2 3ʸ
+    »ú¸À¸ì¥³¡¼¥É¡¢ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¡¢±Ñ¸ì̾¡¢¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
+
+    @return
+    µá¤á¤Æ¤¤¤ë¾ðÊó¤¬ÆÀ¤é¤ì¤ë¤Ê¤é¡¢¤³¤Î´Ø¿ô¤Ï #Mnil °Ê³°¤Î¥·¥ó¥Ü¥ë¤òÊÖ
+    ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤¹¡£
+
+    @seealso
+    mlanguage_code (), mlanguage_text ().  */
+
+MSymbol
+mlanguage_name (MSymbol language)
+{
+  MPlist *plist = mlanguage__info (language);
+  MText *mt;
+  char *str;
+
+  if (! plist)                 /* 3-letter code */
+    return Mnil;
+  plist = MPLIST_NEXT (plist); /* 2-letter code */
+  if (MPLIST_TAIL_P (plist))
+    return Mnil;
+  plist = MPLIST_NEXT (plist); /* english name */
+  if (! MPLIST_MTEXT_P (plist))
+    return Mnil;
+  mt = MPLIST_MTEXT (plist);
+  str = alloca (mtext_nbytes (mt));
+  memcpy (str, MTEXT_DATA (mt), mtext_nbytes (mt));
+  str[0] = tolower (str[0]);
+  return msymbol__with_len (str, mtext_nbytes (mt));
+}
+
+/*=*/
+
+/*
+  Local Variables:
+  coding: euc-japan
+  End:
+*/