💾 Archived View for magaz.hellug.gr › 12 › 03_nls2 › index.gmi captured on 2024-08-25 at 00:29:17. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-02-05)
-=-=-=-=-=-=-
Νίκος Μαυρογιαννόπουλος Φεβ 1999
Μιας και το nls χρησιμοποιείται όλο και περισσότερο στα νέα προγράμματα (ιδιαίτερα αυτά που αποτελούν το GNU σύστημα), είναι αναγκαίο να κάνουμε μια περιγραφή της διαδικασίας που χρειάζεται για να το ενσωματώσουμε και στα δικά μας προγράμματα.
Η άδεια του gettext για τα κομμάτια που θα ενσωματώσουμε στο προγραμμά μας είναι η GNU LGPL που δεν μας περιορίζει στον καθορισμό της άδειας του προγράμματός μας. Κοιτάξτε την πάντως για να δείτε αν είστε συμβατοί(!).
Ας προσπεράσουμε όμως τα "τυπικά" και ας περάσουμε στο ψητό. Τα προγράμματα που θα χρειαστούμε είναι τα GNU autoconf και gettext-0.10, και βρίσκονται στο πιο κοντινό gnu mirror.
#include <stdio.h> #include <time.h> main () { time_t tv; printf( "The time is: " ); time(&tv); printf ( "%s",ctime(&tv) ); }
Το ίδιο πρόγραμμα τώρα γίνεται:
#include <stdio.h> #include <time.h> #include <locale.h> main () { struct tm *tp; char buf[80]; time_t date; /* Θέτει το locale σύμφωνα με την μεταβλητή περιβάλλοντος LANG ή LANGUAGE * Για τα ελληνικά πρεπει να είναι el (ISO639) */ setlocale (LC_TIME, ""); /* Για την ώρα και μόνο */ printf( "The time is: " ); time(&date); /* Μετατρέπει την ώρα έκφραση που συνδέεται με την ζώνη ώρας */ tp = localtime(&date); strftime(buf, sizeof buf, "%a %b %e %H:%M:%S %z %Y", tp); /* εκτυπώνει την ώρα */ printf ("%s\n",buf); }
Η ώρα τώρα θα τυπωθεί στην μορφή: Τετ Νοέ 11 22:44:29 +0200 1998 με ελληνικούς χαρακτήρες όπως βλέπετε (αν LANG=el ή gr για τις παλιές glibc2). Γι'αυτό ξεχάστε το ctime και ασχοληθείτε με το strftime().
1: ftp://argeas.cs-net.gr/pub/unix/linux/GREEK/locale.glibc2.el.tar.gz
#include <stdio.h> #include <time.h> #include <locale.h> #include <libintl.h> /* αρχείο της GNU libc */ main () { struct tm *tp; char buf[80]; time_t date; /* πέρα απο το LC_ALL υπάρχουν τα LC_TIME, LC_MESSAGES κλπ, τα οποία * προσδιορίζουν επ'ακριβώς τί μεταφράσεις θα χρησιμοποιήσουμε. */ setlocale (LC_ALL, ""); bindtextdomain ("my_time", "/usr/share/locale"); textdomain ("my_time"); printf( gettext("The time is: ") ); time(&date); tp = localtime(&date); strftime(buf, sizeof buf, "%a %b %e %H:%M:%S %z %Y", tp); printf ("%s\n",buf); }
Οι εντολές bindtextdomain() και textdomain() αφορούν την nls βιβλιοθήκη (libintl) και την πληροφορούν ότι η μετάφραση του προγράμματος βρίσκεται στο my_time.mo στον κατάλογο /usr/share/locale/XX, όπου ΧΧ η γλώσσα του χρήστη (καθορίζεται απο την μεταβλητή LANG ή LANGUAGE).
Επειδή πολλές φορές το να γράφουμε gettext(...) είναι επίπονο για πολλά μηνύματα, χρησιμοποιούμε το:
#define _(Text) gettext(Text) /* στις επικέφαλίδες */ printf( _("The time is: ") );
Το πρόγραμμα δεν θα λειτουργήσει ακομη με ελληνικά. Χρειάζεται ακόμη την δημιουργία του .po αρχείου. Αυτό είναι σχετικά απλό αν γίνει με το πρόγραμμα xgettext (από το πακέτο GNU gettext). Για το συγκεκριμένο πρόγραμμα η έξοδος του xgettext είναι: (σύνταξη "xgettext my_time.c")
# messages.po # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Free Software Foundation, Inc. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 1998-11-11 22:52+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: ENCODING\n" #: c.c:16 msgid "The time is: " msgstr "" #end of messages.po
και εδώ μετονομάζουμε το messages.po σε el.po, προσθέτοντας ταυτόχρονα στο msgstr την μετάφραση, πχ: msgstr "Η ώρα είναι: "
2: http://teamball.sdsu.edu/doc/texi/gettext_toc.html
Για να απλοποιήσουμε τα πράγματα θεωρούμε την εξής διαμόρφωση των αρχείων του προγράμματος: (έστω ότι το πρόγραμμα είναι στο /xxx) στον κατάλογο /xxx/ configure.in: Χρειάζεται για το autoconf (δείτε παρακάτω) config.h.in : (δείτε παρακάτω)
στον κατάλογο /xxx/src/ my_time.c : Το πρόγραμμα στον κατάλογο /xxx/po/ my_time.pot : Αυτό είναι το messages.po που δημιουργείται απο το xgettext απλώς μετονομασμένο el.po : Το my_time.pot μεταφρασμένο στα ελληνικά POTFILES.in : Εδώ προσθέτετε όλα τα .c αρχεία στο src που χρησιμοποιούν το gettext. πχ: /xxx/src/my_time.c
Αρκεί τώρα να αντιγράψετε απο το πακέτο gettext-0.10 τα po/Makefile.in στον κατάλογο του προγραμματός /xxx/po/ , όλο τον κατάλογο intl/ στον /xxx/intl/ και τα ABOUT-NLS, aclocal.m4 στον /xxx .
Πάμε τώρα στον πρωταρχικό κατάλογο του προγράμματός μας (/xxx) και ας φτιάξουμε το configure.in απο το οποίο θα προκύψει το γνωστό(;) script configure.
# configure.in for my_time.c AC_INIT() AC_CONFIG_HEADER(config.h) AC_PROG_CC AC_PATH_PROG(MAKE,make) AC_PROG_INSTALL VERSION=1.0 PROGRAMS="my_time" AC_PREFIX_DEFAULT(/usr/local) AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE") AC_DEFINE_UNQUOTED(VERSION, "$VERSION") AC_SUBST(PACKAGE) AC_SUBST(VERSION) AC_SUBST(PROGRAMS) dnl υποστηρίζουμε ελληνικά (τό el είναι απο το iso639 που πρέπει να dnl χρησιμοποιείται για την ένδειξη γλώσσας στις μεταφράσεις σύμφωνα με το dnl εγχειρίδιο το gettext.) ALL_LINGUAS="el" dnl Για το gettext 0.10. ud_GNU_GETTEXT AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl) AC_FUNC_STRFTIME AC_OUTPUT([Makefile src/Makefile intl/Makefile po/Makefile.in [sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile]) #end of configure.in
και αμέσως μετά δημιουργούμε ένα config.h.in (είναι βάση του αρχείου config.h που θα συμπεριλαμβάνεται στο πρόγραμμά μας. Η δημιουργία του config.h γίνεται απο το script configure.) Το config.h.in θα περιέχει:
# config.h.in for my_time.c /* Το όνομα του πακέτου (θα χρησιμοποιηθεί για το textdomain) */ #undef PACKAGE #undef VERSION /* strftime */ #undef HAVE_STRFTIME #undef ENABLE_NLS #end of config.h.in
Το Makefile.in για το πρόγραμμα (το Makefile δημιουργείται επίσης αυτόματα απο το configure), πρέπει να έχει σε γενικές γραμμές τα:
# Makefile.in CC = @CC@ LIBS = @LIBS@ CCOPTS = @CFLAGS@ -I. -I.. LN = @LN_S@ INSTALL = @INSTALL@ prefix = @prefix@ exec_prefix = @prefix@ datadir = $(prefix)/lib bin = $(prefix)/bin localedir = $(datadir)/locale DEFS = -DLOCALEDIR="$(localedir)" SUBDIRS = @INTLSUB@ src @POSUB@ MAKE = @MAKE@ INSTALL = @INSTALL@
all: @for subdir in $(SUBDIRS); do \ echo making all in $subdir; \ (cd $subdir && $(MAKE) all) \ || case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$fail" install: @$(INSTALL) my_time $(bin) @$(MAKE) -C po/ install # end of makefile.in # src/Makefile.in # Εδώ οι επικεφαλίδες είναι περίπου ίδιες με πριν: CC = @CC@ LIBS = @LIBS@ CCOPTS = @CFLAGS@ -I../intl -I. -I.. LN = @LN_S@ INSTALL = @INSTALL@ prefix = @prefix@ exec_prefix = @prefix@ datadir = $(prefix)/lib localedir = $(datadir)/locale DEFS = -DLOCALEDIR="$(localedir)" all: my_time my_time: my_time.o $(CC) $(OBJECTS) -o ../my_time $(LIBDIRS) $(LIBS) my_time.o: my_time.c $(CC) -c my_time.c $(CCOPTS) $(DEFS) #end of src/Makefile.in
Το πρόγραμμα τώρα θα γίνει:
# src/my_time.c #include <stdio.h> #include <time.h> #include <config.h> /* ή "config.h" αν δεν βάλετε το -I. στο Makefile */ #ifdef ENABLE_NLS #include <libintl.h> #endif main () { #ifdef HAVE_STRFTIME struct tm *tp; char buf[80]; time_t date; #else time_t tv; #endif #ifdef ENABLE_NLS setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); # define _(Text) gettext(Text) #else # define _(Text) (Text) #endif printf( _("The time is: ") ); #ifdef HAVE_STRFTIME_H time(&date); tp = localtime(&date); strftime(buf, sizeof buf, "%a %b %e %H:%M:%S %z %Y", tp); printf ("%s\n",buf); #else time(&tv); printf ( "%s",ctime(&tv) ); #endif } #end of src/my_time.c
Τώρα τρέχουμε το autoconf που δημιουργεί το configure script. Aν όλα πήγαν καλά έχουμε ένα πρόγραμμα που μιλάει ξένες γλώσσες!