Slovensko jezikovno okolje

Z izrazom jezikovno okolje (angl. locale) označujemo skupek lastnosti programskega okolja, odvisnih od jezikovnega in kulturnega okolja uporabnika. Mednje sodi informacija o tem, kateri znaki so črke in kakšen je njihov vrstni red, način izpisa datuma in ure, izbiro ločila v zapisu decimalnih števil (vejica ali pika), zapis valute in sporočila programov uporabniku.

Programski vmesnik za internacionalizacijo in krajevno prilagajanje (lokalizacijo) v sistemih, združljivih s standardi POSIX, je definiran v standardu ISO/IEC 9899 (Programski jezik ISO C) ter IEEE 1003.2 (POSIX.2). Informacije, pomembne za krajevno prilagoditev, razvršča v šest kategorij:

LC_ALL zajema vseh šest naštetih kategorij. Medtem ko projekt GNU pri izvedbi prvih petih kategorij zvesto sledi standardu, se je v šesti odločil za njegovo razširitev. Standardizacijski komite se namreč ni mogel zediniti o izvedbi ravnanja s prevodi sporočil, zato je standard v tej točki praktično neuporaben: določa le prevode za ,da` in ,ne`. Projekt GNU je zato razvil svojo metodo, to je paket GNU gettext. Prevedeni katalogi sporočil, ki jih uporablja mehanizem gettext, so navadno v podimenikih imenika /usr/share/locale/.

Sledi nekaj zgledov odziva poslovenjenega sistema. Zgledi v tej izdaji spisa HOWTO so že preverjeni in pobrani iz Linuxa (paketi GNU textutils, GNU fileutils ipd.), v katerega pa mora biti nameščena knjižnica GNU libc 2.0 ali poznejša izdaja. Če katerega od zgledov pisec ni uspel preveriti v Linuxu, je na to posebej opozorjeno.

Z nastavitvijo spremenljivke LANG ali LC_ALL na slovensko jezikovno okolje se spremenijo vsi prilastki, spreminjamo pa lahko tudi vsakega posebej:

~> cal
    February 2000
Su Mo Tu We Th Fr Sa
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29
~> date
Sun Feb 13 20:16:07 CET 2000
~> LC_ALL=sl_SI.iso88592 cal
    februar 2000
ne po to sr če pe so
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29
~> LC_TIME=sl_SI date
ned feb 13 20:16:22 CET 2000

Lahko pa jih spreminjamo tudi vsakega posebej. Če bi želili obdržati angleške izpise, obliko datuma, decimalno piko ipd., a bi želeli črke urejene po slovenski abecedi, bi spremenili samo LC_COLLATE (urejanje po izkušnjah pisca z GNU libc 2.1 še vedno ne deluje):

~> sort abc.tex 
abc
abca
abd
abč
~> LANG=C LC_COLLATE=sl_SI.iso88592 sort abc.tex
abc
abca
abč
abd

Seveda LC_COLLATE ne reši vseh težav v zvezi z urejanjem. Pri razvrščanju kastiljskih kraljev bi, recimo, želeli, da Alfonz IX. sledi Alfonzu VIII. in je pred Alfonzom X. Prepoznavanje takih zgledov pa je verjetno že problem za umetno inteligenco...

Spremenljivka LANG ima v splošnem obliko:

LANG =jezik [_država [.nabor]]

Pri tem je jezik dvočrkovna koda jezika, kot jo določa standard ISO 639, država pa dvočrkovna koda države, določena s standardom ISO 3166. Zgled za slovenščino, kot se govori v Sloveniji in piše s kodnim naborom ISO 8859-2, je torej

LANG=sl_SI.iso88592
    

Določitev države in nabora znakov je neobvezna (pomembna je seveda pri jezikih, ki se govorijo v več državah; kakšno jezikovno okolje uporabljajo Slovenci v zamejstvu, piscu teh vrstic ni znano), tako lahko pišemo na kratko

LANG=sl
    

Vsaj v teoriji naj bi bilo tako. Praksa v Linuxu se navadno majčkeno razlikuje: v imeniku /usr/share/locale/sl so shranjeni samo katalogi sporočil iz kategorije LC_MESSAGES, podatki iz vseh drugih kategorij pa so v imeniku /usr/share/locale/sl_SI. Zato moramo postaviti spremenljivko LANG (ali LC_ALL) na vrednost sl_SI (ali sl_SI.iso88592), spremenljivko LC_MESSAGES pa na sl:

LANG=sl_SI
LC_MESSAGES=sl
    

Programiranje z GNU gettext

Paket GNU gettext ponuja nekaj orodij za lokalizacijo:

S kratkim zgledom ponazorimo, kako poteka pisanje krajevno prilagojenega programa s paketom GNU gettext.

  1. Najprej napišemo program zgled.c. Pri pisanju programa že vpletemo mehanizme internacionalizacije:

    #include <locale.h>
    #include <stdio.h>
    #include <libintl.h>
    
    #define PACKAGE   "zgled"
    #define LOCALEDIR "/usr/local/share/locale"
    
    char main() {
        setlocale (LC_MESSAGES, "");
        bindtextdomain (PACKAGE, LOCALEDIR);
        textdomain (PACKAGE);
    
        printf("%s\n", gettext("This is a short example."));
        printf("%s\n", gettext("Author: Primoz Peterlin"));
        return(0);
    }
              
  2. Z ukazom xgettext iz izvirne kode izluščimo izpise na zaslon:

    xgettext zgled.c

    S tem smo ustvarili datoteko messages.po. To je navadna besedilna datoteka s skeletom prevodov sporočil.

  3. Datoteko messages.po z urejevalnikom dopolnimo s prevodi, recimo takole:

    # Slovenski prevod zgleda
    # Primož Peterlin, <primoz.peterlin@biofiz.mf.uni-lj.si>
    #
    msgid ""
    msgstr ""
    "Project-Id-Version: zgled 1.0\n"
    "POT-Creation-Date: 1998-12-06 14:05:53+0100\n"
    "PO-Revision-Date: 1998-12-06 15:00:00+0100\n"
    "Last-Translator: Primoz Peterlin <peterlin@biofiz.mf.uni-lj.si>\n"
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=ISO-8859-2\n"
    "Content-Transfer-Encoding: 8bit\n"
    "Xgettext-Options: \n"
    "Files: zgled.c\n"
    
    #: zgled.c:13
    msgid "This is a short example."
    msgstr "To je kratek zgled."
    
    #: zgled.c:14
    msgid "Author: Primoz Peterlin"
    msgstr "Avtor: Primož Peterlin"
              
  4. Popravljeno prenosljivo datoteko s sporočili (angl. portable message file) messages.po prevedemo v binarno obliko:

    msgfmt -v -o zgled.mo messages.po

  5. Binarno datoteko prestavimo v imenik, v katerem jo bo gettext našel:

    mv zgled.mo /usr/local/share/locale/sl/LC_MESSAGES

  6. Program prevedemo in povežemo s knjižnico libintl.a:

    gcc -o zgled zgled.c -lintl

  7. Pa poskusimo, kakšna je razlika!

    LANG=C ./zgled
    LANG=sl ./zgled
    LC_ALL=sl ./zgled
    LC_MESSAGES=sl ./zgled
    LC_CTYPE=sl ./zgled
    LC_ALL=sl_SI.iso88592 ./zgled
              

    V prvem in zadnjem zgledu je izpisano sporočilo angleško, v predzadnjem pa verjetno tudi. V prvem zato, ker smo izrecno zahtevali jezikovno okolje ,C`, v zadnjem pa zato, ker smo zahtevali jezikovno okolje ,sl_SI.iso88592`, v katerem ni prevoda sporočil -- to namreč obstaja za jezikovno okolje ,sl`. V predzadnjem zgledu smo uporabili pravo jezikovno okolje, a irelevantno kategorijo LC_CTYPE namesto uporabljene LC_MESSAGES.

Še dve opombi: imenik, v katerega prestavimo katalog sporočil, se mora ujemati z imenikom LOCALEDIR, navedenim v izvirni kodi. Težavo, da GNU gettext razume ,sl` in ,sl_SI.iso88592` kot različna locala, je pisec teh vrstic rešil s simbolno povezavo v imeniku /usr/local/share/locale:

ln -s sl sl_SI.iso88592

Perl

Od izdaje 5.004 naprej tudi Perl podpira krajevne prilagoditve. Nastaviti moramo primerne spremenljivke okolja in bodisi v programu uporabiti klic

use locale;
      

bodisi poklicati Perl z izbiro -Mlocale. Nekaj zgledov; preizkus smo si sposodili pri Janu Pazdziori:

~> LC_CTYPE=sl_SI.iso88592 perl -Mlocale -e '$_="težišče\n"; s/\w/$&:/g; print;'
t:e:ž:i:š:č:e:
~> LC_CTYPE=C perl -Mlocale -e '$_="težišče\n"; s/\w/$&:/g; print;'
t:e:ži:šče:
~> LC_CTYPE=sl_SI.iso88592 perl -e '$_="težišče\n"; s/\w/$&:/g; print;'
t:e:ži:šče:

Kakor vidimo, je samo v prvem zgledu, ko smo izvedli oboje: nastavili spremenljivko LC_CTYPE in perl poklicali z izbiro -Mlocale, naše znake res upošteval kot črke (\).

Lokalizacijski paket Gettext ni omejen samo na programska jezika C in C++, za katera je bil razvit. Funkcije iz paketa lahko kličemo tudi iz skriptnih jezikov, kot so perl, python in drugi. Za prvega potrebujemo modul Locale::gettext, ki je na voljo paket perl-gettext (RPM) oziroma liblocale-gettext-perl (Debian). Raba je enaka, kot smo že opisali:

#!/usr/bin/perl
use Locale::gettext;
use POSIX;     # Potrebno za setlocale()

setlocale(LC_MESSAGES, "");
bindtextdomain("countfiles", "/usr/share/locale");
textdomain("countfiles");

printf(gettext("Usage: %s directory\n"), $0);
      

Python

Modul gettext je v pythonu že del standardnega paketa. Tudi tu raba sledi temu, kar smo že povedali. Zgled:

#!/usr/bin/python
import gettext
import sys

gettext.bindtextdomain('countfiles', '/usr/share/locale/')
gettext.textdomain('countfiles')
_ = gettext.gettext

print _('Usage: %s directory\n') % sys.argv[0]
      

PHP

Podpora gettextu je zajeta tudi v skriptni jezik PHP. Zgled je prispeval Rudi Benkovič, :

<?php
bindtextdomain ("countfiles", "/usr/share/locale");
textdomain ("countfiles");

print sprintf(gettext("Usage: %s directory\n"), $var);
?>
      

PHP moramo imeti preveden s podporo za gettext.

Ukazna lupina Bash

Ker obstaja tudi vmesnik na uporabniški ravni -- ukaz gettext -- je mogoče krajevno prilagoditi tudi sporočila ukazne lupine Bash:

#!/bin/sh

TEXTDOMAINDIR=/usr/share/locale
TEXTDOMAIN=countfiles

printf "$(gettext -s "Usage: %s directory\n")" "$0"

Druga izdaja ukazne lupine Bash (preverjeno velja za 2.04) podpira tudi izbiri -D in --dump-po-strings, s katerima iz skripta izluščimo vsa sporočila uporabniku. Več o krajevnem prilagajanju te ukazne lupine si je moč prebrati v Advanced Bash-Scripting Guide.

Poslovenjenje katalogov sporočil

Od leta 1996 naprej poteka internacionalizacija projekta GNU, v okviru katere so doslej prevedeni v slovenščino paketi a2ps, enscript, fileutils, findutils, gettext, grep, hello, lynx, recode, sed, sh-utils, tar, textutils in wget.

Komisija za slovenjenje pri društvu Lugos se od jeseni 1998 naprej ukvarja s prevajanjem namizja KDE v slovenščino in sproti vzdržuje prevode tudi v novejših izdajah. Nekaj mlajši projekt je prevajanje namizja GNOME v slovenščino.

Razprava o delu komisije za slovenjenje poteka med prejemniki elektronskega seznama . Nanj se naročite tako, da na naslov sympa@lugos.si v telesu sporočila pošljete vrstico

subscribe lugos-slo

Obvestila o poslovenjenju paketov iz projekta GNU prejemajo prejemniki elektronskega seznama (seznam je seveda tudi namenjen razpravi med udeleženci, vendar se je ta v zadnjih letih preselila na seznam lugos-slo). Nanj se naročite tako, da na naslov sl-request@li.org v telesu sporočila pošljete vrstico

subscribe