home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 13 / CDA13.ISO / DOC / HOWTO / MINI / LOCALES < prev    next >
Encoding:
Text File  |  1996-06-23  |  16.7 KB  |  455 lines

  1.   Locales mini-HOWTO
  2.   Peeter Joot, joot@ecf.toronto.edu
  3.   v1.3, 6 June 1996.
  4.  
  5.   This document describes how to set up your Linux machine to use
  6.   locales.
  7.  
  8.   1.  Introduction
  9.  
  10.   This is really a description of what I had to do to get localedef
  11.   installed, compile some locales, and try them out.  I did this just
  12.   for fun, and thought that perhaps some people would be interested in
  13.   trying it out themselves.  Once it is set up you should be able to use
  14.   NLS enabled applications with the locale of your choice.  After a
  15.   while, locale support should be part of the standard distributions,
  16.   and most of this mini-HOWTO will be redundant.
  17.  
  18.   2.  What is a "locale" anyhow?
  19.  
  20.   Locales encapsulate some of the language/culture specific things that
  21.   you shouldn't hard code in your programs.
  22.  
  23.   If you have various locales installed on your computer then you can
  24.   select via the following list of environment variables how a locale
  25.   sensitive program will behave.  The default locale is the C, or POSIX
  26.   locale which is hard coded in libc.
  27.  
  28.      LANG
  29.         This sets the locale, but can be overridden with any other
  30.         LC_xxxx environment variables
  31.  
  32.      LC_COLLATE
  33.         Sort order.
  34.  
  35.      LC_CTYPE
  36.         Character definitions, uppercase, lowercase, ...  These are used
  37.         by the functions like toupper, tolower, islower, isdigit, ...
  38.  
  39.      LC_MONETARY
  40.         Contains the information necessary to format money in the
  41.         fashion expected.  It has the definitions of things like the
  42.         thousands separator, decimal separator, and what the monetary
  43.         symbol is and how to position it.
  44.  
  45.      LC_NUMERIC
  46.         Thousands, and decimal separators, and the numeric grouping
  47.         expected.
  48.  
  49.      LC_TIME
  50.         How to specify the time, and date.  This has the things like the
  51.         days of the week, and months of the year in abbreviated, and non
  52.         abbreviated form.
  53.  
  54.      LC_MESSAGES
  55.         Yes, and No expressions.
  56.  
  57.      LC_ALL
  58.         This sets the locale, and overrides any other LC_xxxx
  59.         environment variables.
  60.  
  61.   Here are some other locales, and there are lots more.
  62.  
  63.      en_CA
  64.         English Canadian.
  65.  
  66.      en_US
  67.         US English.
  68.  
  69.      de_DE
  70.         Germany's German.
  71.  
  72.      fr_FR
  73.         France's French.
  74.  
  75.   If you are writing a program, and want to to be usable internationally
  76.   you should utilize locales.  The most glaring reason for this is that
  77.   not everybody is going to use the same character set/code page as you.
  78.  
  79.   Make sure in your programs that you don't do things like
  80.  
  81.        /* check for alphabetic characters */
  82.        if ( (( c >= 'a') && ( c <= 'z' )) ||
  83.             (( c >= 'A') && ( c <= 'Z' )) ) { ... }
  84.  
  85.   If you write that type of code your program assumes that the
  86.   user/file/... is ASCII and nothing but ASCII, and it does not respect
  87.   the code page definitions of the user's locale.  For example it
  88.   preludes characters such as a-umelaut which would be used in a German
  89.   environment.  What you should do instead is use the locale sensitive
  90.   functions like isalpha().  If your program does expliticly require use
  91.   of only US-ASCII alphabetics, you still use the isalpha() function,
  92.   but you must also either do setlocale(LC_CTYPE,"C") or set the LANG,
  93.   LC_CTYPE, or LC_ALL environment variables to "C".
  94.  
  95.   Locales allow a large degree of flexibility and make certain
  96.   assumptions that a programmer may have made in ASCII based C programs
  97.   invalid.
  98.  
  99.   For instance, you cannot assume the code positions of characters.
  100.   There is nothing stopping you from creating a charmap file that
  101.   defines the code position of 'A' to be 0xC1 rather than 0x41.  This is
  102.   in fact the code point mapping for 'A' in IBM code page 37, used on
  103.   mainframes, while the former is used for US-ASCII, iso8859-x, and
  104.   others.
  105.  
  106.   The basic idea is different people speak different languages, expect
  107.   different sorting orders, use different code pages, and live in
  108.   different countries.  Locales and locale sensitive programs give one a
  109.   means to respect such things, and handle them accordingly.  It is not
  110.   really much extra work to do so, it just requires a slightly different
  111.   frame of mind when writing programs.
  112.  
  113.   3.  Notes.
  114.  
  115.   ╖  In order to set up locales on my machine I had to upgrade a few
  116.      things.  Apparently ftp.tu-clausthal.de:/pub/linux/SLT/nls contains
  117.      a a.out version of locale and localedef (in the file
  118.      nlsutils-0.5.tar.gz), so if you don't have an ELF system, or don't
  119.      want one you can use the above.  There is probably a copy of the
  120.      nlsutils package some other place, but I have not looked for it.  I
  121.      hadn't known that there was a stand alone version of locale and
  122.      localedef, and kind of figured that you would have to have the
  123.      corresponding libc installed.  Because of this a lot of this HOWTO
  124.      is just a log of what I had to do to upgrade libc and family.  If
  125.      you do this, as I have you, will need to be running an ELF system,
  126.      or upgrade to one as you set up your locales.
  127.  
  128.   ╖  The sorts of system upgrades that I did are the same sort of
  129.      upgrades that have to be done to upgrade from a.out to ELF.  If you
  130.      haven't done this, or if you have upgraded to ELF by reinstalling
  131.      Linux then you should get the resent ELF HOWTO from a sunsite
  132.      mirror.  This is an excellent guide, and gives additional guidance
  133.      for installing libc, ld.so, and other ELF system upgrades.
  134.  
  135.   ╖  For anything that you install, read the appropriate release notes,
  136.      or README type files.  If you mess up your system by
  137.      misinterpreting something that I say here, or ( hopefully not ) by
  138.      doing something that I say in here, please don't blame me.
  139.  
  140.   ╖  Mis-installing a new libc, and ld.so, could leave you with an
  141.      unbootable system.  You probably ought to have a boot disk handy,
  142.      and make sure any critical, non-replaceable, data is backed up.
  143.  
  144.   4.  What you need.
  145.  
  146.   A few things need to be down loaded from various places.  Everything
  147.   here except for the locale source files can be obtained from
  148.   sunsite.unc.edu, tsx-11.mit.edu, or, preferably, a local mirror of
  149.   these sites.
  150.  
  151.   ╖  locale, and charmap sources --- These are what you compile using
  152.      localedef.
  153.  
  154.   ╖  libc-5.2.18.bin.tar.gz --- the ELF shared libraries for the c and
  155.      math libraries.
  156.  
  157.   ╖  libc-5.2.18.tar.gz --- the source code for the ELF shared
  158.      libraries.  You will need this to compile localedef.
  159.  
  160.   ╖  make-3.74.tar.gz --- you may need to compile make to incorporate a
  161.      patch to fix the dirent bug.
  162.  
  163.   ╖  release.libc-5.2.18 --- these release notes have the patch to make
  164.      make.
  165.  
  166.   ╖  ld.so-1.7.12+ --- the dynamic linker.
  167.  
  168.   ╖  ELF gcc-2.7.2+ --- to compile things.
  169.  
  170.   ╖  ELF kernel 1.1.92+, or ELF kernel 1.3.40+ --- to compile things.
  171.  
  172.   ╖  binutils 2.6.0.2+ --- to compile things.
  173.  
  174.   There are probably lots of places that you can get locale sources.  I
  175.   have found public domain locale and charmap sources at
  176.   dkuug.dk:/i18n/WG15-collection/locales
  177.   <ftp://dkuug.dk/i18n/WG15-collection/locales> and
  178.   dkuug.dk:/i18n/WG15-collection/charmaps
  179.   <ftp://dkuug.dk/i18n/WG15-collection/charmaps>  respectively.
  180.  
  181.   5.  Installing everything.
  182.  
  183.   This is what I did to install everything.  I already had an ELF system
  184.   ( compiler, kernel, ... ) installed before I did this.
  185.  
  186.   1. First I installed the binutils package.  tar xzf
  187.      binutils-2.6.0.2.bin.tar.gz -C /
  188.  
  189.   2. Next I installed the dynamic linker:
  190.  
  191.        tar zxf ld.so-1.7.12.tar.gz -C /usr/src
  192.        cd /usr/src/ld.so-1.7.12
  193.        sh instldso.sh
  194.  
  195.   3. Next I installed the libc binaries.  See release.libc-5.2.18 for
  196.      more instructions.
  197.  
  198.        rm -f /usr/lib/libc.so /usr/lib/libm.so
  199.        rm -f /usr/include/iolibio.h /usr/include/iostdio.h
  200.        rm -f /usr/include/ld_so_config.h /usr/include/localeinfo.h
  201.        rm -rf /usr/include/netinet /usr/include/net /usr/include/pthread
  202.        tar -xzf libc-5.2.18.bin.tar.gz -C /
  203.  
  204.   4. Now ldconfig must be run to locate the new shared libraries.
  205.      ldconfig -v.
  206.  
  207.   5. There is a bug that was fixed in libc that breaks make, and some
  208.      other programs.  Here is what I did in order to rebuild and install
  209.      make.
  210.  
  211.        tar zxf make-3.74.tar.gz -C /usr/src
  212.        cd /usr/src/make-3.74
  213.        patch < /whereever_you_put_it/release.libc-5.2.18
  214.        configure --prefix=/usr
  215.        sh build.sh
  216.         ../make install
  217.        cd ..
  218.        rm -rf make-2.74
  219.  
  220.   6. Now localedef can be compiled and installed.
  221.  
  222.   mkdir /usr/src/libc
  223.   tar zxf libc-5.2.18.tar.gz -C /usr/src/libc
  224.   cd /usr/src/libc
  225.   cd include
  226.   ln -s /usr/src/linux/include/asm .
  227.   ln -s /usr/src/linux/include/linux .
  228.   cd ../libc
  229.    ../configure
  230.   # I am not sure if these two makes are necessary, but just to be safe :
  231.   make clean ; make depend
  232.   cd locale
  233.   make programs
  234.   mv localedef /usr/local/bin
  235.   mv locale /usr/local/bin
  236.  
  237.   7. Put the charmaps where localedef will find them.  This uses the
  238.      charmaps and locale sources which I down loaded from dkuug.dk ftp
  239.      site as charmaps.tar, and locales.tar respectively.
  240.  
  241.   tar xf charmaps.tar -C /tmp
  242.   mkdir /usr/share/nls
  243.   mkdir /usr/share/nls/charmap
  244.   mkdir /usr/share/locale
  245.   mv /tmp/charmaps/* /usr/share/nls/charmap
  246.   rm -rf /tmp/charmaps
  247.   tar xf locales.tar -C /usr/share # put these where you want.
  248.  
  249.   # Some of the locale sources use `copy' and thus
  250.   # have dependencies on other locales.  I did some
  251.   # grep'ping, cut'ting, and sed'ding to
  252.   # make a makefile to make the following
  253.   # list of commands.  This will create all the
  254.   # locale objects within the /usr/share/locale
  255.   # directory.
  256.   #
  257.   localedef -ci locales/en_DK -f ISO_8859-1:1987 en_DK
  258.   localedef -ci locales/sv_SE -f ISO_8859-1:1987 sv_SE
  259.   localedef -ci locales/fi_FI -f ISO_8859-1:1987 fi_FI
  260.   localedef -ci locales/sv_FI -f ISO_8859-1:1987 sv_FI
  261.   localedef -ci locales/ro_RO -f ISO_8859-1:1987 ro_RO
  262.   localedef -ci locales/pt_PT -f ISO_8859-1:1987 pt_PT
  263.   localedef -ci locales/no_NO -f ISO_8859-1:1987 no_NO
  264.   localedef -ci locales/nl_NL -f ISO_8859-1:1987 nl_NL
  265.   localedef -ci locales/fr_BE -f ISO_8859-1:1987 fr_BE
  266.   localedef -ci locales/nl_BE -f ISO_8859-1:1987 nl_BE
  267.   localedef -ci locales/da_DK -f ISO_8859-1:1987 da_DK
  268.   localedef -ci locales/kl_GL -f ISO_8859-1:1987 kl_GL
  269.   localedef -ci locales/it_IT -f ISO_8859-1:1987 it_IT
  270.   localedef -ci locales/is_IS -f ISO_8859-1:1987 is_IS
  271.   localedef -ci locales/fr_LU -f ISO_8859-1:1987 fr_LU
  272.   localedef -ci locales/fr_FR -f ISO_8859-1:1987 fr_FR
  273.   localedef -ci locales/de_DE -f ISO_8859-1:1987 de_DE
  274.   localedef -ci locales/de_CH -f ISO_8859-1:1987 de_CH
  275.   localedef -ci locales/fr_CH -f ISO_8859-1:1987 fr_CH
  276.   localedef -ci locales/en_CA -f ISO_8859-1:1987 en_CA
  277.   localedef -ci locales/fr_CA -f ISO_8859-1:1987 fr_CA
  278.   localedef -ci locales/fo_FO -f ISO_8859-1:1987 fo_FO
  279.   localedef -ci locales/et_EE -f ISO_8859-1:1987 et_EE
  280.   localedef -ci locales/es_ES -f ISO_8859-1:1987 es_ES
  281.   localedef -ci locales/en_US -f ISO_8859-1:1987 en_US
  282.   localedef -ci locales/en_GB -f ISO_8859-1:1987 en_GB
  283.   localedef -ci locales/en_IE -f ISO_8859-1:1987 en_IE
  284.   localedef -ci locales/de_LU -f ISO_8859-1:1987 de_LU
  285.   localedef -ci locales/de_BE -f ISO_8859-1:1987 de_BE
  286.   localedef -ci locales/de_AT -f ISO_8859-1:1987 de_AT
  287.   localedef -ci locales/sl_SI -f ISO_8859-2:1987 sl_SI
  288.   localedef -ci locales/ru_RU -f ISO_8859-5:1988 ru_RU
  289.   localedef -ci locales/pl_PL -f ISO_8859-2:1987 pl_PL
  290.   localedef -ci locales/lv_LV -f BALTIC lv_LV
  291.   localedef -ci locales/lt_LT -f BALTIC lt_LT
  292.   localedef -ci locales/iw_IL -f ISO_8859-8:1988 iw_IL
  293.   localedef -ci locales/hu_HU -f ISO_8859-2:1987 hu_HU
  294.   localedef -ci locales/hr_HR -f ISO_8859-4:1988 hr_HR
  295.   localedef -ci locales/gr_GR -f ISO_8859-7:1987 gr_GR
  296.  
  297.   6.  Now what.
  298.  
  299.   After doing all the stuff above you should now be able to use the
  300.   locales that have been created.  Here is a simple example program.
  301.  
  302.        /* test.c : a simple test to see if the locales can be loaded, and
  303.         * used */
  304.        #include <locale.h>
  305.        #include <stdio.h>
  306.        #include <time.h>
  307.  
  308.        main(){
  309.                time_t t;
  310.                struct tm * _t;
  311.                char buf[256];
  312.  
  313.                time(&t);
  314.                _t = gmtime(&t);
  315.  
  316.                setlocale(LC_TIME,"");
  317.                strftime(buf,256,"%c",_t);
  318.  
  319.                printf("%s\n",buf);
  320.        }
  321.  
  322.   You can use the locale program to see what your current locale
  323.   environment variable settings are.
  324.  
  325.        $ # compile the simple test program above, and run it with
  326.        $ # some different locale settings
  327.        $ gcc -s -o Test test.c
  328.        $ # see what the current locale is :
  329.        $ locale
  330.        LANG=POSIX
  331.        LC_COLLATE="POSIX"
  332.        LC_CTYPE="POSIX"
  333.        LC_MONETARY="POSIX"
  334.        LC_NUMERIC="POSIX"
  335.        LC_TIME="POSIX"
  336.        LC_MESSAGES="POSIX"
  337.        LC_ALL=
  338.        $ # Ho, hum... we're using the boring C locale
  339.        $ # let's change to English Canadian:
  340.        $ export LC_TIME=en_CA
  341.        $ Test
  342.        Sat 23 Mar 1996 07:51:49 PM
  343.        $ # let's try French Canadian:
  344.        $ export LC_TIME=fr_CA
  345.        $ Test
  346.        sam 23 mar 1996 19:55:27
  347.  
  348.   7.  catopen bug fix.
  349.  
  350.   Installing the locales fixes a bug (feature ?)  that is in the catopen
  351.   command in Linux libc.  Say you create a program that uses message
  352.   catalogs, and you create an German catalog and put it in
  353.   /home/peeter/catalogs/de_DE.
  354.  
  355.   Now upon doing the following, without the de_DE locale installed :
  356.  
  357.   export LC_MESSAGES=de_DE
  358.   export NLSPATH=/home/peeter/catalogs/%L/%N.cat:$NLSPATH
  359.  
  360.   the German message catalog does not get opened, and the default mes¡
  361.   sages in the catgets calls are used.
  362.  
  363.   This is because catopen does a setlocale call to get the right message
  364.   category, the setlocale fails even though the environment variable has
  365.   been set.  catopen then attempts to load the message catalog
  366.   substituting "C" for all the "%L"'s in the NLSPATH.
  367.  
  368.   You can still use your message catalog without installing the locale,
  369.   but you would have to explicitly set the "%L" part of the NLSPATH like
  370.  
  371.        export NLSPATH=/home/peeter/catalogs/de_DE/%N.cat:$NLSPATH
  372.  
  373.   , but this defeats the whole purpose of the locale catagory environ¡
  374.   ment variables.
  375.  
  376.   8.  Questions and Answers.
  377.  
  378.   This section could grow into a FAQ, but isn't really one yet.
  379.  
  380.   8.1.  msgcat question
  381.  
  382.   I am an user of LINUX, and have written the following test program:
  383.  
  384.        --------------------------------------------------------------------
  385.        #include <stdio.h>
  386.        #include <locale.h>
  387.        #include <features.h>
  388.        #include <nl_types.h>
  389.  
  390.        main(int argc, char ** argv)
  391.        {
  392.                nl_catd catd;
  393.  
  394.                setlocale(LC_MESSAGES, "");
  395.                catd = catopen("msg", MCLoadBySet);
  396.                fprintf(stderr,catgets(catd, 1, 1, "locale message fail\n"));
  397.                catclose(catd);
  398.        }
  399.        --------------------------------------------------------------------
  400.        $ msg.m
  401.        $set 1
  402.  
  403.        1 locale message pass\n
  404.        --------------------------------------------------------------------
  405.  
  406.   If I use absolute path in catopen like
  407.   catopen("/etc/locale/msg.cat",MCLoadBySet); ,I got the right result.
  408.   But,if I use above example,catopen return -1 (failure).
  409.  
  410.   8.2.  msgcat answer
  411.  
  412.   This question is sort of answered in the previous section, but here is
  413.   some additional information.
  414.  
  415.   There are a number of valid places where you can put your message
  416.   catalogs.  Even though you may not have NLSPATH explicitly defined in
  417.   your environment settings it is defined in libc as follows :
  418.  
  419.        $ strings /lib/libc.so.5.2.18 | grep locale | grep %L
  420.        /etc/locale/%L/%N.cat:/usr/lib/locale/%L/%N.cat:/usr
  421.        /lib/locale/%N/%L:/usr/share/locale/%L/%N.cat:/usr/
  422.        local/share/locale/%L/%N.cat
  423.  
  424.   so you if you have done one of :
  425.  
  426.        $ export LC_MESSAGES=en_CA
  427.        $ export LC_ALL=en_CA
  428.        $ export LANG=en_CA
  429.  
  430.   With the NLSPATH above and the specified environment , the
  431.   catopen("msg", MCLoadBySet); should work if your message catalog has
  432.   been copied to any one of :
  433.  
  434.        /etc/locale/en_CA/msg.cat
  435.        /usr/lib/locale/en_CA/msg.cat
  436.        /usr/lib/locale/msg/en_CA
  437.        /usr/share/locale/en_CA/msg.cat
  438.        /usr/local/share/locale/en_CA/msg.cat
  439.  
  440.   This, however, will not work if you don't have the en_CA locale
  441.   installed because the setlocale will fail, and "C" will be substituted
  442.   for "%L" in the catopen routine ( rather than "en_CA" ).
  443.  
  444.   9.  Finale
  445.  
  446.   Well that's it.  Hopefully this guide has been some help to you.
  447.   There are probably lots of places that you can look for additional
  448.   information on writing locale sensitive programs.  There is some
  449.   information in the info pages for libc, and there is always man pages.
  450.   I'll bet that if you browse the web a bit you will be able to find a
  451.   lot of info.  If you find any good sources of information for
  452.   internationalized programming and want to let me know, then I can
  453.   reference them here.
  454.  
  455.