4803 lines
209 KiB
Plaintext
4803 lines
209 KiB
Plaintext
\input texinfo @c -*-texinfo-*-
|
|
@c %**start of header
|
|
@setfilename gettext.info
|
|
@settitle GNU @code{gettext} utilities
|
|
@finalout
|
|
@c %**end of header
|
|
|
|
@include version.texi
|
|
|
|
@dircategory GNU Gettext Utilities
|
|
@direntry
|
|
* Gettext: (gettext). GNU gettext utilities.
|
|
* gettextize: (gettext)gettextize Invocation. Prepare a package for gettext.
|
|
* msgfmt: (gettext)msgfmt Invocation. Make MO files out of PO files.
|
|
* msgmerge: (gettext)msgmerge Invocation. Update two PO files into one.
|
|
* xgettext: (gettext)xgettext Invocation. Extract strings into a PO file.
|
|
@end direntry
|
|
|
|
@ifinfo
|
|
This file provides documentation for GNU @code{gettext} utilities.
|
|
It also serves as a reference for the free Translation Project.
|
|
|
|
Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
|
|
|
|
Permission is granted to make and distribute verbatim copies of
|
|
this manual provided the copyright notice and this permission notice
|
|
are preserved on all copies.
|
|
|
|
@ignore
|
|
Permission is granted to process this file through TeX and print the
|
|
results, provided the printed document carries copying permission
|
|
notice identical to this one except for the removal of this paragraph
|
|
(this paragraph not being relevant to the printed manual).
|
|
|
|
@end ignore
|
|
Permission is granted to copy and distribute modified versions of this
|
|
manual under the conditions for verbatim copying, provided that the entire
|
|
resulting derived work is distributed under the terms of a permission
|
|
notice identical to this one.
|
|
|
|
Permission is granted to copy and distribute translations of this manual
|
|
into another language, under the above conditions for modified versions,
|
|
except that this permission notice may be stated in a translation approved
|
|
by the Foundation.
|
|
@end ifinfo
|
|
|
|
@titlepage
|
|
@title GNU gettext tools, version @value{VERSION}
|
|
@subtitle Native Language Support Library and Tools
|
|
@subtitle Edition @value{EDITION}, @value{UPDATED}
|
|
@author Ulrich Drepper
|
|
@author Jim Meyering
|
|
@author Fran@,{c}ois Pinard
|
|
|
|
@page
|
|
@vskip 0pt plus 1filll
|
|
Copyright @copyright{} 1995, 1996, 1997 Free Software Foundation, Inc.
|
|
|
|
Permission is granted to make and distribute verbatim copies of
|
|
this manual provided the copyright notice and this permission notice
|
|
are preserved on all copies.
|
|
|
|
Permission is granted to copy and distribute modified versions of this
|
|
manual under the conditions for verbatim copying, provided that the entire
|
|
resulting derived work is distributed under the terms of a permission
|
|
notice identical to this one.
|
|
|
|
Permission is granted to copy and distribute translations of this manual
|
|
into another language, under the above conditions for modified versions,
|
|
except that this permission notice may be stated in a translation approved
|
|
by the Foundation.
|
|
@end titlepage
|
|
|
|
@ifinfo
|
|
@node Top, Introduction, (dir), (dir)
|
|
@top GNU @code{gettext} utilities
|
|
|
|
@menu
|
|
* Introduction:: Introduction
|
|
* Basics:: PO Files and PO Mode Basics
|
|
* Sources:: Preparing Program Sources
|
|
* Initial:: Making the Initial PO File
|
|
* Updating:: Updating Existing PO Files
|
|
* Binaries:: Producing Binary MO Files
|
|
* Users:: The User's View
|
|
* Programmers:: The Programmer's View
|
|
* Translators:: The Translator's View
|
|
* Maintainers:: The Maintainer's View
|
|
* Conclusion:: Concluding Remarks
|
|
|
|
* Country Codes:: ISO 639 country codes
|
|
|
|
--- The Detailed Node Listing ---
|
|
|
|
Introduction
|
|
|
|
* Why:: The Purpose of GNU @code{gettext}
|
|
* Concepts:: I18n, L10n, and Such
|
|
* Aspects:: Aspects in Native Language Support
|
|
* Files:: Files Conveying Translations
|
|
* Overview:: Overview of GNU @code{gettext}
|
|
|
|
PO Files and PO Mode Basics
|
|
|
|
* Installation:: Completing GNU @code{gettext} Installation
|
|
* PO Files:: The Format of PO Files
|
|
* Main PO Commands:: Main Commands
|
|
* Entry Positioning:: Entry Positioning
|
|
* Normalizing:: Normalizing Strings in Entries
|
|
|
|
Preparing Program Sources
|
|
|
|
* Triggering:: Triggering @code{gettext} Operations
|
|
* Mark Keywords:: How Marks Appears in Sources
|
|
* Marking:: Marking Translatable Strings
|
|
* c-format:: Telling something about the following string
|
|
* Special cases:: Special Cases of Translatable Strings
|
|
|
|
Making the Initial PO File
|
|
|
|
* xgettext Invocation:: Invoking the @code{xgettext} Program
|
|
* C Sources Context:: C Sources Context
|
|
* Compendium:: Using Translation Compendiums
|
|
|
|
Updating Existing PO Files
|
|
|
|
* msgmerge Invocation:: Invoking the @code{msgmerge} Program
|
|
* Translated Entries::
|
|
* Fuzzy Entries:: Fuzzy translated Entries
|
|
* Untranslated Entries:: Untranslated Entries
|
|
* Obsolete Entries:: Obsolete Entries
|
|
* Modifying Translations:: Modifying Translations
|
|
* Modifying Comments:: Modifying Comments
|
|
* Auxiliary:: Consulting Auxiliary PO Files
|
|
|
|
Producing Binary MO Files
|
|
|
|
* msgfmt Invocation:: Invoking the @code{msgfmt} Program
|
|
* MO Files:: The Format of GNU MO Files
|
|
|
|
The User's View
|
|
|
|
* Matrix:: The Current @file{ABOUT-NLS} Matrix
|
|
* Installers:: Magic for Installers
|
|
* End Users:: Magic for End Users
|
|
|
|
The Programmer's View
|
|
|
|
* catgets:: About @code{catgets}
|
|
* gettext:: About @code{gettext}
|
|
* Comparison:: Comparing the two interfaces
|
|
* Using libintl.a:: Using libintl.a in own programs
|
|
* gettext grok:: Being a @code{gettext} grok
|
|
* Temp Programmers:: Temporary Notes for the Programmers Chapter
|
|
|
|
About @code{catgets}
|
|
|
|
* Interface to catgets:: The interface
|
|
* Problems with catgets:: Problems with the @code{catgets} interface?!
|
|
|
|
About @code{gettext}
|
|
|
|
* Interface to gettext:: The interface
|
|
* Ambiguities:: Solving ambiguities
|
|
* Locating Catalogs:: Locating message catalog files
|
|
* Optimized gettext:: Optimization of the *gettext functions
|
|
|
|
Temporary Notes for the Programmers Chapter
|
|
|
|
* Temp Implementations:: Temporary - Two Possible Implementations
|
|
* Temp catgets:: Temporary - About @code{catgets}
|
|
* Temp WSI:: Temporary - Why a single implementation
|
|
* Temp Notes:: Temporary - Notes
|
|
|
|
The Translator's View
|
|
|
|
* Trans Intro 0:: Introduction 0
|
|
* Trans Intro 1:: Introduction 1
|
|
* Discussions:: Discussions
|
|
* Organization:: Organization
|
|
* Information Flow:: Information Flow
|
|
|
|
Organization
|
|
|
|
* Central Coordination:: Central Coordination
|
|
* National Teams:: National Teams
|
|
* Mailing Lists:: Mailing Lists
|
|
|
|
National Teams
|
|
|
|
* Sub-Cultures:: Sub-Cultures
|
|
* Organizational Ideas:: Organizational Ideas
|
|
|
|
The Maintainer's View
|
|
|
|
* Flat and Non-Flat:: Flat or Non-Flat Directory Structures
|
|
* Prerequisites:: Prerequisite Works
|
|
* gettextize Invocation:: Invoking the @code{gettextize} Program
|
|
* Adjusting Files:: Files You Must Create or Alter
|
|
|
|
Files You Must Create or Alter
|
|
|
|
* po/POTFILES.in:: @file{POTFILES.in} in @file{po/}
|
|
* configure.in:: @file{configure.in} at top level
|
|
* aclocal:: @file{aclocal.m4} at top level
|
|
* acconfig:: @file{acconfig.h} at top level
|
|
* Makefile:: @file{Makefile.in} at top level
|
|
* src/Makefile:: @file{Makefile.in} in @file{src/}
|
|
|
|
Concluding Remarks
|
|
|
|
* History:: History of GNU @code{gettext}
|
|
* References:: Related Readings
|
|
@end menu
|
|
|
|
@end ifinfo
|
|
|
|
@node Introduction, Basics, Top, Top
|
|
@chapter Introduction
|
|
|
|
@quotation
|
|
This manual is still in @emph{DRAFT} state. Some sections are still
|
|
empty, or almost. We keep merging material from other sources
|
|
(essentially e-mail folders) while the proper integration of this
|
|
material is delayed.
|
|
@end quotation
|
|
|
|
In this manual, we use @emph{he} when speaking of the programmer or
|
|
maintainer, @emph{she} when speaking of the translator, and @emph{they}
|
|
when speaking of the installers or end users of the translated program.
|
|
This is only a convenience for clarifying the documentation. It is
|
|
@emph{absolutely} not meant to imply that some roles are more appropriate
|
|
to males or females. Besides, as you might guess, GNU @code{gettext}
|
|
is meant to be useful for people using computers, whatever their sex,
|
|
race, religion or nationality!
|
|
|
|
This chapter explains the goals sought in the creation
|
|
of GNU @code{gettext} and the free Translation Project.
|
|
Then, it explains a few broad concepts around
|
|
Native Language Support, and positions message translation with regard
|
|
to other aspects of national and cultural variance, as they apply to
|
|
to programs. It also surveys those files used to convey the
|
|
translations. It explains how the various tools interact in the
|
|
initial generation of these files, and later, how the maintenance
|
|
cycle should usually operate.
|
|
|
|
Please send suggestions and corrections to:
|
|
|
|
@example
|
|
@group
|
|
@r{Internet address:}
|
|
bug-gnu-utils@@prep.ai.mit.edu
|
|
@end group
|
|
@end example
|
|
|
|
@noindent
|
|
Please include the manual's edition number and update date in your messages.
|
|
|
|
@menu
|
|
* Why:: The Purpose of GNU @code{gettext}
|
|
* Concepts:: I18n, L10n, and Such
|
|
* Aspects:: Aspects in Native Language Support
|
|
* Files:: Files Conveying Translations
|
|
* Overview:: Overview of GNU @code{gettext}
|
|
@end menu
|
|
|
|
@node Why, Concepts, Introduction, Introduction
|
|
@section The Purpose of GNU @code{gettext}
|
|
|
|
Usually, programs are written and documented in English, and use
|
|
English at execution time to interact with users. This is true
|
|
not only of GNU software, but also of a great deal of commercial
|
|
and free software. Using a common language is quite handy for
|
|
communication between developers, maintainers and users from all
|
|
countries. On the other hand, most people are less comfortable with
|
|
English than with their own native language, and would prefer to
|
|
use their mother tongue for day to day's work, as far as possible.
|
|
Many would simply @emph{love} to see their computer screen showing
|
|
a lot less of English, and far more of their own language.
|
|
|
|
However, to many people, this dream might appear so far fetched that
|
|
they may believe it is not even worth spending time thinking about
|
|
it. They have no confidence at all that the dream might ever
|
|
become true. Yet some have not lost hope, and have organized themselves.
|
|
The Translation Project is a formalization of this hope into a
|
|
workable structure, which has a good chance to get all of us nearer
|
|
the achievement of a truly multi-lingual set of programs.
|
|
|
|
GNU @code{gettext} is an important step for the Translation Project,
|
|
as it is an asset on which we may build many other steps. This package
|
|
offers to programmers, translators and even users, a well integrated
|
|
set of tools and documentation. Specifically, the GNU @code{gettext}
|
|
utilities are a set of tools that provides a framework within which
|
|
other free packages may produce multi-lingual messages. These tools
|
|
include a set of conventions about how programs should be written to
|
|
support message catalogs, a directory and file naming organization for the
|
|
message catalogs themselves, a runtime library supporting the retrieval of
|
|
translated messages, and a few stand-alone programs to massage in various
|
|
ways the sets of translatable strings, or already translated strings.
|
|
A special mode for GNU Emacs also helps ease interested parties into
|
|
preparing these sets, or bringing them up to date.
|
|
|
|
GNU @code{gettext} is designed to minimize the impact of
|
|
internationalization on program sources, keeping this impact as small
|
|
and hardly noticeable as possible. Internationalization has better
|
|
chances of succeeding if it is very light weighted, or at least,
|
|
appear to be so, when looking at program sources.
|
|
|
|
The Translation Project also uses the GNU @code{gettext}
|
|
distribution as a vehicle for documenting its structure and methods.
|
|
This goes beyond the strict technicalities of documenting the GNU @code{gettext}
|
|
proper. By so doing, translators will find in a single place, as
|
|
far as possible, all they need to know for properly doing their
|
|
translating work. Also, this supplemental documentation might also
|
|
help programmers, and even curious users, in understanding how GNU
|
|
@code{gettext} is related to the remainder of the Translation
|
|
Project, and consequently, have a glimpse at the @emph{big picture}.
|
|
|
|
@node Concepts, Aspects, Why, Introduction
|
|
@section I18n, L10n, and Such
|
|
|
|
Two long words appear all the time when we discuss support of native
|
|
language in programs, and these words have a precise meaning, worth
|
|
being explained here, once and for all in this document. The words are
|
|
@emph{internationalization} and @emph{localization}. Many people,
|
|
tired of writing these long words over and over again, took the
|
|
habit of writing @dfn{i18n} and @dfn{l10n} instead, quoting the first
|
|
and last letter of each word, and replacing the run of intermediate
|
|
letters by a number merely telling how many such letters there are.
|
|
But in this manual, in the sake of clarity, we will patiently write
|
|
the names in full, each time@dots{}
|
|
|
|
By @dfn{internationalization}, one refers to the operation by which a
|
|
program, or a set of programs turned into a package, is made aware of and
|
|
able to support multiple languages. This is a generalization process,
|
|
by which the programs are untied from calling only English strings or
|
|
other English specific habits, and connected to generic ways of doing
|
|
the same, instead. Program developers may use various techniques to
|
|
internationalize their programs. Some of these have been standardized.
|
|
GNU @code{gettext} offers one of these standards. @xref{Programmers}.
|
|
|
|
By @dfn{localization}, one means the operation by which, in a set
|
|
of programs already internationalized, one gives the program all
|
|
needed information so that it can adapt itself to handle its input
|
|
and output in a fashion which is correct for some native language and
|
|
cultural habits. This is a particularisation process, by which generic
|
|
methods already implemented in an internationalized program are used
|
|
in specific ways. The programming environment puts several functions
|
|
to the programmers disposal which allow this runtime configuration.
|
|
The formal description of specific set of cultural habits for some
|
|
country, together with all associated translations targeted to the
|
|
same native language, is called the @dfn{locale} for this language
|
|
or country. Users achieve localization of programs by setting proper
|
|
values to special environment variables, prior to executing those
|
|
programs, identifying which locale should be used.
|
|
|
|
In fact, locale message support is only one component of the cultural
|
|
data that makes up a particular locale. There are a whole host of
|
|
routines and functions provided to aid programmers in developing
|
|
internationalized software and which allow them to access the data
|
|
stored in a particular locale. When someone presently refers to a
|
|
particular locale, they are obviously referring to the data stored
|
|
within that particular locale. Similarly, if a programmer is referring
|
|
to ``accessing the locale routines'', they are referring to the
|
|
complete suite of routines that access all of the locale's information.
|
|
|
|
One uses the expression @dfn{Native Language Support}, or merely NLS,
|
|
for speaking of the overall activity or feature encompassing both
|
|
internationalization and localization, allowing for multi-lingual
|
|
interactions in a program. In a nutshell, one could say that
|
|
internationalization is the operation by which further localizations
|
|
are made possible.
|
|
|
|
Also, very roughly said, when it comes to multi-lingual messages,
|
|
internationalization is usually taken care of by programmers, and
|
|
localization is usually taken care of by translators.
|
|
|
|
@node Aspects, Files, Concepts, Introduction
|
|
@section Aspects in Native Language Support
|
|
|
|
For a totally multi-lingual distribution, there are many things to
|
|
translate beyond output messages.
|
|
|
|
@itemize @bullet
|
|
@item
|
|
As of today, GNU @code{gettext} offers a complete toolset for
|
|
translating messages output by C programs. Perl scripts and shell
|
|
scripts will also need to be translated. Even if there are today some hooks
|
|
by which this can be done, these hooks are not integrated as well as they
|
|
should be.
|
|
|
|
@item
|
|
Some programs, like @code{autoconf} or @code{bison}, are able
|
|
to produce other programs (or scripts). Even if the generating
|
|
programs themselves are internationalized, the generated programs they
|
|
produce may need internationalization on their own, and this indirect
|
|
internationalization could be automated right from the generating
|
|
program. In fact, quite usually, generating and generated programs
|
|
could be internationalized independently, as the effort needed is
|
|
fairly orthogonal.
|
|
|
|
@item
|
|
A few programs include textual tables which might need translation
|
|
themselves, independently of the strings contained in the program
|
|
itself. For example, @w{RFC 1345} gives an English description for each
|
|
character which GNU @code{recode} is able to reconstruct at execution.
|
|
Since these descriptions are extracted from the RFC by mechanical means,
|
|
translating them properly would require a prior translation of the RFC
|
|
itself.
|
|
|
|
@item
|
|
Almost all programs accept options, which are often worded out so to
|
|
be descriptive for the English readers; one might want to consider
|
|
offering translated versions for program options as well.
|
|
|
|
@item
|
|
Many programs read, interpret, compile, or are somewhat driven by
|
|
input files which are texts containing keywords, identifiers, or
|
|
replies which are inherently translatable. For example, one may want
|
|
@code{gcc} to allow diacriticized characters in identifiers or use
|
|
translated keywords; @samp{rm -i} might accept something else than
|
|
@samp{y} or @samp{n} for replies, etc. Even if the program will
|
|
eventually make most of its output in the foreign languages, one has
|
|
to decide whether the input syntax, option values, etc., are to be
|
|
localized or not.
|
|
|
|
@item
|
|
The manual accompanying a package, as well as all documentation files
|
|
in the distribution, could surely be translated, too. Translating a
|
|
manual, with the intent of later keeping up with updates, is a major
|
|
undertaking in itself, generally.
|
|
|
|
@end itemize
|
|
|
|
As we already stressed, translation is only one aspect of locales.
|
|
Other internationalization aspects are not currently handled by GNU
|
|
@code{gettext}, but perhaps may be handled in future versions. There
|
|
are many attributes that are needed to define a country's cultural
|
|
conventions. These attributes include beside the country's native
|
|
language, the formatting of the date and time, the representation of
|
|
numbers, the symbols for currency, etc. These local @dfn{rules} are
|
|
termed the country's locale. The locale represents the knowledge
|
|
needed to support the country's native attributes.
|
|
|
|
There are a few major areas which may vary between countries and
|
|
hence, define what a locale must describe. The following list helps
|
|
putting multi-lingual messages into the proper context of other tasks
|
|
related to locales, and also presents some other areas which GNU
|
|
@code{gettext} might eventually tackle, maybe, one of these days.
|
|
|
|
@table @emph
|
|
|
|
@item Characters and Codesets
|
|
|
|
The codeset most commonly used through out the USA and most English
|
|
speaking parts of the world is the ASCII codeset. However, there are
|
|
many characters needed by various locales that are not found within
|
|
this codeset. The 8-bit @w{ISO 8859-1} code set has most of the special
|
|
characters needed to handle the major European languages. However, in
|
|
many cases, the @w{ISO 8859-1} font is not adequate. Hence each locale
|
|
will need to specify which codeset they need to use and will need
|
|
to have the appropriate character handling routines to cope with
|
|
the codeset.
|
|
|
|
@item Currency
|
|
|
|
The symbols used vary from country to country as does the position
|
|
used by the symbol. Software needs to be able to transparently
|
|
display currency figures in the native mode for each locale.
|
|
|
|
@item Dates
|
|
|
|
The format of date varies between locales. For example, Christmas day
|
|
in 1994 is written as 12/25/94 in the USA and as 25/12/94 in Australia.
|
|
Other countries might use @w{ISO 8061} dates, etc.
|
|
|
|
Time of the day may be noted as @var{hh}:@var{mm}, @var{hh}.@var{mm},
|
|
or otherwise. Some locales require time to be specified in 24-hour
|
|
mode rather than as AM or PM. Further, the nature and yearly extent
|
|
of the Daylight Saving correction vary widely between countries.
|
|
|
|
@item Numbers
|
|
|
|
Numbers can be represented differently in different locales.
|
|
For example, the following numbers are all written correctly for
|
|
their respective locales:
|
|
|
|
@example
|
|
12,345.67 English
|
|
12.345,67 French
|
|
1,2345.67 Asia
|
|
@end example
|
|
|
|
Some programs could go further and use different unit systems, like
|
|
English units or Metric units, or even take into account variants
|
|
about how numbers are spelled in full.
|
|
|
|
@item Messages
|
|
|
|
The most obvious area is the language support within a locale. This is
|
|
where GNU @code{gettext} provides the means for developers and users to
|
|
easily change the language that the software uses to communicate to
|
|
the user.
|
|
|
|
@end table
|
|
|
|
In the near future we see no chance that components of locale outside of
|
|
message handling will be made available for use in other
|
|
packages. The reason for this is that most modern systems provide
|
|
a more or less reasonable support for at least some of the missing
|
|
components. Another point is that the GNU @code{libc} and Linux will get
|
|
a new and complete implementation of the whole locale functionality
|
|
which could be adopted by system lacking a reasonable locale support.
|
|
|
|
@node Files, Overview, Aspects, Introduction
|
|
@section Files Conveying Translations
|
|
|
|
The letters PO in @file{.po} files means Portable Object, to
|
|
distinguish it from @file{.mo} files, where MO stands for Machine
|
|
Object. This paradigm, as well as the PO file format, is inspired
|
|
by the NLS standard developed by Uniforum, and implemented by Sun
|
|
in their Solaris system.
|
|
|
|
PO files are meant to be read and edited by humans, and associate each
|
|
original, translatable string of a given package with its translation
|
|
in a particular target language. A single PO file is dedicated to
|
|
a single target language. If a package supports many languages,
|
|
there is one such PO file per language supported, and each package
|
|
has its own set of PO files. These PO files are best created by
|
|
the @code{xgettext} program, and later updated or refreshed through
|
|
the @code{msgmerge} program. Program @code{xgettext} extracts all
|
|
marked messages from a set of C files and initializes a PO file with
|
|
empty translations. Program @code{msgmerge} takes care of adjusting
|
|
PO files between releases of the corresponding sources, commenting
|
|
obsolete entries, initializing new ones, and updating all source
|
|
line references. Files ending with @file{.pot} are kind of base
|
|
translation files found in distributions, in PO file format, and
|
|
@file{.pox} files are often temporary PO files.
|
|
|
|
MO files are meant to be read by programs, and are binary in nature.
|
|
A few systems already offer tools for creating and handling MO files
|
|
as part of the Native Language Support coming with the system, but the
|
|
format of these MO files is often different from system to system,
|
|
and non-portable. They do not necessary use @file{.mo} for file
|
|
extensions, but since system libraries are also used for accessing
|
|
these files, it works as long as the system is self-consistent about
|
|
it. If GNU @code{gettext} is able to interface with the tools already
|
|
provided with systems, it will consequently let these provided tools
|
|
take care of generating the MO files. Or else, if such tools are not
|
|
found or do not seem usable, GNU @code{gettext} will use its own ways
|
|
and its own format for MO files. Files ending with @file{.gmo} are
|
|
really MO files, when it is known that these files use the GNU format.
|
|
|
|
@node Overview, , Files, Introduction
|
|
@section Overview of GNU @code{gettext}
|
|
|
|
The following diagram summarizes the relation between the files
|
|
handled by GNU @code{gettext} and the tools acting on these files.
|
|
It is followed by a somewhat detailed explanations, which you should
|
|
read while keeping an eye on the diagram. Having a clear understanding
|
|
of these interrelations would surely help programmers, translators
|
|
and maintainers.
|
|
|
|
@example
|
|
@group
|
|
Original C Sources ---> PO mode ---> Marked C Sources ---.
|
|
|
|
|
.---------<--- GNU gettext Library |
|
|
.--- make <---+ |
|
|
| `---------<--------------------+-----------'
|
|
| |
|
|
| .-----<--- PACKAGE.pot <--- xgettext <---' .---<--- PO Compendium
|
|
| | | ^
|
|
| | `---. |
|
|
| `---. +---> PO mode ---.
|
|
| +----> msgmerge ------> LANG.pox --->--------' |
|
|
| .---' |
|
|
| | |
|
|
| `-------------<---------------. |
|
|
| +--- LANG.po <--- New LANG.pox <----'
|
|
| .--- LANG.gmo <--- msgfmt <---'
|
|
| |
|
|
| `---> install ---> /.../LANG/PACKAGE.mo ---.
|
|
| +---> "Hello world!"
|
|
`-------> install ---> /.../bin/PROGRAM -------'
|
|
@end group
|
|
@end example
|
|
|
|
The indication @samp{PO mode} appears in two places in this picture,
|
|
and you may safely read it as merely meaning ``hand editing'', using
|
|
any editor of your choice, really. However, for those of you being
|
|
the lucky users of GNU Emacs, PO mode has been specifically created
|
|
for providing a cozy environment for editing or modifying PO files.
|
|
While editing a PO file, PO mode allows for the easy browsing of
|
|
auxiliary and compendium PO files, as well as for following references into
|
|
the set of C program sources from which PO files have been derived.
|
|
It has a few special features, among which are the interactive marking
|
|
of program strings as translatable, and the validatation of PO files
|
|
with easy repositioning to PO file lines showing errors.
|
|
|
|
As a programmer, the first step to bringing GNU @code{gettext}
|
|
into your package is identifying, right in the C sources, those strings
|
|
which are meant to be translatable, and those which are untranslatable.
|
|
This tedious job can be done a little more comfortably using emacs PO
|
|
mode, but you can use any means familiar to you for modifying your
|
|
C sources. Beside this some other simple, standard changes are needed to
|
|
properly initialize the translation library. @xref{Sources}, for
|
|
more information about all this.
|
|
|
|
For newly written software the strings of course can and should be
|
|
marked while writing the it. The @code{gettext} approach makes this
|
|
very easy. Simply put the following lines at the beginning of each file
|
|
or in a central header file:
|
|
|
|
@example
|
|
@group
|
|
#define _(String) (String)
|
|
#define N_(String) (String)
|
|
#define textdomain(Domain)
|
|
#define bindtextdomain(Package, Directory)
|
|
@end group
|
|
@end example
|
|
|
|
@noindent
|
|
Doing this allows you to prepare the sources for internationalization.
|
|
Later when you feel ready for the step to use the @code{gettext} library
|
|
simply remove these definitions, include @file{libintl.h} and link
|
|
against @file{libintl.a}. That is all you have to change.
|
|
|
|
Once the C sources have been modified, the @code{xgettext} program
|
|
is used to find and extract all translatable strings, and create an
|
|
initial PO file out of all these. This @file{@var{package}.pot} file
|
|
contains all original program strings. It has sets of pointers to
|
|
exactly where in C sources each string is used. All translations
|
|
are set to empty. The letter @kbd{t} in @file{.pot} marks this as
|
|
a Template PO file, not yet oriented towards any particular language.
|
|
@xref{xgettext Invocation}, for more details about how one calls the
|
|
@code{xgettext} program. If you are @emph{really} lazy, you might
|
|
be interested at working a lot more right away, and preparing the
|
|
whole distribution setup (@pxref{Maintainers}). By doing so, you
|
|
spare yourself typing the @code{xgettext} command, as @code{make}
|
|
should now generate the proper things automatically for you!
|
|
|
|
The first time through, there is no @file{@var{lang}.po} yet, so the
|
|
@code{msgmerge} step may be skipped and replaced by a mere copy of
|
|
@file{@var{package}.pot} to @file{@var{lang}.pox}, where @var{lang}
|
|
represents the target language.
|
|
|
|
Then comes the initial translation of messages. Translation in
|
|
itself is a whole matter, still exclusively meant for humans,
|
|
and whose complexity far overwhelms the level of this manual.
|
|
Nevertheless, a few hints are given in some other chapter of this
|
|
manual (@pxref{Translators}). You will also find there indications
|
|
about how to contact translating teams, or becoming part of them,
|
|
for sharing your translating concerns with others who target the same
|
|
native language.
|
|
|
|
While adding the translated messages into the @file{@var{lang}.pox}
|
|
PO file, if you do not have GNU Emacs handy, you are on your own
|
|
for ensuring that your efforts fully respect the PO file format, and quoting
|
|
conventions (@pxref{PO Files}). This is surely not an impossible task,
|
|
as this is the way many people have handled PO files already for Uniforum or
|
|
Solaris. On the other hand, by using PO mode in GNU Emacs, most details
|
|
of PO file format are taken care of for you, but you have to acquire
|
|
some familiarity with PO mode itself. Besides main PO mode commands
|
|
(@pxref{Main PO Commands}), you should know how to move between entries
|
|
(@pxref{Entry Positioning}), and how to handle untranslated entries
|
|
(@pxref{Untranslated Entries}).
|
|
|
|
If some common translations have already been saved into a compendium
|
|
PO file, translators may use PO mode for initializing untranslated
|
|
entries from the compendium, and also save selected translations into
|
|
the compendium, updating it (@pxref{Compendium}). Compendium files
|
|
are meant to be exchanged between members of a given translation team.
|
|
|
|
Programs, or packages of programs, are dynamic in nature: users write
|
|
bug reports and suggestion for improvements, maintainers react by
|
|
modifying programs in various ways. The fact that a package has
|
|
already been internationalized should not make maintainers shy
|
|
of adding new strings, or modifying strings already translated.
|
|
They just do their job the best they can. For the Translation
|
|
Project to work smoothly, it is important that maintainers do not
|
|
carry translation concerns on their already loaded shoulders, and that
|
|
translators be kept as free as possible of programmatic concerns.
|
|
|
|
The only concern maintainers should have is carefully marking new
|
|
strings as translatable, when they should be, and do not otherwise
|
|
worry about them being translated, as this will come in proper time.
|
|
Consequently, when programs and their strings are adjusted in various
|
|
ways by maintainers, and for matters usually unrelated to translation,
|
|
@code{xgettext} would construct @file{@var{package}.pot} files which are
|
|
evolving over time, so the translations carried by @file{@var{lang}.po}
|
|
are slowly fading out of date.
|
|
|
|
It is important for translators (and even maintainers) to understand
|
|
that package translation is a continuous process in the lifetime of a
|
|
package, and not something which is done once and for all at the start.
|
|
After an initial burst of translation activity for a given package,
|
|
interventions are needed once in a while, because here and there,
|
|
translated entries become obsolete, and new untranslated entries
|
|
appear, needing translation.
|
|
|
|
The @code{msgmerge} program has the purpose of refreshing an already
|
|
existing @file{@var{lang}.po} file, by comparing it with a newer
|
|
@file{@var{package}.pot} template file, extracted by @code{xgettext}
|
|
out of recent C sources. The refreshing operation adjusts all
|
|
references to C source locations for strings, since these strings
|
|
move as programs are modified. Also, @code{msgmerge} comments out as
|
|
obsolete, in @file{@var{lang}.pox}, those already translated entries
|
|
which are no longer used in the program sources (@pxref{Obsolete
|
|
Entries}). It finally discovers new strings and inserts them in
|
|
the resulting PO file as untranslated entries (@pxref{Untranslated
|
|
Entries}). @xref{msgmerge Invocation}, for more information about what
|
|
@code{msgmerge} really does.
|
|
|
|
Whatever route or means taken, the goal is to obtain an updated
|
|
@file{@var{lang}.pox} file offering translations for all strings.
|
|
When this is properly achieved, this file @file{@var{lang}.pox} may
|
|
take the place of the previous official @file{@var{lang}.po} file.
|
|
|
|
The temporal mobility, or fluidity of PO files, is an integral part of
|
|
the translation game, and should be well understood, and accepted.
|
|
People resisting it will have a hard time participating in the
|
|
Translation Project, or will give a hard time to other participants! In
|
|
particular, maintainers should relax and include all available official
|
|
PO files in their distributions, even if these have not recently been
|
|
updated, without banging or otherwise trying to exert pressure on the
|
|
translator teams to get the job done. The pressure should rather come
|
|
from the community of users speaking a particular language, and
|
|
maintainers should consider themselves fairly relieved of any concern
|
|
about the adequacy of translation files. On the other hand, translators
|
|
should reasonably try updating the PO files they are responsible for,
|
|
while the package is undergoing pretest, prior to an official
|
|
distribution.
|
|
|
|
Once the PO file is complete and dependable, the @code{msgfmt} program
|
|
is used for turning the PO file into a machine-oriented format, which
|
|
may yield efficient retrieval of translations by the programs of the
|
|
package, whenever needed at runtime (@pxref{MO Files}). @xref{msgfmt
|
|
Invocation}, for more information about all modalities of execution
|
|
for the @code{msgfmt} program.
|
|
|
|
Finally, the modified and marked C sources are compiled and linked
|
|
with the GNU @code{gettext} library, usually through the operation of
|
|
@code{make}, given a suitable @file{Makefile} exists for the project,
|
|
and the resulting executable is installed somewhere users will find it.
|
|
The MO files themselves should also be properly installed. Given the
|
|
appropriate environment variables are set (@pxref{End Users}), the
|
|
program should localize itself automatically, whenever it executes.
|
|
|
|
The remainder of this manual has the purpose of explaining in depth the various
|
|
steps outlined above.
|
|
|
|
@node Basics, Sources, Introduction, Top
|
|
@chapter PO Files and PO Mode Basics
|
|
|
|
The GNU @code{gettext} toolset helps programmers and translators
|
|
at producing, updating and using translation files, mainly those
|
|
PO files which are textual, editable files. This chapter stresses
|
|
the format of PO files, and contains a PO mode starter. PO mode
|
|
description is spread throughout this manual instead of being concentrated
|
|
in one place. Here we present only the basics of PO mode.
|
|
|
|
@menu
|
|
* Installation:: Completing GNU @code{gettext} Installation
|
|
* PO Files:: The Format of PO Files
|
|
* Main PO Commands:: Main Commands
|
|
* Entry Positioning:: Entry Positioning
|
|
* Normalizing:: Normalizing Strings in Entries
|
|
@end menu
|
|
|
|
@node Installation, PO Files, Basics, Basics
|
|
@section Completing GNU @code{gettext} Installation
|
|
|
|
Once you have received, unpacked, configured and compiled the GNU
|
|
@code{gettext} distribution, the @samp{make install} command puts in
|
|
place the programs @code{xgettext}, @code{msgfmt}, @code{gettext}, and
|
|
@code{msgmerge}, as well as their available message catalogs. To
|
|
top off a comfortable installation, you might also want to make the
|
|
PO mode available to your GNU Emacs users.
|
|
|
|
During the installation of the PO mode, you might want modify your
|
|
file @file{.emacs}, once and for all, so it contains a few lines looking
|
|
like:
|
|
|
|
@example
|
|
(setq auto-mode-alist
|
|
(cons '("\\.po[tx]?\\'\\|\\.po\\." . po-mode) auto-mode-alist))
|
|
(autoload 'po-mode "po-mode")
|
|
@end example
|
|
|
|
Later, whenever you edit some @file{.po}, @file{.pot} or @file{.pox}
|
|
file, or any file having the string @samp{.po.} within its name,
|
|
Emacs loads @file{po-mode.elc} (or @file{po-mode.el}) as needed, and
|
|
automatically activates PO mode commands for the associated buffer.
|
|
The string @emph{PO} appears in the mode line for any buffer for
|
|
which PO mode is active. Many PO files may be active at once in a
|
|
single Emacs session.
|
|
|
|
If you are using Emacs version 20 or better, and have already installed
|
|
the appropriate international fonts on your system, you may also manage
|
|
for the these fonts to be automatically loaded and used for displaying
|
|
the translations on your Emacs screen, whenever necessary. For this to
|
|
happen, you might want to add the lines:
|
|
|
|
@example
|
|
(autoload 'po-find-file-coding-system "po-mode")
|
|
(modify-coding-system-alist 'file "\\.po[tx]?\\'\\|\\.po\\."
|
|
'po-find-file-coding-system)
|
|
@end example
|
|
|
|
@noindent
|
|
to your @file{.emacs} file.
|
|
|
|
@node PO Files, Main PO Commands, Installation, Basics
|
|
@section The Format of PO Files
|
|
|
|
A PO file is made up of many entries, each entry holding the relation
|
|
between an original untranslated string and its corresponding
|
|
translation. All entries in a given PO file usually pertain
|
|
to a single project, and all translations are expressed in a single
|
|
target language. One PO file @dfn{entry} has the following schematic
|
|
structure:
|
|
|
|
@example
|
|
@var{white-space}
|
|
# @var{translator-comments}
|
|
#. @var{automatic-comments}
|
|
#: @var{reference}@dots{}
|
|
#, @var{flag}@dots{}
|
|
msgid @var{untranslated-string}
|
|
msgstr @var{translated-string}
|
|
@end example
|
|
|
|
The general structure of a PO file should be well understood by
|
|
the translator. When using PO mode, very little has to be known
|
|
about the format details, as PO mode takes care of them for her.
|
|
|
|
Entries begin with some optional white space. Usually, when generated
|
|
through GNU @code{gettext} tools, there is exactly one blank line
|
|
between entries. Then comments follow, on lines all starting with the
|
|
character @kbd{#}. There are two kinds of comments: those which have
|
|
some white space immediately following the @kbd{#}, which comments are
|
|
created and maintained exclusively by the translator, and those which
|
|
have some non-white character just after the @kbd{#}, which comments
|
|
are created and maintained automatically by GNU @code{gettext} tools.
|
|
All comments, of either kind, are optional.
|
|
|
|
After white space and comments, entries show two strings, giving
|
|
first the untranslated string as it appears in the original program
|
|
sources, and then, the translation of this string. The original
|
|
string is introduced by the keyword @code{msgid}, and the translation,
|
|
by @code{msgstr}. The two strings, untranslated and translated,
|
|
are quoted in various ways in the PO file, using @kbd{"}
|
|
delimiters and @kbd{\} escapes, but the translator does not really
|
|
have to pay attention to the precise quoting format, as PO mode fully
|
|
intend to take care of quoting for her.
|
|
|
|
The @code{msgid} strings, as well as automatic comments, are produced
|
|
and managed by other GNU @code{gettext} tools, and PO mode does not
|
|
provide means for the translator to alter these. The most she can
|
|
do is merely deleting them, and only by deleting the whole entry.
|
|
On the other hand, the @code{msgstr} string, as well as translator
|
|
comments, are really meant for the translator, and PO mode gives her
|
|
the full control she needs.
|
|
|
|
The comment lines beginning with @kbd{#,} are special because they are
|
|
not completely ignored by the programs as comments generally are. The
|
|
comma separated list of @var{flag}s is used by the @code{msgfmt}
|
|
program to give the user some better disgnostic messages. Currently
|
|
there are two forms of flags defined:
|
|
|
|
@table @kbd
|
|
@item fuzzy
|
|
This flag can be generated by the @code{msgmerge} program or it can be
|
|
inserted by the translator herself. It shows that the @code{msgstr}
|
|
string might not be a correct translation (anymore). Only the translator
|
|
can judge if the translation requires further modification, or is
|
|
acceptable as is. Once satisfied with the translation, she then removes
|
|
this @kbd{fuzzy} attribute. The @code{msgmerge} programs inserts this
|
|
when it combined the @code{msgid} and @code{msgstr} entries after fuzzy
|
|
search only. @xref{Fuzzy Entries}.
|
|
|
|
@item c-format
|
|
@itemx no-c-format
|
|
These flags should not be added by a human. Instead only the
|
|
@code{xgettext} program adds them. In an automatized PO file processing
|
|
system as proposed here the user changes would be thrown away again as
|
|
soon as the @code{xgettext} program generates a new template file.
|
|
|
|
In case the @kbd{c-format} flag is given for a string the @code{msgfmt}
|
|
does some more tests to check to validity of the translation.
|
|
@xref{msgfmt Invocation}.
|
|
|
|
@end table
|
|
|
|
It happens that some lines, usually whitespace or comments, follow the
|
|
very last entry of a PO file. Such lines are not part of any entry,
|
|
and PO mode is unable to take action on those lines. By using the
|
|
PO mode function @w{@kbd{M-x po-normalize}}, the translator may get
|
|
rid of those spurious lines. @xref{Normalizing}.
|
|
|
|
The remainder of this section may be safely skipped by those using
|
|
PO mode, yet it may be interesting for everybody to have a better
|
|
idea of the precise format of a PO file. On the other hand, those
|
|
not having GNU Emacs handy should carefully continue reading on.
|
|
|
|
Each of @var{untranslated-string} and @var{translated-string} respects
|
|
the C syntax for a character string, including the surrounding quotes
|
|
and imbedded backslashed escape sequences. When the time comes
|
|
to write multi-line strings, one should not use escaped newlines.
|
|
Instead, a closing quote should follow the last character on the
|
|
line to be continued, and an opening quote should resume the string
|
|
at the beginning of the following PO file line. For example:
|
|
|
|
@example
|
|
msgid ""
|
|
"Here is an example of how one might continue a very long string\n"
|
|
"for the common case the string represents multi-line output.\n"
|
|
@end example
|
|
|
|
@noindent
|
|
In this example, the empty string is used on the first line, to
|
|
allow better alignment of the @kbd{H} from the word @samp{Here}
|
|
over the @kbd{f} from the word @samp{for}. In this example, the
|
|
@code{msgid} keyword is followed by three strings, which are meant
|
|
to be concatenated. Concatenating the empty string does not change
|
|
the resulting overall string, but it is a way for us to comply with
|
|
the necessity of @code{msgid} to be followed by a string on the same
|
|
line, while keeping the multi-line presentation left-justified, as
|
|
we find this to be a cleaner disposition. The empty string could have
|
|
been omitted, but only if the string starting with @samp{Here} was
|
|
promoted on the first line, right after @code{msgid}.@footnote{This
|
|
limitation is not imposed by GNU @code{gettext}, but comes from the
|
|
@code{msgfmt} implementation on Solaris.} It was not really necessary
|
|
either to switch between the two last quoted strings immediately after
|
|
the newline @samp{\n}, the switch could have occurred after @emph{any}
|
|
other character, we just did it this way because it is neater.
|
|
|
|
One should carefully distinguish between end of lines marked as
|
|
@samp{\n} @emph{inside} quotes, which are part of the represented
|
|
string, and end of lines in the PO file itself, outside string quotes,
|
|
which have no incidence on the represented string.
|
|
|
|
Outside strings, white lines and comments may be used freely.
|
|
Comments start at the beginning of a line with @samp{#} and extend
|
|
until the end of the PO file line. Comments written by translators
|
|
should have the initial @samp{#} immediately followed by some white
|
|
space. If the @samp{#} is not immediately followed by white space,
|
|
this comment is most likely generated and managed by specialized GNU
|
|
tools, and might disappear or be replaced unexpectedly when the PO
|
|
file is given to @code{msgmerge}.
|
|
|
|
@node Main PO Commands, Entry Positioning, PO Files, Basics
|
|
@section Main PO mode Commands
|
|
|
|
After setting up Emacs with something similar to the lines in
|
|
@ref{Installation}, PO mode is activated for a window when Emacs finds a
|
|
PO file in that window. This puts the window read-only and establishes a
|
|
po-mode-map, which is a genuine Emacs mode, in a way that is not derived
|
|
from text mode in any way. Functions found on @code{po-mode-hook},
|
|
if any, will be executed.
|
|
|
|
When PO mode is active in a window, the letters @samp{PO} appear
|
|
in the mode line for that window. The mode line also displays how
|
|
many entries of each kind are held in the PO file. For example,
|
|
the string @samp{132t+3f+10u+2o} would tell the translator that the
|
|
PO mode contains 132 translated entries (@pxref{Translated Entries},
|
|
3 fuzzy entries (@pxref{Fuzzy Entries}), 10 untranslated entries
|
|
(@pxref{Untranslated Entries}) and 2 obsolete entries (@pxref{Obsolete
|
|
Entries}). Zero-coefficients items are not shown. So, in this example, if
|
|
the fuzzy entries were unfuzzied, the untranslated entries were translated
|
|
and the obsolete entries were deleted, the mode line would merely display
|
|
@samp{145t} for the counters.
|
|
|
|
The main PO commands are those which do not fit into the other categories of
|
|
subsequent sections. These allow for quitting PO mode or for managing windows
|
|
in special ways.
|
|
|
|
@table @kbd
|
|
@item U
|
|
Undo last modification to the PO file.
|
|
|
|
@item Q
|
|
Quit processing and save the PO file.
|
|
|
|
@item q
|
|
Quit processing, possibly after confirmation.
|
|
|
|
@item O
|
|
Temporary leave the PO file window.
|
|
|
|
@item ?
|
|
@itemx h
|
|
Show help about PO mode.
|
|
|
|
@item =
|
|
Give some PO file statistics.
|
|
|
|
@item V
|
|
Batch validate the format of the whole PO file.
|
|
|
|
@end table
|
|
|
|
The command @kbd{U} (@code{po-undo}) interfaces to the GNU Emacs
|
|
@emph{undo} facility. @xref{Undo, , Undoing Changes, emacs, The Emacs
|
|
Editor}. Each time @kbd{U} is typed, modifications which the translator
|
|
did to the PO file are undone a little more. For the purpose of
|
|
undoing, each PO mode command is atomic. This is especially true for
|
|
the @kbd{@key{RET}} command: the whole edition made by using a single
|
|
use of this command is undone at once, even if the edition itself
|
|
implied several actions. However, while in the editing window, one
|
|
can undo the edition work quite parsimoniously.
|
|
|
|
The commands @kbd{Q} (@code{po-quit}) and @kbd{q}
|
|
(@code{po-confirm-and-quit}) are used when the translator is done with the
|
|
PO file. The former is a bit less verbose than the latter. If the file
|
|
has been modified, it is saved to disk first. In both cases, and prior to
|
|
all this, the commands check if some untranslated message remains in the
|
|
PO file and, if yes, the translator is asked if she really wants to leave
|
|
off working with this PO file. This is the preferred way of getting rid
|
|
of an Emacs PO file buffer. Merely killing it through the usual command
|
|
@w{@kbd{C-x k}} (@code{kill-buffer}) is not the tidiest way to proceed.
|
|
|
|
The command @kbd{O} (@code{po-other-window}) is another, softer way,
|
|
to leave PO mode, temporarily. It just moves the cursor to some other
|
|
Emacs window, and pops one if necessary. For example, if the translator
|
|
just got PO mode to show some source context in some other, she might
|
|
discover some apparent bug in the program source that needs correction.
|
|
This command allows the translator to change sex, become a programmer,
|
|
and have the cursor right into the window containing the program she
|
|
(or rather @emph{he}) wants to modify. By later getting the cursor back
|
|
in the PO file window, or by asking Emacs to edit this file once again,
|
|
PO mode is then recovered.
|
|
|
|
The command @kbd{h} (@code{po-help}) displays a summary of all available PO
|
|
mode commands. The translator should then type any character to resume
|
|
normal PO mode operations. The command @kbd{?} has the same effect
|
|
as @kbd{h}.
|
|
|
|
The command @kbd{=} (@code{po-statistics}) computes the total number of
|
|
entries in the PO file, the ordinal of the current entry (counted from
|
|
1), the number of untranslated entries, the number of obsolete entries,
|
|
and displays all these numbers.
|
|
|
|
The command @kbd{V} (@code{po-validate}) launches @code{msgfmt} in verbose
|
|
mode over the current PO file. This command first offers to save the
|
|
current PO file on disk. The @code{msgfmt} tool, from GNU @code{gettext},
|
|
has the purpose of creating a MO file out of a PO file, and PO mode uses
|
|
the features of this program for checking the overall format of a PO file,
|
|
as well as all individual entries.
|
|
|
|
The program @code{msgfmt} runs asynchronously with Emacs, so the
|
|
translator regains control immediately while her PO file is being studied.
|
|
Error output is collected in the GNU Emacs @samp{*compilation*} buffer,
|
|
displayed in another window. The regular GNU Emacs command @kbd{C-x`}
|
|
(@code{next-error}), as well as other usual compile commands, allow the
|
|
translator to reposition quickly to the offending parts of the PO file.
|
|
Once the cursor is on the line in error, the translator may decide on
|
|
any PO mode action which would help correcting the error.
|
|
|
|
@node Entry Positioning, Normalizing, Main PO Commands, Basics
|
|
@section Entry Positioning
|
|
|
|
The cursor in a PO file window is almost always part of
|
|
an entry. The only exceptions are the special case when the cursor
|
|
is after the last entry in the file, or when the PO file is
|
|
empty. The entry where the cursor is found to be is said to be the
|
|
current entry. Many PO mode commands operate on the current entry,
|
|
so moving the cursor does more than allowing the translator to browse
|
|
the PO file, this also selects on which entry commands operate.
|
|
|
|
Some PO mode commands alter the position of the cursor in a specialized
|
|
way. A few of those special purpose positioning are described here,
|
|
the others are described in following sections.
|
|
|
|
@table @kbd
|
|
|
|
@item .
|
|
Redisplay the current entry.
|
|
|
|
@item n
|
|
@itemx n
|
|
Select the entry after the current one.
|
|
|
|
@item p
|
|
@itemx p
|
|
Select the entry before the current one.
|
|
|
|
@item <
|
|
Select the first entry in the PO file.
|
|
|
|
@item >
|
|
Select the last entry in the PO file.
|
|
|
|
@item m
|
|
Record the location of the current entry for later use.
|
|
|
|
@item l
|
|
Return to a previously saved entry location.
|
|
|
|
@item x
|
|
Exchange the current entry location with the previously saved one.
|
|
|
|
@end table
|
|
|
|
Any GNU Emacs command able to reposition the cursor may be used
|
|
to select the current entry in PO mode, including commands which
|
|
move by characters, lines, paragraphs, screens or pages, and search
|
|
commands. However, there is a kind of standard way to display the
|
|
current entry in PO mode, which usual GNU Emacs commands moving
|
|
the cursor do not especially try to enforce. The command @kbd{.}
|
|
(@code{po-current-entry}) has the sole purpose of redisplaying the
|
|
current entry properly, after the current entry has been changed by
|
|
means external to PO mode, or the Emacs screen otherwise altered.
|
|
|
|
It is yet to be decided if PO mode helps the translator, or otherwise
|
|
irritates her, by forcing a rigid window disposition while she
|
|
is doing her work. We originally had quite precise ideas about
|
|
how windows should behave, but on the other hand, anyone used to
|
|
GNU Emacs is often happy to keep full control. Maybe a fixed window
|
|
disposition might be offered as a PO mode option that the translator
|
|
might activate or deactivate at will, so it could be offered on an
|
|
experimental basis. If nobody feels a real need for using it, or
|
|
a compulsion for writing it, we should drop this whole idea.
|
|
The incentive for doing it should come from translators rather than
|
|
programmers, as opinions from an experienced translator are surely
|
|
more worth to me than opinions from programmers @emph{thinking} about
|
|
how @emph{others} should do translation.
|
|
|
|
The commands @kbd{n} (@code{po-next-entry}) and @kbd{p}
|
|
(@code{po-previous-entry}) move the cursor the entry following,
|
|
or preceding, the current one. If @kbd{n} is given while the
|
|
cursor is on the last entry of the PO file, or if @kbd{p}
|
|
is given while the cursor is on the first entry, no move is done.
|
|
|
|
The commands @kbd{<} (@code{po-first-entry}) and @kbd{>}
|
|
(@code{po-last-entry}) move the cursor to the first entry, or last
|
|
entry, of the PO file. When the cursor is located past the last
|
|
entry in a PO file, most PO mode commands will return an error saying
|
|
@samp{After last entry}. Moreover, the commands @kbd{<} and @kbd{>}
|
|
have the special property of being able to work even when the cursor
|
|
is not into some PO file entry, and one may use them for nicely
|
|
correcting this situation. But even these commands will fail on a
|
|
truly empty PO file. There are development plans for the PO mode for it
|
|
to interactively fill an empty PO file from sources. @xref{Marking}.
|
|
|
|
The translator may decide, before working at the translation of
|
|
a particular entry, that she needs to browse the remainder of the
|
|
PO file, maybe for finding the terminology or phraseology used
|
|
in related entries. She can of course use the standard Emacs idioms
|
|
for saving the current cursor location in some register, and use that
|
|
register for getting back, or else, use the location ring.
|
|
|
|
PO mode offers another approach, by which cursor locations may be saved
|
|
onto a special stack. The command @kbd{m} (@code{po-push-location})
|
|
merely adds the location of current entry to the stack, pushing
|
|
the already saved locations under the new one. The command
|
|
@kbd{r} (@code{po-pop-location}) consumes the top stack element and
|
|
reposition the cursor to the entry associated with that top element.
|
|
This position is then lost, for the next @kbd{r} will move the cursor
|
|
to the previously saved location, and so on until no locations remain
|
|
on the stack.
|
|
|
|
If the translator wants the position to be kept on the location stack,
|
|
maybe for taking a look at the entry associated with the top
|
|
element, then go elsewhere with the intent of getting back later, she
|
|
ought to use @kbd{m} immediately after @kbd{r}.
|
|
|
|
The command @kbd{x} (@code{po-exchange-location}) simultaneously
|
|
reposition the cursor to the entry associated with the top element of
|
|
the stack of saved locations, and replace that top element with the
|
|
location of the current entry before the move. Consequently, repeating
|
|
the @kbd{x} command toggles alternatively between two entries.
|
|
For achieving this, the translator will position the cursor on the
|
|
first entry, use @kbd{m}, then position to the second entry, and
|
|
merely use @kbd{x} for making the switch.
|
|
|
|
@node Normalizing, , Entry Positioning, Basics
|
|
@section Normalizing Strings in Entries
|
|
|
|
There are many different ways for encoding a particular string into a
|
|
PO file entry, because there are so many different ways to split and
|
|
quote multi-line strings, and even, to represent special characters
|
|
by backslahsed escaped sequences. Some features of PO mode rely on
|
|
the ability for PO mode to scan an already existing PO file for a
|
|
particular string encoded into the @code{msgid} field of some entry.
|
|
Even if PO mode has internally all the built-in machinery for
|
|
implementing this recognition easily, doing it fast is technically
|
|
difficult. To facilitate a solution to this efficiency problem,
|
|
we decided on a canonical representation for strings.
|
|
|
|
A conventional representation of strings in a PO file is currently
|
|
under discussion, and PO mode experiments with a canonical representation.
|
|
Having both @code{xgettext} and PO mode converging towards a uniform
|
|
way of representing equivalent strings would be useful, as the internal
|
|
normalization needed by PO mode could be automatically satisfied
|
|
when using @code{xgettext} from GNU @code{gettext}. An explicit
|
|
PO mode normalization should then be only necessary for PO files
|
|
imported from elsewhere, or for when the convention itself evolves.
|
|
|
|
So, for achieving normalization of at least the strings of a given
|
|
PO file needing a canonical representation, the following PO mode
|
|
command is available:
|
|
|
|
@table @kbd
|
|
@item M-x po-normalize
|
|
Tidy the whole PO file by making entries more uniform.
|
|
|
|
@end table
|
|
|
|
The special command @kbd{M-x po-normalize}, which has no associate
|
|
keys, revises all entries, ensuring that strings of both original
|
|
and translated entries use uniform internal quoting in the PO file.
|
|
It also removes any crumb after the last entry. This command may be
|
|
useful for PO files freshly imported from elsewhere, or if we ever
|
|
improve on the canonical quoting format we use. This canonical format
|
|
is not only meant for getting cleaner PO files, but also for greatly
|
|
speeding up @code{msgid} string lookup for some other PO mode commands.
|
|
|
|
@kbd{M-x po-normalize} presently makes three passes over the entries.
|
|
The first implements heuristics for converting PO files for GNU
|
|
@code{gettext} 0.6 and earlier, in which @code{msgid} and @code{msgstr}
|
|
fields were using K&R style C string syntax for multi-line strings.
|
|
These heuristics may fail for comments not related to obsolete
|
|
entries and ending with a backslash; they also depend on subsequent
|
|
passes for finalizing the proper commenting of continued lines for
|
|
obsolete entries. This first pass might disappear once all oldish PO
|
|
files would have been adjusted. The second and third pass normalize
|
|
all @code{msgid} and @code{msgstr} strings respectively. They also
|
|
clean out those trailing backslashes used by XView's @code{msgfmt}
|
|
for continued lines.
|
|
|
|
Having such an explicit normalizing command allows for importing PO
|
|
files from other sources, but also eases the evolution of the current
|
|
convention, evolution driven mostly by aesthetic concerns, as of now.
|
|
It is easy to make suggested adjustments at a later time, as the
|
|
normalizing command and eventually, other GNU @code{gettext} tools
|
|
should greatly automate conformance. A description of the canonical
|
|
string format is given below, for the particular benefit of those not
|
|
having GNU Emacs handy, and who would nevertheless want to handcraft
|
|
their PO files in nice ways.
|
|
|
|
Right now, in PO mode, strings are single line or multi-line. A string
|
|
goes multi-line if and only if it has @emph{embedded} newlines, that
|
|
is, if it matches @samp{[^\n]\n+[^\n]}. So, we would have:
|
|
|
|
@example
|
|
msgstr "\n\nHello, world!\n\n\n"
|
|
@end example
|
|
|
|
but, replacing the space by a newline, this becomes:
|
|
|
|
@example
|
|
msgstr ""
|
|
"\n"
|
|
"\n"
|
|
"Hello,\n"
|
|
"world!\n"
|
|
"\n"
|
|
"\n"
|
|
@end example
|
|
|
|
We are deliberately using a caricatural example, here, to make the
|
|
point clearer. Usually, multi-lines are not that bad looking.
|
|
It is probable that we will implement the following suggestion.
|
|
We might lump together all initial newlines into the empty string,
|
|
and also all newlines introducing empty lines (that is, for @w{@var{n}
|
|
> 1}, the @var{n}-1'th last newlines would go together on a separate
|
|
string), so making the previous example appear:
|
|
|
|
@example
|
|
msgstr "\n\n"
|
|
"Hello,\n"
|
|
"world!\n"
|
|
"\n\n"
|
|
@end example
|
|
|
|
There are a few yet undecided little points about string normalization,
|
|
to be documented in this manual, once these questions settle.
|
|
|
|
@node Sources, Initial, Basics, Top
|
|
@chapter Preparing Program Sources
|
|
|
|
@c FIXME: Rewrite (the whole chapter).
|
|
|
|
For the programmer, changes to the C source code fall into three
|
|
categories. First, you have to make the localization functions
|
|
known to all modules needing message translation. Second, you should
|
|
properly trigger the operation of GNU @code{gettext} when the program
|
|
initializes, usually from the @code{main} function. Last, you should
|
|
identify and especially mark all constant strings in your program
|
|
needing translation.
|
|
|
|
Presuming that your set of programs, or package, has been adjusted
|
|
so all needed GNU @code{gettext} files are available, and your
|
|
@file{Makefile} files are adjusted (@pxref{Maintainers}), each C module
|
|
having translated C strings should contain the line:
|
|
|
|
@example
|
|
#include <libintl.h>
|
|
@end example
|
|
|
|
The remaining changes to your C sources are discussed in the further
|
|
sections of this chapter.
|
|
|
|
@menu
|
|
* Triggering:: Triggering @code{gettext} Operations
|
|
* Mark Keywords:: How Marks Appears in Sources
|
|
* Marking:: Marking Translatable Strings
|
|
* c-format:: Telling something about the following string
|
|
* Special cases:: Special Cases of Translatable Strings
|
|
@end menu
|
|
|
|
@node Triggering, Mark Keywords, Sources, Sources
|
|
@section Triggering @code{gettext} Operations
|
|
|
|
The initialization of locale data should be done with more or less
|
|
the same code in every program, as demonstrated below:
|
|
|
|
@example
|
|
@group
|
|
int
|
|
main (argc, argv)
|
|
int argc;
|
|
char argv;
|
|
@{
|
|
@dots{}
|
|
setlocale (LC_ALL, "");
|
|
bindtextdomain (PACKAGE, LOCALEDIR);
|
|
textdomain (PACKAGE);
|
|
@dots{}
|
|
@}
|
|
@end group
|
|
@end example
|
|
|
|
@var{PACKAGE} and @var{LOCALEDIR} should be provided either by
|
|
@file{config.h} or by the Makefile. For now consult the @code{gettext}
|
|
sources for more information.
|
|
|
|
The use of @code{LC_ALL} might not be appropriate for you.
|
|
@code{LC_ALL} includes all locale categories and especially
|
|
@code{LC_CTYPE}. This later category is responsible for determining
|
|
character classes with the @code{isalnum} etc. functions from
|
|
@file{ctype.h} which could especially for programs, which process some
|
|
kind of input language, be wrong. For example this would mean that a
|
|
source code using the @,{c} (c-cedilla character) is runnable in
|
|
France but not in the U.S.
|
|
|
|
Some systems also have problems with parsing number using the
|
|
@code{scanf} functions if an other but the @code{LC_ALL} locale is used.
|
|
The standards say that additional formats but the one known in the
|
|
@code{"C"} locale might be recognized. But some systems seem to reject
|
|
numbers in the @code{"C"} locale format. In some situation, it might
|
|
also be a problem with the notation itself which makes it impossible to
|
|
recognize whether the number is in the @code{"C"} locale or the local
|
|
format. This can happen if thousands separator characters are used.
|
|
Some locales define this character according to the national
|
|
conventions to @code{'.'} which is the same character used in the
|
|
@code{"C"} locale to denote the decimal point.
|
|
|
|
So it is sometimes necessary to replace the @code{LC_ALL} line in the
|
|
code above by a sequence of @code{setlocale} lines
|
|
|
|
@example
|
|
@group
|
|
@{
|
|
@dots{}
|
|
setlocale (LC_TIME, "");
|
|
setlocale (LC_MESSAGES, "");
|
|
@dots{}
|
|
@}
|
|
@end group
|
|
@end example
|
|
|
|
@noindent
|
|
or to switch for and back to the character class in question. On all
|
|
POSIX conformant systems the locale categories @code{LC_CTYPE},
|
|
@code{LC_COLLATE}, @code{LC_MONETARY}, @code{LC_NUMERIC}, and
|
|
@code{LC_TIME} are available. On some modern systems there is also a
|
|
locale @code{LC_MESSAGES} which is called on some old, XPG2 compliant
|
|
systems @code{LC_RESPONSES}.
|
|
|
|
@node Mark Keywords, Marking, Triggering, Sources
|
|
@section How Marks Appears in Sources
|
|
|
|
All strings requiring translation should be marked in the C sources. Marking
|
|
is done in such a way that each translatable string appears to be
|
|
the sole argument of some function or preprocessor macro. There are
|
|
only a few such possible functions or macros meant for translation,
|
|
and their names are said to be marking keywords. The marking is
|
|
attached to strings themselves, rather than to what we do with them.
|
|
This approach has more uses. A blatant example is an error message
|
|
produced by formatting. The format string needs translation, as
|
|
well as some strings inserted through some @samp{%s} specification
|
|
in the format, while the result from @code{sprintf} may have so many
|
|
different instances that it is impractical to list them all in some
|
|
@samp{error_string_out()} routine, say.
|
|
|
|
This marking operation has two goals. The first goal of marking
|
|
is for triggering the retrieval of the translation, at run time.
|
|
The keyword are possibly resolved into a routine able to dynamically
|
|
return the proper translation, as far as possible or wanted, for the
|
|
argument string. Most localizable strings are found in executable
|
|
positions, that is, attached to variables or given as parameters to
|
|
functions. But this is not universal usage, and some translatable
|
|
strings appear in structured initializations. @xref{Special cases}.
|
|
|
|
The second goal of the marking operation is to help @code{xgettext}
|
|
at properly extracting all translatable strings when it scans a set
|
|
of program sources and produces PO file templates.
|
|
|
|
The canonical keyword for marking translatable strings is
|
|
@samp{gettext}, it gave its name to the whole GNU @code{gettext}
|
|
package. For packages making only light use of the @samp{gettext}
|
|
keyword, macro or function, it is easily used @emph{as is}. However,
|
|
for packages using the @code{gettext} interface more heavily, it
|
|
is usually more convenient to give the main keyword a shorter, less
|
|
obtrusive name. Indeed, the keyword might appear on a lot of strings
|
|
all over the package, and programmers usually do not want nor need
|
|
their program sources to remind them forcefully, all the time, that they
|
|
are internationalized. Further, a long keyword has the disadvantage
|
|
of using more horizontal space, forcing more indentation work on
|
|
sources for those trying to keep them within 79 or 80 columns.
|
|
|
|
Many packages use @samp{_} (a simple underline) as a keyword,
|
|
and write @samp{_("Translatable string")} instead of @samp{gettext
|
|
("Translatable string")}. Further, the coding rule, from GNU standards,
|
|
wanting that there is a space between the keyword and the opening
|
|
parenthesis is relaxed, in practice, for this particular usage.
|
|
So, the textual overhead per translatable string is reduced to
|
|
only three characters: the underline and the two parentheses.
|
|
However, even if GNU @code{gettext} uses this convention internally,
|
|
it does not offer it officially. The real, genuine keyword is truly
|
|
@samp{gettext} indeed. It is fairly easy for those wanting to use
|
|
@samp{_} instead of @samp{gettext} to declare:
|
|
|
|
@example
|
|
#include <libintl.h>
|
|
#define _(String) gettext (String)
|
|
@end example
|
|
|
|
@noindent
|
|
instead of merely using @samp{#include <libintl.h>}.
|
|
|
|
Later on, the maintenance is relatively easy. If, as a programmer,
|
|
you add or modify a string, you will have to ask yourself if the
|
|
new or altered string requires translation, and include it within
|
|
@samp{_()} if you think it should be translated. @samp{"%s: %d"} is
|
|
an example of string @emph{not} requiring translation!
|
|
|
|
@node Marking, c-format, Mark Keywords, Sources
|
|
@section Marking Translatable Strings
|
|
|
|
In PO mode, one set of features is meant more for the programmer than
|
|
for the translator, and allows him to interactively mark which strings,
|
|
in a set of program sources, are translatable, and which are not.
|
|
Even if it is a fairly easy job for a programmer to find and mark
|
|
such strings by other means, using any editor of his choice, PO mode
|
|
makes this work more comfortable. Further, this gives translators
|
|
who feel a little like programmers, or programmers who feel a little
|
|
like translators, a tool letting them work at marking translatable
|
|
strings in the program sources, while simultaneously producing a set of
|
|
translation in some language, for the package being internationalized.
|
|
|
|
The set of program sources, targetted by the PO mode commands describe
|
|
here, should have an Emacs tags table constructed for your project,
|
|
prior to using these PO file commands. This is easy to do. In any
|
|
shell window, change the directory to the root of your project, then
|
|
execute a command resembling:
|
|
|
|
@example
|
|
etags src/*.[hc] lib/*.[hc]
|
|
@end example
|
|
|
|
@noindent
|
|
presuming here you want to process all @file{.h} and @file{.c} files
|
|
from the @file{src/} and @file{lib/} directories. This command will
|
|
explore all said files and create a @file{TAGS} file in your root
|
|
directory, somewhat summarizing the contents using a special file
|
|
format Emacs can understand.
|
|
|
|
For packages following the GNU coding standards, there is
|
|
a make goal @code{tags} or @code{TAGS} which construct the tag files in
|
|
all directories and for all files containing source code.
|
|
|
|
Once your @file{TAGS} file is ready, the following commands assist
|
|
the programmer at marking translatable strings in his set of sources.
|
|
But these commands are necessarily driven from within a PO file
|
|
window, and it is likely that you do not even have such a PO file yet.
|
|
This is not a problem at all, as you may safely open a new, empty PO
|
|
file, mainly for using these commands. This empty PO file will slowly
|
|
fill in while you mark strings as translatable in your program sources.
|
|
|
|
@table @kbd
|
|
@item ,
|
|
Search through program sources for a string which looks like a
|
|
candidate for translation.
|
|
|
|
@item M-,
|
|
Mark the last string found with @samp{_()}.
|
|
|
|
@item M-.
|
|
Mark the last string found with a keyword taken from a set of possible
|
|
keywords. This command with a prefix allows some management of these
|
|
keywords.
|
|
|
|
@end table
|
|
|
|
The @kbd{,} (@code{po-tags-search}) command search for the next
|
|
occurrence of a string which looks like a possible candidate for
|
|
translation, and displays the program source in another Emacs window,
|
|
positioned in such a way that the string is near the top of this other
|
|
window. If the string is too big to fit whole in this window, it is
|
|
positioned so only its end is shown. In any case, the cursor
|
|
is left in the PO file window. If the shown string would be better
|
|
presented differently in different native languages, you may mark it
|
|
using @kbd{M-,} or @kbd{M-.}. Otherwise, you might rather ignore it
|
|
and skip to the next string by merely repeating the @kbd{,} command.
|
|
|
|
A string is a good candidate for translation if it contains a sequence
|
|
of three or more letters. A string containing at most two letters in
|
|
a row will be considered as a candidate if it has more letters than
|
|
non-letters. The command disregards strings containing no letters,
|
|
or isolated letters only. It also disregards strings within comments,
|
|
or strings already marked with some keyword PO mode knows (see below).
|
|
|
|
If you have never told Emacs about some @file{TAGS} file to use, the
|
|
command will request that you specify one from the minibuffer, the
|
|
first time you use the command. You may later change your @file{TAGS}
|
|
file by using the regular Emacs command @w{@kbd{M-x visit-tags-table}},
|
|
which will ask you to name the precise @file{TAGS} file you want
|
|
to use. @xref{Tags, , Tag Tables, emacs, The Emacs Editor}.
|
|
|
|
Each time you use the @kbd{,} command, the search resumes from where it was
|
|
left by the previous search, and goes through all program sources,
|
|
obeying the @file{TAGS} file, until all sources have been processed.
|
|
However, by giving a prefix argument to the command @w{(@kbd{C-u
|
|
,})}, you may request that the search be restarted all over again
|
|
from the first program source; but in this case, strings that you
|
|
recently marked as translatable will be automatically skipped.
|
|
|
|
Using this @kbd{,} command does not prevent using of other regular
|
|
Emacs tags commands. For example, regular @code{tags-search} or
|
|
@code{tags-query-replace} commands may be used without disrupting the
|
|
independent @kbd{,} search sequence. However, as implemented, the
|
|
@emph{initial} @kbd{,} command (or the @kbd{,} command is used with a
|
|
prefix) might also reinitialize the regular Emacs tags searching to the
|
|
first tags file, this reinitialization might be considered spurious.
|
|
|
|
The @kbd{M-,} (@code{po-mark-translatable}) command will mark the
|
|
recently found string with the @samp{_} keyword. The @kbd{M-.}
|
|
(@code{po-select-mark-and-mark}) command will request that you type
|
|
one keyword from the minibuffer and use that keyword for marking
|
|
the string. Both commands will automatically create a new PO file
|
|
untranslated entry for the string being marked, and make it the
|
|
current entry (making it easy for you to immediately proceed to its
|
|
translation, if you feel like doing it right away). It is possible
|
|
that the modifications made to the program source by @kbd{M-,} or
|
|
@kbd{M-.} render some source line longer than 80 columns, forcing you
|
|
to break and re-indent this line differently. You may use the @kbd{O}
|
|
command from PO mode, or any other window changing command from
|
|
GNU Emacs, to break out into the program source window, and do any
|
|
needed adjustments. You will have to use some regular Emacs command
|
|
to return the cursor to the PO file window, if you want command
|
|
@kbd{,} for the next string, say.
|
|
|
|
The @kbd{M-.} command has a few built-in speedups, so you do not
|
|
have to explicitly type all keywords all the time. The first such
|
|
speedup is that you are presented with a @emph{preferred} keyword,
|
|
which you may accept by merely typing @kbd{@key{RET}} at the prompt.
|
|
The second speedup is that you may type any non-ambiguous prefix of the
|
|
keyword you really mean, and the command will complete it automatically
|
|
for you. This also means that PO mode has to @emph{know} all
|
|
your possible keywords, and that it will not accept mistyped keywords.
|
|
|
|
If you reply @kbd{?} to the keyword request, the command gives a
|
|
list of all known keywords, from which you may choose. When the
|
|
command is prefixed by an argument @w{(@kbd{C-u M-.})}, it inhibits
|
|
updating any program source or PO file buffer, and does some simple
|
|
keyword management instead. In this case, the command asks for a
|
|
keyword, written in full, which becomes a new allowed keyword for
|
|
later @kbd{M-.} commands. Moreover, this new keyword automatically
|
|
becomes the @emph{preferred} keyword for later commands. By typing
|
|
an already known keyword in response to @w{@kbd{C-u M-.}}, one merely
|
|
changes the @emph{preferred} keyword and does nothing more.
|
|
|
|
All keywords known for @kbd{M-.} are recognized by the @kbd{,} command
|
|
when scanning for strings, and strings already marked by any of those
|
|
known keywords are automatically skipped. If many PO files are opened
|
|
simultaneously, each one has its own independent set of known keywords.
|
|
There is no provision in PO mode, currently, for deleting a known
|
|
keyword, you have to quit the file (maybe using @kbd{q}) and reopen
|
|
it afresh. When a PO file is newly brought up in an Emacs window, only
|
|
@samp{gettext} and @samp{_} are known as keywords, and @samp{gettext}
|
|
is preferred for the @kbd{M-.} command. In fact, this is not useful to
|
|
prefer @samp{_}, as this one is already built in the @kbd{M-,} command.
|
|
|
|
@node c-format, Special cases, Marking, Sources
|
|
@section Special Comments preceding Keywords
|
|
|
|
@c FIXME document c-format and no-c-format.
|
|
|
|
In C programs strings are often used within calls of functions from the
|
|
@code{printf} family. The special thing about these format strings is
|
|
that they can contain format specifiers introduced with @kbd{%}. Assume
|
|
we have the code
|
|
|
|
@example
|
|
printf (gettext ("String `%s' has %d characters\n"), s, strlen (s));
|
|
@end example
|
|
|
|
@noindent
|
|
A possible German translation for the above string might be:
|
|
|
|
@example
|
|
"%d Zeichen lang ist die Zeichenkette `%s'"
|
|
@end example
|
|
|
|
A C programmer, even if he cannot speak German, will recognize that
|
|
there is something wrong here. The order of the two format specifiers
|
|
is changed but of course the arguments in the @code{printf} don't have.
|
|
This will most probably lead to problems because now the length of the
|
|
string is regarded as the address.
|
|
|
|
To prevent errors at runtime caused by translations the @code{msgfmt}
|
|
tool can check statically whether the arguments in the original and the
|
|
translation string match in type and number. If this is not the case a
|
|
warning will be given and the error cannot causes problems at runtime.
|
|
|
|
@noindent
|
|
If the word order in the above German translation would be correct one
|
|
would have to write
|
|
|
|
@example
|
|
"%2$d Zeichen lang ist die Zeichenkette `%1$s'"
|
|
@end example
|
|
|
|
@noindent
|
|
The routines in @code{msgfmt} know about this special notation.
|
|
|
|
Because not all strings in a program must be format strings it is not
|
|
useful for @code{msgfmt} to test all the strings in the @file{.po} file.
|
|
This might cause problems because the string might contain what looks
|
|
like a format specifier, but the string is not used in @code{printf}.
|
|
|
|
Therefore the @code{xgettext} adds a special tag to those messages it
|
|
thinks might be a format string. There is no absolute rule for this,
|
|
only a heuristic. In the @file{.po} file the entry is marked using the
|
|
@code{c-format} flag in the @kbd{#,} comment line (@pxref{PO Files}).
|
|
|
|
The careful reader now might say that this again can cause problems.
|
|
The heuristic might guess it wrong. This is true and therefore
|
|
@code{xgettext} knows about special kind of comment which lets
|
|
the programmer take over the decision. If in the same line or
|
|
the immediately preceding line of the @code{gettext} keyword
|
|
the @code{xgettext} program find a comment containing the words
|
|
@kbd{xgettext:c-format} it will mark the string in any case with
|
|
the @kbd{c-format} flag. This kind of comment should be used when
|
|
@code{xgettext} does not recognize the string as a format string but
|
|
is really is one and it should be tested. Please note that when the
|
|
comment is in the same line of the @code{gettext} keyword, it must be
|
|
before the string to be translated.
|
|
|
|
This situation happens quite often. The @code{printf} function is often
|
|
called with strings which do not contain a format specifier. Of course
|
|
one would normally use @code{fputs} but it does happen. In this case
|
|
@code{xgettext} does not recognize this as a format string but what
|
|
happens if the translation introduces a valid format specifier? The
|
|
@code{printf} function will try to access one of the parameter but none
|
|
exists because the original code does not refer to any parameter.
|
|
|
|
@code{xgettext} of course could make a wrong decision the other way
|
|
round. A string marked as a format string is not really a format
|
|
string. In this case the @code{msgfmt} might give too many warnings and
|
|
would prevent translating the @file{.po} file. The method to prevent
|
|
this wrong decision is similar to the one used above, only the comment
|
|
to use must contain the string @kbd{xgettext:no-c-format}.
|
|
|
|
If a string is marked with @kbd{c-format} and this is not correct the
|
|
user can find out who is responsible for the decision. @xref{xgettext
|
|
Invocation} to see how the @kbd{--debug} option can be used for solving
|
|
this problem.
|
|
|
|
@node Special cases, , c-format, Sources
|
|
@section Special Cases of Translatable Strings
|
|
|
|
The attentive reader might now point out that it is not always possible
|
|
to mark translatable string with @code{gettext} or something like this.
|
|
Consider the following case:
|
|
|
|
@example
|
|
@group
|
|
@{
|
|
static const char *messages[] = @{
|
|
"some very meaningful message",
|
|
"and another one"
|
|
@};
|
|
const char *string;
|
|
@dots{}
|
|
string
|
|
= index > 1 ? "a default message" : messages[index];
|
|
|
|
fputs (string);
|
|
@dots{}
|
|
@}
|
|
@end group
|
|
@end example
|
|
|
|
While it is no problem to mark the string @code{"a default message"} it
|
|
is not possible to mark the string initializers for @code{messages}.
|
|
What is to be done? We have to fulfill two tasks. First we have to mark the
|
|
strings so that the @code{xgettext} program (@pxref{xgettext Invocation})
|
|
can find them, and second we have to translate the string at runtime
|
|
before printing them.
|
|
|
|
The first task can be fulfilled by creating a new keyword, which names a
|
|
no-op. For the second we have to mark all access points to a string
|
|
from the array. So one solution can look like this:
|
|
|
|
@example
|
|
@group
|
|
#define gettext_noop(String) (String)
|
|
|
|
@{
|
|
static const char *messages[] = @{
|
|
gettext_noop ("some very meaningful message"),
|
|
gettext_noop ("and another one")
|
|
@};
|
|
const char *string;
|
|
@dots{}
|
|
string
|
|
= index > 1 ? gettext ("a default message") : gettext (messages[index]);
|
|
|
|
fputs (string);
|
|
@dots{}
|
|
@}
|
|
@end group
|
|
@end example
|
|
|
|
Please convince yourself that the string which is written by
|
|
@code{fputs} is translated in any case. How to get @code{xgettext} know
|
|
the additional keyword @code{gettext_noop} is explained in @ref{xgettext
|
|
Invocation}.
|
|
|
|
The above is of course not the only solution. You could also come along
|
|
with the following one:
|
|
|
|
@example
|
|
@group
|
|
#define gettext_noop(String) (String)
|
|
|
|
@{
|
|
static const char *messages[] = @{
|
|
gettext_noop ("some very meaningful message",
|
|
gettext_noop ("and another one")
|
|
@};
|
|
const char *string;
|
|
@dots{}
|
|
string
|
|
= index > 1 ? gettext_noop ("a default message") : messages[index];
|
|
|
|
fputs (gettext (string));
|
|
@dots{}
|
|
@}
|
|
@end group
|
|
@end example
|
|
|
|
But this has some drawbacks. First the programmer has to take care that
|
|
he uses @code{gettext_noop} for the string @code{"a default message"}.
|
|
A use of @code{gettext} could have in rare cases unpredictable results.
|
|
The second reason is found in the internals of the GNU @code{gettext}
|
|
Library which will make this solution less efficient.
|
|
|
|
One advantage is that you need not make control flow analysis to make
|
|
sure the output is really translated in any case. But this analysis is
|
|
generally not very difficult. If it should be in any situation you can
|
|
use this second method in this situation.
|
|
|
|
@node Initial, Updating, Sources, Top
|
|
@chapter Making the Initial PO File
|
|
|
|
@c FIXME: Rewrite.
|
|
|
|
@menu
|
|
* xgettext Invocation:: Invoking the @code{xgettext} Program
|
|
* C Sources Context:: C Sources Context
|
|
* Compendium:: Using Translation Compendiums
|
|
@end menu
|
|
|
|
@node xgettext Invocation, C Sources Context, Initial, Initial
|
|
@section Invoking the @code{xgettext} Program
|
|
|
|
@c FIXME: Rewrite.
|
|
|
|
@example
|
|
xgettext [@var{option}] @var{inputfile} @dots{}
|
|
@end example
|
|
|
|
@table @samp
|
|
@item -a
|
|
@itemx --extract-all
|
|
Extract all strings.
|
|
|
|
@item -c [@var{tag}]
|
|
@itemx --add-comments[=@var{tag}]
|
|
Place comment block with @var{tag} (or those preceding keyword lines)
|
|
in output file.
|
|
|
|
@item -C
|
|
@itemx --c++
|
|
Recognize C++ style comments.
|
|
|
|
@itemx --debug
|
|
Use the flags @kbd{c-format} and @kbd{possible-c-format} to show who was
|
|
responsible for marking a message as a format string. The later form is
|
|
used if the @code{xgettext} program decided, the format form is used if
|
|
the programmer prescribed it.
|
|
|
|
By default only the @kbd{c-format} form is used. The translator should
|
|
not have to care about these details.
|
|
|
|
@item -d @var{name}
|
|
@itemx --default-domain=@var{name}
|
|
Use @file{@var{name}.po} for output (instead of @file{messages.po}).
|
|
|
|
The special domain name @file{-} or @file{/dev/stdout} means to write
|
|
the output to @file{stdout}.
|
|
|
|
@item -D @var{directory}
|
|
@itemx --directory=@var{directory}
|
|
Change to @var{directory} before beginning to search and scan source
|
|
files. The resulting @file{.po} file will be written relative to the
|
|
original directory, though.
|
|
|
|
@item -f @var{file}
|
|
@itemx --files-from=@var{file}
|
|
Read the names of the input files from @var{file} instead of getting
|
|
them from the command line.
|
|
|
|
@itemx --force
|
|
Always write output file even if no message is defined.
|
|
|
|
@item -h
|
|
@itemx --help
|
|
Display this help and exit.
|
|
|
|
@item -I @var{list}
|
|
@itemx --input-path=@var{list}
|
|
List of directories searched for input files.
|
|
|
|
@item -j
|
|
@itemx --join-existing
|
|
Join messages with existing file.
|
|
|
|
@item -k @var{word}
|
|
@itemx --keyword[=@var{word}]
|
|
Additonal keyword to be looked for (without @var{word} means not to
|
|
use default keywords).
|
|
|
|
The default keywords, which are always looked for if not explicitly
|
|
disabled, are @code{gettext}, @code{dgettext}, @code{dcgettext} and
|
|
@code{gettext_noop}.
|
|
|
|
@item -m [@var{string}]
|
|
@itemx --msgstr-prefix[=@var{string}]
|
|
Use @var{string} or "" as prefix for msgstr entries.
|
|
|
|
@item -M [@var{string}]
|
|
@itemx --msgstr-suffix[=@var{string}]
|
|
Use @var{string} or "" as suffix for msgstr entries.
|
|
|
|
@item --no-location
|
|
Do not write @samp{#: @var{filename}:@var{line}} lines.
|
|
|
|
@item -n
|
|
@itemx --add-location
|
|
Generate @samp{#: @var{filename}:@var{line}} lines (default).
|
|
|
|
@item --omit-header
|
|
Don't write header with @samp{msgid ""} entry.
|
|
|
|
This is useful for testing purposes because it eliminates a source
|
|
of variance for generated @code{.gmo} files. We can ship some of
|
|
these files in the GNU @code{gettext} package, and the result of
|
|
regenerating them through @code{msgfmt} should yield the same values.
|
|
|
|
@item -p @var{dir}
|
|
@itemx --output-dir=@var{dir}
|
|
Output files will be placed in directory @var{dir}.
|
|
|
|
@item -s
|
|
@itemx --sort-output
|
|
Generate sorted output and remove duplicates.
|
|
|
|
@item --strict
|
|
Write out strict Uniforum conforming PO file.
|
|
|
|
@item -v
|
|
@itemx --version
|
|
Output version information and exit.
|
|
|
|
@item -x @var{file}
|
|
@itemx --exclude-file=@var{file}
|
|
Entries from @var{file} are not extracted.
|
|
|
|
@end table
|
|
|
|
Search path for supplementary PO files is:
|
|
@file{/usr/local/share/nls/src/}.
|
|
|
|
If @var{inputfile} is @samp{-}, standard input is read.
|
|
|
|
This implementation of @code{xgettext} is able to process a few awkward
|
|
cases, like strings in preprocessor macros, ANSI concatenation of
|
|
adjacent strings, and escaped end of lines for continued strings.
|
|
|
|
@node C Sources Context, Compendium, xgettext Invocation, Initial
|
|
@section C Sources Context
|
|
|
|
PO mode is particularily powerful when used with PO files
|
|
created through GNU @code{gettext} utilities, as those utilities
|
|
insert special comments in the PO files they generate.
|
|
Some of these special comments relate the PO file entry to
|
|
exactly where the untranslated string appears in the program sources.
|
|
|
|
When the translator gets to an untranslated entry, she is fairly
|
|
often faced with an original string which is not as informative as
|
|
it normally should be, being succinct, cryptic, or otherwise ambiguous.
|
|
Before chosing how to translate the string, she needs to understand
|
|
better what the string really means and how tight the translation has
|
|
to be. Most of times, when problems arise, the only way left to make
|
|
her judgment is looking at the true program sources from where this
|
|
string originated, searching for surrounding comments the programmer
|
|
might have put in there, and looking around for helping clues of
|
|
@emph{any} kind.
|
|
|
|
Surely, when looking at program sources, the translator will receive
|
|
more help if she is a fluent programmer. However, even if she is
|
|
not versed in programming and feels a little lost in C code, the
|
|
translator should not be shy at taking a look, once in a while.
|
|
It is most probable that she will still be able to find some of the
|
|
hints she needs. She will learn quickly to not feel uncomfortable
|
|
in program code, paying more attention to programmer's comments,
|
|
variable and function names (if he dared chosing them well), and
|
|
overall organization, than to programmation itself.
|
|
|
|
The following commands are meant to help the translator at getting
|
|
program source context for a PO file entry.
|
|
|
|
@table @kbd
|
|
@item s
|
|
Resume the display of a program source context, or cycle through them.
|
|
|
|
@item M-s
|
|
Display of a program source context selected by menu.
|
|
|
|
@item S
|
|
Add a directory to the search path for source files.
|
|
|
|
@item M-S
|
|
Delete a directory from the search path for source files.
|
|
|
|
@end table
|
|
|
|
The commands @kbd{s} (@code{po-cycle-reference}) and @kbd{M-s}
|
|
(@code{po-select-source-reference}) both open another window displaying
|
|
some source program file, and already positioned in such a way that
|
|
it shows an actual use of the string to be translated. By doing
|
|
so, the command gives source program context for the string. But if
|
|
the entry has no source context references, or if all references
|
|
are unresolved along the search path for program sources, then the
|
|
command diagnoses this as an error.
|
|
|
|
Even if @kbd{s} (or @kbd{M-s}) opens a new window, the cursor stays
|
|
in the PO file window. If the translator really wants to
|
|
get into the program source window, she ought to do it explicitly,
|
|
maybe by using command @kbd{O}.
|
|
|
|
When @kbd{s} is typed for the first time, or for a PO file entry which
|
|
is different of the last one used for getting source context, then the
|
|
command reacts by giving the first context available for this entry,
|
|
if any. If some context has already been recently displayed for the
|
|
current PO file entry, and the translator wandered off to do other
|
|
things, typing @kbd{s} again will merely resume, in another window,
|
|
the context last displayed. In particular, if the translator moved
|
|
the cursor away from the context in the source file, the command will
|
|
bring the cursor back to the context. By using @kbd{s} many times
|
|
in a row, with no other commands intervening, PO mode will cycle to
|
|
the next available contexts for this particular entry, getting back
|
|
to the first context once the last has been shown.
|
|
|
|
The command @kbd{M-s} behaves differently. Instead of cycling through
|
|
references, it lets the translator choose of particular reference among
|
|
many, and displays that reference. It is best used with completion,
|
|
if the translator types @kbd{TAB} immediately after @kbd{M-s}, in
|
|
response to the question, she will be offered a menu of all possible
|
|
references, as a reminder of which are the acceptable answers.
|
|
This command is useful only where there are really many contexts
|
|
available for a single string to translate.
|
|
|
|
Program source files are usually found relative to where the PO
|
|
file stands. As a special provision, when this fails, the file is
|
|
also looked for, but relative to the directory immediately above it.
|
|
Those two cases take proper care of most PO files. However, it might
|
|
happen that a PO file has been moved, or is edited in a different
|
|
place than its normal location. When this happens, the translator
|
|
should tell PO mode in which directory normally sits the genuine PO
|
|
file. Many such directories may be specified, and all together, they
|
|
constitute what is called the @dfn{search path} for program sources.
|
|
The command @kbd{S} (@code{po-consider-source-path}) is used to interactively
|
|
enter a new directory at the front of the search path, and the command
|
|
@kbd{M-S} (@code{po-ignore-source-path}) is used to select, with completion,
|
|
one of the directories she does not want anymore on the search path.
|
|
|
|
@node Compendium, , C Sources Context, Initial
|
|
@section Using Translation Compendiums
|
|
|
|
@c FIXME: Rewrite.
|
|
|
|
Compendiums are yet to be implemented.
|
|
|
|
An incoming PO mode feature will let the translator maintain a
|
|
compendium of already achieved translations. A @dfn{compendium}
|
|
is a special PO file containing a set of translations recurring in
|
|
many different packages. The translator will be given commands for
|
|
adding entries to her compendium, and later initializing untranslated
|
|
entries, or updating already translated entries, from translations
|
|
kept in the compendium. For this to work, however, the compendium
|
|
would have to be normalized. @xref{Normalizing}.
|
|
|
|
@c It is not useful that I modify the @file{lib/} routines if not done in
|
|
@c the true sources. How do you/I/they proceed for getting this job done?
|
|
@c I presume that @file{lib/} routines will all use @code{gettext} for
|
|
@c the time being.
|
|
|
|
@node Updating, Binaries, Initial, Top
|
|
@chapter Updating Existing PO Files
|
|
|
|
@c FIXME: Rewrite.
|
|
|
|
@menu
|
|
* msgmerge Invocation:: Invoking the @code{msgmerge} Program
|
|
* Translated Entries::
|
|
* Fuzzy Entries::
|
|
* Untranslated Entries:: Untranslated Entries
|
|
* Obsolete Entries:: Obsolete Entries
|
|
* Modifying Translations:: Modifying Translations
|
|
* Modifying Comments:: Modifying Comments
|
|
* Auxiliary:: Consulting Auxiliary PO Files
|
|
@end menu
|
|
|
|
@node msgmerge Invocation, Translated Entries, Updating, Updating
|
|
@section Invoking the @code{msgmerge} Program
|
|
|
|
@c FIXME: Rewrite.
|
|
|
|
@c @example
|
|
@c tupdate --help
|
|
@c tupdate --version
|
|
@c tupdate @var{new} @var{old}
|
|
@c @end example
|
|
|
|
@c File @var{new} is the last created PO file (generally by
|
|
@c @code{xgettext}). It need not contain any translations. File
|
|
@c @var{old} is the PO file including the old translations which will
|
|
@c be taken over to the newly created file as long as they still match.
|
|
|
|
@c When English messages change in the programs, this is reflected in
|
|
@c the PO file as extracted by @code{xgettext}. In large messages, that
|
|
@c can be hard to detect, and will obviously result in an incomplete
|
|
@c translation. One of the virtues of @code{tupdate} is that it detects
|
|
@c such changes, saving the previous translation into a PO file comment,
|
|
@c so marking the entry as obsolete, and giving the modified string with
|
|
@c an empty translation, that is, marking the entry as untranslated.
|
|
|
|
@node Translated Entries
|
|
@section Translated Entries
|
|
|
|
Each PO file entry for which the @code{msgstr} field has been filled with
|
|
a translation, and which is not marked as fuzzy (@pxref{Fuzzy Entries}),
|
|
is a said to be a @dfn{translated} entry. Only translated entries will
|
|
later be compiled by GNU @code{msgfmt} and become usable in programs.
|
|
Other entry types will be excluded; translation will not occur for them.
|
|
|
|
Some commands are more specifically related to translated entry processing.
|
|
|
|
@table @kbd
|
|
@item t
|
|
Find the next translated entry.
|
|
|
|
@item M-t
|
|
Find the previous translated entry.
|
|
|
|
@end table
|
|
|
|
The commands @kbd{t} (@code{po-next-translated-entry}) and @kbd{M-t}
|
|
(@code{po-previous-transted-entry}) move forwards or backwards, chasing
|
|
for an translated entry. If none is found, the search is extended and
|
|
wraps around in the PO file buffer.
|
|
|
|
Translated entries usually result from the translator having edited in
|
|
a translation for them, @ref{Modifying Translations}. However, if the
|
|
variable @code{po-auto-fuzzy-on-edit} is not @code{nil}, the entry having
|
|
received a new translation first becomes a fuzzy entry, which ought to
|
|
be later unfuzzied before becoming an official, genuine translated entry.
|
|
@xref{Fuzzy Entries}.
|
|
|
|
@node Fuzzy Entries, Untranslated Entries, Translated Entries, Updating
|
|
@section Fuzzy Entries
|
|
|
|
Each PO file entry may have a set of @dfn{attributes}, which are
|
|
qualities given an name and explicitely associated with the entry
|
|
translation, using a special system comment. One of these attributes
|
|
has the name @code{fuzzy}, and entries having this attribute are said
|
|
to have a fuzzy translation. They are called fuzzy entries, for short.
|
|
|
|
Fuzzy entries, even if they account for translated entries for
|
|
most other purposes, usually call for revision by the translator.
|
|
Those may be produced by applying the program @code{msgmerge} to
|
|
update an older translated PO files according to a new PO template
|
|
file, when this tool hypothesises that some new @code{msgid} has
|
|
been modified only slightly out of an older one, and chooses to pair
|
|
what it thinks to be the old translation for the new modified entry.
|
|
The slight alteration in the original string (the @code{msgid} string)
|
|
should often be reflected in the translated string, and this requires
|
|
the intervention of the translator. For this reason, @code{msgmerge}
|
|
might mark some entries as being fuzzy.
|
|
|
|
Also, the translator may decide herself to mark an entry as fuzzy
|
|
for her own convenience, when she wants to remember that the entry
|
|
has to be later revisited. So, some commands are more specifically
|
|
related to fuzzy entry processing.
|
|
|
|
@table @kbd
|
|
@item f
|
|
Find the next fuzzy entry.
|
|
|
|
@item M-f
|
|
Find the previous fuzzy entry.
|
|
|
|
@item TAB
|
|
Remove the fuzzy attribute of the current entry.
|
|
|
|
@end table
|
|
|
|
The commands @kbd{f} (@code{po-next-fuzzy}) and @kbd{M-f}
|
|
(@code{po-previous-fuzzy}) move forwards or backwards, chasing for
|
|
a fuzzy entry. If none is found, the search is extended and wraps
|
|
around in the PO file buffer.
|
|
|
|
The command @kbd{TAB} (@code{po-unfuzzy}) removes the fuzzy
|
|
attribute associated with an entry, usually leaving it translated.
|
|
Further, if the variable @code{po-auto-select-on-unfuzzy} has not
|
|
the @code{nil} value, the @kbd{TAB} command will automatically chase
|
|
for another interesting entry to work on. The initial value of
|
|
@code{po-auto-select-on-unfuzzy} is @code{nil}.
|
|
|
|
The initial value of @code{po-auto-fuzzy-on-edit} is @code{nil}. However,
|
|
if the variable @code{po-auto-fuzzy-on-edit} is set to @code{t}, any entry
|
|
edited through the @kbd{RET} command is marked fuzzy, as a way to ensure
|
|
some kind of double check, later. In this case, the usual paradigm is
|
|
that an entry becomes fuzzy (if not already) whenever the translator
|
|
modifies it. If she is satisfied with the translation, she then uses
|
|
@kbd{TAB} to pick another entry to work on, clearing the fuzzy attribute
|
|
on the same blow. If she is not satisfied yet, she merely uses @kbd{SPC}
|
|
to chase another entry, leaving the entry fuzzy.
|
|
|
|
The translator may also use the @kbd{DEL} command
|
|
(@code{po-fade-out-entry}) over any translated entry to mark it as being
|
|
fuzzy, when she wants to easily leave a trace she wants to later return
|
|
working at this entry.
|
|
|
|
Also, when time comes to quit working on a PO file buffer with the @kbd{q}
|
|
command, the translator is asked for confirmation, if fuzzy string
|
|
still exists.
|
|
|
|
@node Untranslated Entries, Obsolete Entries, Fuzzy Entries, Updating
|
|
@section Untranslated Entries
|
|
|
|
When @code{xgettext} originally creates a PO file, unless told
|
|
otherwise, it initializes the @code{msgid} field with the untranslated
|
|
string, and leaves the @code{msgstr} string to be empty. Such entries,
|
|
having an empty translation, are said to be @dfn{untranslated} entries.
|
|
Later, when the programmer slightly modifies some string right in
|
|
the program, this change is later reflected in the PO file
|
|
by the appearance of a new untranslated entry for the modified string.
|
|
|
|
The usual commands moving from entry to entry consider untranslated
|
|
entries on the same level as active entries. Untranslated entries
|
|
are easily recognizable by the fact they end with @w{@samp{msgstr ""}}.
|
|
|
|
The work of the translator might be (quite naively) seen as the process
|
|
of seeking after an untranslated entry, editing a translation for
|
|
it, and repeating these actions until no untranslated entries remain.
|
|
Some commands are more specifically related to untranslated entry
|
|
processing.
|
|
|
|
@table @kbd
|
|
@item u
|
|
Find the next untranslated entry.
|
|
|
|
@item M-u
|
|
Find the previous untranslated entry.
|
|
|
|
@item k
|
|
Turn the current entry into an untranslated one.
|
|
|
|
@end table
|
|
|
|
The commands @kbd{u} (@code{po-next-untranslated-entry}) and @kbd{M-u}
|
|
(@code{po-previous-untransted-entry}) move forwards or backwards,
|
|
chasing for an untranslated entry. If none is found, the search is
|
|
extended and wraps around in the PO file buffer.
|
|
|
|
An entry can be turned back into an untranslated entry by
|
|
merely emptying its translation, using the command @kbd{k}
|
|
(@code{po-kill-msgstr}). @xref{Modifying Translations}.
|
|
|
|
Also, when time comes to quit working on a PO file buffer
|
|
with the @kbd{q} command, the translator is asked for confirmation,
|
|
if some untranslated string still exists.
|
|
|
|
@node Obsolete Entries, Modifying Translations, Untranslated Entries, Updating
|
|
@section Obsolete Entries
|
|
|
|
By @dfn{obsolete} PO file entries, we mean those entries which are
|
|
commented out, usually by @code{msgmerge} when it found that the
|
|
translation is not needed anymore by the package being localized.
|
|
|
|
The usual commands moving from entry to entry consider obsolete
|
|
entries on the same level as active entries. Obsolete entries are
|
|
easily recognizable by the fact that all their lines start with
|
|
@kbd{#}, even those lines containing @code{msgid} or @code{msgstr}.
|
|
|
|
Commands exist for emptying the translation or reinitializing it
|
|
to the original untranslated string. Commands interfacing with the
|
|
kill ring may force some previously saved text into the translation.
|
|
The user may interactively edit the translation. All these commands
|
|
may apply to obsolete entries, carefully leaving the entry obsolete
|
|
after the fact.
|
|
|
|
Moreover, some commands are more specifically related to obsolete
|
|
entry processing.
|
|
|
|
@table @kbd
|
|
@item o
|
|
Find the next obsolete entry.
|
|
|
|
@item M-o
|
|
Find the previous obsolete entry.
|
|
|
|
@item DEL
|
|
Make an active entry obsolete, or zap out an obsolete entry.
|
|
|
|
@end table
|
|
|
|
The commands @kbd{o} (@code{po-next-obsolete-entry}) and @kbd{M-o}
|
|
(@code{po-previous-obsolete-entry}) move forwards or backwards,
|
|
chasing for an obsolete entry. If none is found, the search is
|
|
extended and wraps around in the PO file buffer.
|
|
|
|
PO mode does not provide ways for un-commenting an obsolete entry
|
|
and making it active, because this would reintroduce an original
|
|
untranslated string which does not correspond to any marked string
|
|
in the program sources. This goes with the philosophy of never
|
|
introducing useless @code{msgid} values.
|
|
|
|
However, it is possible to comment out an active entry, so making
|
|
it obsolete. GNU @code{gettext} utilities will later react to the
|
|
disappearance of a translation by using the untranslated string.
|
|
The command @kbd{DEL} (@code{po-fade-out-entry}) pushes the current entry
|
|
a little further towards annihilation. If the entry is active (it is a
|
|
translated entry), then it is first made fuzzy. If it is already fuzzy,
|
|
then the entry is merely commented out, with confirmation. If the entry
|
|
is already obsolete, then it is completely deleted from the PO file.
|
|
It is easy to recycle the translation so deleted into some other PO file
|
|
entry, usually one which is untranslated. @xref{Modifying Translations}.
|
|
|
|
Here is a quite interesting problem to solve for later development of
|
|
PO mode, for those nights you are not sleepy. The idea would be that
|
|
PO mode might become bright enough, one of these days, to make good
|
|
guesses at retrieving the most probable candidate, among all obsolete
|
|
entries, for initializing the translation of a newly appeared string.
|
|
I think it might be a quite hard problem to do this algorithmically, as
|
|
we have to develop good and efficient measures of string similarity.
|
|
Right now, PO mode completely lets the decision to the translator,
|
|
when the time comes to find the adequate obsolete translation, it
|
|
merely tries to provide handy tools for helping her to do so.
|
|
|
|
@node Modifying Translations, Modifying Comments, Obsolete Entries, Updating
|
|
@section Modifying Translations
|
|
|
|
PO mode prevents direct edition of the PO file, by the usual
|
|
means Emacs give for altering a buffer's contents. By doing so,
|
|
it pretends helping the translator to avoid little clerical errors
|
|
about the overall file format, or the proper quoting of strings,
|
|
as those errors would be easily made. Other kinds of errors are
|
|
still possible, but some may be caught and diagnosed by the batch
|
|
validation process, which the translator may always trigger by the
|
|
@kbd{V} command. For all other errors, the translator has to rely on
|
|
her own judgment, and also on the linguistic reports submitted to her
|
|
by the users of the translated package, having the same mother tongue.
|
|
|
|
When the time comes to create a translation, correct an error diagnosed
|
|
mechanically or reported by a user, the translators have to resort to
|
|
using the following commands for modifying the translations.
|
|
|
|
@table @kbd
|
|
|
|
@item RET
|
|
Interactively edit the translation.
|
|
|
|
@item LFD
|
|
Reinitialize the translation with the original, untranslated string.
|
|
|
|
@item k
|
|
Save the translation on the kill ring, and delete it.
|
|
|
|
@item w
|
|
Save the translation on the kill ring, without deleting it.
|
|
|
|
@item y
|
|
Replace the translation, taking the new from the kill ring.
|
|
|
|
@end table
|
|
|
|
The command @kbd{RET} (@code{po-edit-msgstr}) opens a new Emacs window
|
|
containing a copy of the translation taken from the current PO file entry,
|
|
all ready for edition, fully modifiable and with the complete extent of
|
|
GNU Emacs modifying commands. The string is presented to the translator
|
|
expunged of all quoting marks, and she will modify the @emph{unquoted}
|
|
string in this window to heart's content. Once done, the regular Emacs
|
|
command @kbd{M-C-c} (@code{exit-recursive-edit}) may be used to return the
|
|
edited translation into the PO file, replacing the original translation.
|
|
The keys @w{@kbd{C-c C-c}} are bound so they have the same effect as
|
|
@kbd{M-C-c}.
|
|
|
|
If the translator becomes unsatisfied with her translation to the extent
|
|
she prefers keeping the translation which was existent prior to the
|
|
@kbd{RET} command, she may use the standard Emacs command @kbd{C-]}
|
|
(@code{abort-recursive-edit}) to merely get rid of edition, while
|
|
preserving the original translation. The keys @w{@kbd{C-c C-k}} are
|
|
bound so they have the same effect as @kbd{C-]}. Another way would
|
|
be for her to exit normally with @w{@kbd{C-c C-c}}, then type @code{U}
|
|
once for undoing the whole effect of last edition.
|
|
|
|
Functions found on @code{po-subedit-mode-hook}, if any, are executed after
|
|
the string has been inserted in the edit buffer and before recursive edit
|
|
is entered.
|
|
|
|
While editing her translation, the translator should pay attention to
|
|
not inserting unwanted @kbd{@key{RET}} (carriage returns) characters at
|
|
the end of the translated string if those are not meant to be there,
|
|
or to removing such characters when they are required. Since these
|
|
characters are not visible in the editing buffer, they are easily
|
|
introduced by mistake. To help her, @kbd{@key{RET}} automatically puts
|
|
the character @kbd{<} at the end of the string being edited, but this
|
|
@kbd{<} is not really part of the string. On exiting the editing
|
|
window with @w{@kbd{C-c C-c}}, PO mode automatically removes such
|
|
@kbd{<} and all whitespace added after it. If the translator adds
|
|
characters after the terminating @kbd{<}, it looses its delimiting
|
|
property and integrally becomes part of the string. If she removes
|
|
the delimiting @kbd{<}, then the edited string is taken @emph{as
|
|
is}, with all trailing newlines, even if invisible. Also, if the
|
|
translated string ought to end itself with a genuine @kbd{<}, then the
|
|
delimiting @kbd{<} may not be removed; so the string should appear,
|
|
in the editing window, as ending with two @kbd{<} in a row.
|
|
|
|
When a translation (or a comment) is being edited, the translator
|
|
may move the cursor back into the PO file buffer and freely
|
|
move to other entries, browsing at will. The edited entry will
|
|
be recovered as soon as the edit ceases, because it is this entry
|
|
only which is being modified. If, with an edition still opened, the
|
|
translator wanders in the PO file buffer, she cannot modify
|
|
any other entry. If she tries to, PO mode will react by suggesting
|
|
that she abort the current edit, or else, by inviting her to finish
|
|
the current edit prior to any other modification.
|
|
|
|
The command @kbd{LFD} (@code{po-msgid-to-msgstr}) initializes, or
|
|
reinitializes the translation with the original string. This command
|
|
is normally used when the translator wants to redo a fresh translation
|
|
of the original string, disregarding any previous work.
|
|
|
|
It is possible to arrange so, whenever editing an untranslated
|
|
entry, the @kbd{LFD} command be automatically executed. If you set
|
|
@code{po-auto-edit-with-msgid} to @code{t}, the translation gets
|
|
initialised with the original string, in case none exist already.
|
|
The default value for @code{po-auto-edit-with-msgid} is @code{nil}.
|
|
|
|
In fact, whether it is best to start a translation with an empty
|
|
string, or rather with a copy of the original string, is a matter of
|
|
taste or habit. Sometimes, the source language and the
|
|
target language are so different that is simply best to start writing
|
|
on an empty page. At other times, the source and target languages
|
|
are so close that it would be a waste to retype a number of words
|
|
already being written in the original string. A translator may also
|
|
like having the original string right under her eyes, as she will
|
|
progressively overwrite the original text with the translation, even
|
|
if this requires some extra editing work to get rid of the original.
|
|
|
|
The command @kbd{k} (@code{po-kill-msgstr}) merely empties the
|
|
translation string, so turning the entry into an untranslated
|
|
one. But while doing so, its previous contents is put apart in
|
|
a special place, known as the kill ring. The command @kbd{w}
|
|
(@code{po-kill-ring-save-msgstr}) has also the effect of taking a
|
|
copy of the translation onto the kill ring, but it otherwise leaves
|
|
the entry alone, and does @emph{not} remove the translation from the
|
|
entry. Both commands use exactly the Emacs kill ring, which is shared
|
|
between buffers, and which is well known already to GNU Emacs lovers.
|
|
|
|
The translator may use @kbd{k} or @kbd{w} many times in the course
|
|
of her work, as the kill ring may hold several saved translations.
|
|
From the kill ring, strings may later be reinserted in various
|
|
Emacs buffers. In particular, the kill ring may be used for moving
|
|
translation strings between different entries of a single PO file
|
|
buffer, or if the translator is handling many such buffers at once,
|
|
even between PO files.
|
|
|
|
To facilitate exchanges with buffers which are not in PO mode, the
|
|
translation string put on the kill ring by the @kbd{k} command is fully
|
|
unquoted before being saved: external quotes are removed, multi-lines
|
|
strings are concatenated, and backslashed escaped sequences are turned
|
|
into their corresponding characters. In the special case of obsolete
|
|
entries, the translation is also uncommented prior to saving.
|
|
|
|
The command @kbd{y} (@code{po-yank-msgstr}) completely replaces the
|
|
translation of the current entry by a string taken from the kill ring.
|
|
Following GNU Emacs terminology, we then say that the replacement
|
|
string is @dfn{yanked} into the PO file buffer.
|
|
@xref{Yanking, , , emacs, The Emacs Editor}.
|
|
The first time @kbd{y} is used, the translation receives the value of
|
|
the most recent addition to the kill ring. If @kbd{y} is typed once
|
|
again, immediately, without intervening keystrokes, the translation
|
|
just inserted is taken away and replaced by the second most recent
|
|
addition to the kill ring. By repeating @kbd{y} many times in a row,
|
|
the translator may travel along the kill ring for saved strings,
|
|
until she finds the string she really wanted.
|
|
|
|
When a string is yanked into a PO file entry, it is fully and
|
|
automatically requoted for complying with the format PO files should
|
|
have. Further, if the entry is obsolete, PO mode then appropriately
|
|
push the inserted string inside comments. Once again, translators
|
|
should not burden themselves with quoting considerations besides, of
|
|
course, the necessity of the translated string itself respective to
|
|
the program using it.
|
|
|
|
Note that @kbd{k} or @kbd{w} are not the only commands pushing strings
|
|
on the kill ring, as almost any PO mode command replacing translation
|
|
strings (or the translator comments) automatically save the old string
|
|
on the kill ring. The main exceptions to this general rule are the
|
|
yanking commands themselves.
|
|
|
|
To better illustrate the operation of killing and yanking, let's
|
|
use an actual example, taken from a common situation. When the
|
|
programmer slightly modifies some string right in the program, his
|
|
change is later reflected in the PO file by the appearance
|
|
of a new untranslated entry for the modified string, and the fact
|
|
that the entry translating the original or unmodified string becomes
|
|
obsolete. In many cases, the translator might spare herself some work
|
|
by retrieving the unmodified translation from the obsolete entry,
|
|
then initializing the untranslated entry @code{msgstr} field with
|
|
this retrieved translation. Once this done, the obsolete entry is
|
|
not wanted anymore, and may be safely deleted.
|
|
|
|
When the translator finds an untranslated entry and suspects that a
|
|
slight variant of the translation exists, she immediately uses @kbd{m}
|
|
to mark the current entry location, then starts chasing obsolete
|
|
entries with @kbd{o}, hoping to find some translation corresponding
|
|
to the unmodified string. Once found, she uses the @kbd{DEL} command
|
|
for deleting the obsolete entry, knowing that @kbd{DEL} also @emph{kills}
|
|
the translation, that is, pushes the translation on the kill ring.
|
|
Then, @kbd{r} returns to the initial untranslated entry, @kbd{y}
|
|
then @emph{yanks} the saved translation right into the @code{msgstr}
|
|
field. The translator is then free to use @kbd{@key{RET}} for fine
|
|
tuning the translation contents, and maybe to later use @kbd{u},
|
|
then @kbd{m} again, for going on with the next untranslated string.
|
|
|
|
When some sequence of keys has to be typed over and over again, the
|
|
translator may find it useful to become better acquainted with the GNU
|
|
Emacs capability of learning these sequences and playing them back under
|
|
request. @xref{Keyboard Macros, , , emacs, The Emacs Editor}.
|
|
|
|
@node Modifying Comments, Auxiliary, Modifying Translations, Updating
|
|
@section Modifying Comments
|
|
|
|
Any translation work done seriously will raise many linguistic
|
|
difficulties, for which decisions have to be made, and the choices
|
|
further documented. These documents may be saved within the
|
|
PO file in form of translator comments, which the translator
|
|
is free to create, delete, or modify at will. These comments may
|
|
be useful to herself when she returns to this PO file after a while.
|
|
|
|
Comments not having whitespace after the initial @samp{#}, for example,
|
|
those beginning with @samp{#.} or @samp{#:}, are @emph{not} translator
|
|
comments, they are exclusively created by other @code{gettext} tools.
|
|
So, the commands below will never alter such system added comments,
|
|
they are not meant for the translator to modify. @xref{PO Files}.
|
|
|
|
The following commands are somewhat similar to those modifying translations,
|
|
so the general indications given for those apply here. @xref{Modifying
|
|
Translations}.
|
|
|
|
@table @kbd
|
|
|
|
@item #
|
|
Interactively edit the translator comments.
|
|
|
|
@item K
|
|
Save the translator comments on the kill ring, and delete it.
|
|
|
|
@item W
|
|
Save the translator comments on the kill ring, without deleting it.
|
|
|
|
@item Y
|
|
Replace the translator comments, taking the new from the kill ring.
|
|
|
|
@end table
|
|
|
|
These commands parallel PO mode commands for modifying the translation
|
|
strings, and behave much the same way as they do, except that they handle
|
|
this part of PO file comments meant for translator usage, rather
|
|
than the translation strings. So, if the descriptions given below are
|
|
slightly succinct, it is because the full details have already been given.
|
|
@xref{Modifying Translations}.
|
|
|
|
The command @kbd{#} (@code{po-edit-comment}) opens a new Emacs
|
|
window containing a copy of the translator comments on the current
|
|
PO file entry. If there are no such comments, PO mode
|
|
understands that the translator wants to add a comment to the entry,
|
|
and she is presented with an empty screen. Comment marks (@kbd{#}) and
|
|
the space following them are automatically removed before edition,
|
|
and reinstated after. For translator comments pertaining to obsolete
|
|
entries, the uncommenting and recommenting operations are done twice.
|
|
Once in the editing window, the keys @w{@kbd{C-c C-c}} allow the
|
|
translator to tell she is finished with editing the comment.
|
|
|
|
Functions found on @code{po-subedit-mode-hook}, if any, are executed after
|
|
the string has been inserted in the edit buffer and before recursive edit
|
|
is entered.
|
|
|
|
The command @kbd{K} (@code{po-kill-comment}) get rid of all
|
|
translator comments, while saving those comments on the kill ring.
|
|
The command @kbd{W} (@code{po-kill-ring-save-comment}) takes
|
|
a copy of the translator comments on the kill ring, but leaves
|
|
them undisturbed in the current entry. The command @kbd{Y}
|
|
(@code{po-yank-comment}) completely replaces the translator comments
|
|
by a string taken at the front of the kill ring. When this command
|
|
is immediately repeated, the comments just inserted are withdrawn,
|
|
and replaced by other strings taken along the kill ring.
|
|
|
|
On the kill ring, all strings have the same nature. There is no
|
|
distinction between @emph{translation} strings and @emph{translator
|
|
comments} strings. So, for example, let's presume the translator
|
|
has just finished editing a translation, and wants to create a new
|
|
translator comment to document why the previous translation was
|
|
not good, just to remember what was the problem. Foreseeing that she
|
|
will do that in her documentation, the translator may want to quote
|
|
the previous translation in her translator comments. To do so, she
|
|
may initialize the translator comments with the previous translation,
|
|
still at the head of the kill ring. Because editing already pushed the
|
|
previous translation on the kill ring, she merely has to type @kbd{M-w}
|
|
prior to @kbd{#}, and the previous translation will be right there,
|
|
all ready for being introduced by some explanatory text.
|
|
|
|
On the other hand, presume there are some translator comments already
|
|
and that the translator wants to add to those comments, instead
|
|
of wholly replacing them. Then, she should edit the comment right
|
|
away with @kbd{#}. Once inside the editing window, she can use the
|
|
regular GNU Emacs commands @kbd{C-y} (@code{yank}) and @kbd{M-y}
|
|
(@code{yank-pop}) to get the previous translation where she likes.
|
|
|
|
@node Auxiliary, , Modifying Comments, Updating
|
|
@section Consulting Auxiliary PO Files
|
|
|
|
PO mode is able to help the knowledgeable translator, being fluent in
|
|
many languages, at taking advantage of translations already achieved
|
|
in other languages she just happens to know. It provides these other
|
|
language translations as additional context for her own work. Moreover,
|
|
it has features to ease the production of translations for many languages
|
|
at once, for translators preferring to work in this way.
|
|
|
|
An @dfn{auxiliary} PO file is an existing PO file meant for the same
|
|
package the translator is working on, but targeted to a different mother
|
|
tongue language. Commands exist for declaring and handling auxiliary
|
|
PO files, and also for showing contexts for the entry under work.
|
|
|
|
Here are the auxiliary file commands available in PO mode.
|
|
|
|
@table @kbd
|
|
@item a
|
|
Seek auxiliary files for another translation for the same entry.
|
|
|
|
@item M-a
|
|
Switch to a particular auxiliary file.
|
|
|
|
@item A
|
|
Declare this PO file as an auxiliary file.
|
|
|
|
@item M-A
|
|
Remove this PO file from the list of auxiliary files.
|
|
|
|
@end table
|
|
|
|
Command @kbd{A} (@code{po-consider-as-auxiliary}) adds the current
|
|
PO file to the list of auxiliary files, while command @kbd{M-A}
|
|
(@code{po-ignore-as-auxiliary} just removes it.
|
|
|
|
The command @kbd{a} (@code{po-cycle-auxiliary}) seeks all auxiliary PO
|
|
files, round-robin, searching for a translated entry in some other language
|
|
having an @code{msgid} field identical as the one for the current entry.
|
|
The found PO file, if any, takes the place of the current PO file in
|
|
the display (its window gets on top). Before doing so, the current PO
|
|
file is also made into an auxiliary file, if not already. So, @kbd{a}
|
|
in this newly displayed PO file will seek another PO file, and so on,
|
|
so repeating @kbd{a} will eventually yield back the original PO file.
|
|
|
|
The command @kbd{M-a} (@code{po-select-auxiliary}) asks the translator
|
|
for her choice of a particular auxiliary file, with completion, and
|
|
then switches to that selected PO file. The command also checks if
|
|
the selected file has an @code{msgid} field identical as the one for
|
|
the current entry, and if yes, this entry becomes current. Otherwise,
|
|
the cursor of the selected file is left undisturbed.
|
|
|
|
For all this to work fully, auxiliary PO files will have to be normalized,
|
|
in that way that @code{msgid} fields should be written @emph{exactly}
|
|
the same way. It is possible to write @code{msgid} fields in various
|
|
ways for representing the same string, different writing would break the
|
|
proper behaviour of the auxiliary file commands of PO mode. This is not
|
|
expected to be much a problem in practice, as most existing PO files have
|
|
their @code{msgid} entries written by the same GNU @code{gettext} tools.
|
|
|
|
However, PO files initially created by PO mode itself, while marking
|
|
strings in source files, are normalised differently. So are PO
|
|
files resulting of the the @samp{M-x normalize} command. Until these
|
|
discrepancies between PO mode and other GNU @code{gettext} tools get
|
|
fully resolved, the translator should stay aware of normalisation issues.
|
|
|
|
@node Binaries, Users, Updating, Top
|
|
@chapter Producing Binary MO Files
|
|
|
|
@c FIXME: Rewrite.
|
|
|
|
@menu
|
|
* msgfmt Invocation:: Invoking the @code{msgfmt} Program
|
|
* MO Files:: The Format of GNU MO Files
|
|
@end menu
|
|
|
|
@node msgfmt Invocation, MO Files, Binaries, Binaries
|
|
@section Invoking the @code{msgfmt} Program
|
|
|
|
@c FIXME: Rewrite.
|
|
|
|
@example
|
|
Usage: msgfmt [@var{option}] @var{filename}.po @dots{}
|
|
@end example
|
|
|
|
@table @samp
|
|
@item -a @var{number}
|
|
@itemx --alignment=@var{number}
|
|
Align strings to @var{number} bytes (default: 1).
|
|
@c Currently the README mentions that this constant could be changed by
|
|
@c the installer by changing the value in config.h. Should this go away?
|
|
|
|
@item -h
|
|
@itemx --help
|
|
Display this help and exit.
|
|
|
|
@item --no-hash
|
|
Binary file will not include the hash table.
|
|
|
|
@item -o @var{file}
|
|
@itemx --output-file=@var{file}
|
|
Specify output file name as @var{file}.
|
|
|
|
@itemx --strict
|
|
Direct the program to work strictly following the Uniforum/Sun
|
|
implementation. Currently this only affects the naming of the output
|
|
file. If this option is not given the name of the output file is the
|
|
same as the domain name. If the strict Uniforum mode is enable the
|
|
suffix @file{.mo} is added to the file name if it is not already
|
|
present.
|
|
|
|
We find this behaviour of Sun's implementation rather silly and so by
|
|
default this mode is @emph{not} selected.
|
|
|
|
@item -v
|
|
@itemx --verbose
|
|
Detect and diagnose input file anomalies which might represent
|
|
translation errors. The @code{msgid} and @code{msgstr} strings are
|
|
studied and compared. It is considered abnormal that one string
|
|
starts or ends with a newline while the other does not.
|
|
|
|
Also, if the string represents a format sring used in a
|
|
@code{printf}-like function both strings should have the same number of
|
|
@samp{%} format specifiers, with matching types. If the flag
|
|
@code{c-format} or @code{possible-c-format} appears in the special
|
|
comment @key{#,} for this entry a check is performed. For example, the
|
|
check will diagnose using @samp{%.*s} against @samp{%s}, or @samp{%d}
|
|
against @samp{%s}, or @samp{%d} against @samp{%x}. It can even handle
|
|
positional parameters.
|
|
|
|
Normally the @code{xgettext} program automatically decides whether a
|
|
string is a format string or not. This algorithm is not perfect,
|
|
though. It might regard a string as a format string though it is not
|
|
used in a @code{printf}-like function and so @code{msgfmt} might report
|
|
errors where there are none. Or the other way round: a string is not
|
|
regarded as a format string but it is used in a @code{printf}-like
|
|
function.
|
|
|
|
So solve this problem the programmer can dictate the decision to the
|
|
@code{xgettext} program (@pxref{c-format}). The translator should not
|
|
consider removing the flag from the @key{#,} line. This "fix" would be
|
|
reversed again as soon as @code{msgmerge} is called the next time.
|
|
|
|
@item -V
|
|
@itemx --version
|
|
Output version information and exit.
|
|
|
|
@end table
|
|
|
|
If input file is @samp{-}, standard input is read. If output file
|
|
is @samp{-}, output is written to standard output.
|
|
|
|
@node MO Files, , msgfmt Invocation, Binaries
|
|
@section The Format of GNU MO Files
|
|
|
|
The format of the generated MO files is best described by a picture,
|
|
which appears below.
|
|
|
|
The first two words serve the identification of the file. The magic
|
|
number will always signal GNU MO files. The number is stored in the
|
|
byte order of the generating machine, so the magic number really is
|
|
two numbers: @code{0x950412de} and @code{0xde120495}. The second
|
|
word describes the current revision of the file format. For now the
|
|
revision is 0. This might change in future versions, and ensures
|
|
that the readers of MO files can distinguish new formats from old
|
|
ones, so that both can be handled correctly. The version is kept
|
|
separate from the magic number, instead of using different magic
|
|
numbers for different formats, mainly because @file{/etc/magic} is
|
|
not updated often. It might be better to have magic separated from
|
|
internal format version identification.
|
|
|
|
Follow a number of pointers to later tables in the file, allowing
|
|
for the extension of the prefix part of MO files without having to
|
|
recompile programs reading them. This might become useful for later
|
|
inserting a few flag bits, indication about the charset used, new
|
|
tables, or other things.
|
|
|
|
Then, at offset @var{O} and offset @var{T} in the picture, two tables
|
|
of string descriptors can be found. In both tables, each string
|
|
descriptor uses two 32 bits integers, one for the string length,
|
|
another for the offset of the string in the MO file, counting in bytes
|
|
from the start of the file. The first table contains descriptors
|
|
for the original strings, and is sorted so the original strings
|
|
are in increasing lexicographical order. The second table contains
|
|
descriptors for the translated strings, and is parallel to the first
|
|
table: to find the corresponding translation one has to access the
|
|
array slot in the second array with the same index.
|
|
|
|
Having the original strings sorted enables the use of simple binary
|
|
search, for when the MO file does not contain an hashing table, or
|
|
for when it is not practical to use the hashing table provided in
|
|
the MO file. This also has another advantage, as the empty string
|
|
in a PO file GNU @code{gettext} is usually @emph{translated} into
|
|
some system information attached to that particular MO file, and the
|
|
empty string necessarily becomes the first in both the original and
|
|
translated tables, making the system information very easy to find.
|
|
|
|
The size @var{S} of the hash table can be zero. In this case, the
|
|
hash table itself is not contained in the MO file. Some people might
|
|
prefer this because a precomputed hashing table takes disk space, and
|
|
does not win @emph{that} much speed. The hash table contains indices
|
|
to the sorted array of strings in the MO file. Conflict resolution is
|
|
done by double hashing. The precise hashing algorithm used is fairly
|
|
dependent of GNU @code{gettext} code, and is not documented here.
|
|
|
|
As for the strings themselves, they follow the hash file, and each
|
|
is terminated with a @key{NUL}, and this @key{NUL} is not counted in
|
|
the length which appears in the string descriptor. The @code{msgfmt}
|
|
program has an option selecting the alignment for MO file strings.
|
|
With this option, each string is separately aligned so it starts at
|
|
an offset which is a multiple of the alignment value. On some RISC
|
|
machines, a correct alignment will speed things up.
|
|
|
|
Nothing prevents a MO file from having embedded @key{NUL}s in strings.
|
|
However, the program interface currently used already presumes
|
|
that strings are @key{NUL} terminated, so embedded @key{NUL}s are
|
|
somewhat useless. But MO file format is general enough so other
|
|
interfaces would be later possible, if for example, we ever want to
|
|
implement wide characters right in MO files, where @key{NUL} bytes may
|
|
accidently appear.
|
|
|
|
This particular issue has been strongly debated in the GNU
|
|
@code{gettext} development forum, and it is expectable that MO file
|
|
format will evolve or change over time. It is even possible that many
|
|
formats may later be supported concurrently. But surely, we have to
|
|
start somewhere, and the MO file format described here is a good start.
|
|
Nothing is cast in concrete, and the format may later evolve fairly
|
|
easily, so we should feel comfortable with the current approach.
|
|
|
|
@example
|
|
@group
|
|
byte
|
|
+------------------------------------------+
|
|
0 | magic number = 0x950412de |
|
|
| |
|
|
4 | file format revision = 0 |
|
|
| |
|
|
8 | number of strings | == N
|
|
| |
|
|
12 | offset of table with original strings | == O
|
|
| |
|
|
16 | offset of table with translation strings | == T
|
|
| |
|
|
20 | size of hashing table | == S
|
|
| |
|
|
24 | offset of hashing table | == H
|
|
| |
|
|
. .
|
|
. (possibly more entries later) .
|
|
. .
|
|
| |
|
|
O | length & offset 0th string ----------------.
|
|
O + 8 | length & offset 1st string ------------------.
|
|
... ... | |
|
|
O + ((N-1)*8)| length & offset (N-1)th string | | |
|
|
| | | |
|
|
T | length & offset 0th translation ---------------.
|
|
T + 8 | length & offset 1st translation -----------------.
|
|
... ... | | | |
|
|
T + ((N-1)*8)| length & offset (N-1)th translation | | | | |
|
|
| | | | | |
|
|
H | start hash table | | | | |
|
|
... ... | | | |
|
|
H + S * 4 | end hash table | | | | |
|
|
| | | | | |
|
|
| NUL terminated 0th string <----------------' | | |
|
|
| | | | |
|
|
| NUL terminated 1st string <------------------' | |
|
|
| | | |
|
|
... ... | |
|
|
| | | |
|
|
| NUL terminated 0th translation <---------------' |
|
|
| | |
|
|
| NUL terminated 1st translation <-----------------'
|
|
| |
|
|
... ...
|
|
| |
|
|
+------------------------------------------+
|
|
@end group
|
|
@end example
|
|
|
|
@node Users, Programmers, Binaries, Top
|
|
@chapter The User's View
|
|
|
|
When GNU @code{gettext} will truly have reached is goal, average users
|
|
should feel some kind of astonished pleasure, seeing the effect of
|
|
that strange kind of magic that just makes their own native language
|
|
appear everywhere on their screens. As for naive users, they would
|
|
ideally have no special pleasure about it, merely taking their own
|
|
language for @emph{granted}, and becoming rather unhappy otherwise.
|
|
|
|
So, let's try to describe here how we would like the magic to operate,
|
|
as we want the users' view to be the simplest, among all ways one
|
|
could look at GNU @code{gettext}. All other software engineers:
|
|
programmers, translators, maintainers, should work together in such a
|
|
way that the magic becomes possible. This is a long and progressive
|
|
undertaking, and information is available about the progress of the
|
|
Translation Project.
|
|
|
|
When a package is distributed, there are two kind of users:
|
|
@dfn{installers} who fetch the distribution, unpack it, configure
|
|
it, compile it and install it for themselves or others to use; and
|
|
@dfn{end users} that call programs of the package, once these have
|
|
been installed at their site. GNU @code{gettext} is offering magic
|
|
for both installers and end users.
|
|
|
|
@menu
|
|
* Matrix:: The Current @file{ABOUT-NLS} Matrix
|
|
* Installers:: Magic for Installers
|
|
* End Users:: Magic for End Users
|
|
@end menu
|
|
|
|
@node Matrix, Installers, Users, Users
|
|
@section The Current @file{ABOUT-NLS} Matrix
|
|
|
|
Languages are not equally supported in all packages using GNU
|
|
@code{gettext}. To know if some package uses GNU @code{gettext}, one
|
|
may check the distribution for the @file{ABOUT-NLS} information file, for
|
|
some @file{@var{ll}.po} files, often kept together into some @file{po/}
|
|
directory, or for an @file{intl/} directory. Internationalized packages
|
|
have usually many @file{@var{ll}.po} files, where @var{ll} represents
|
|
the language. @ref{End Users} for a complete description of the format
|
|
for @var{ll}.
|
|
|
|
More generally, a matrix is available for showing the current state
|
|
of the Translation Project, listing which packages are prepared for
|
|
multi-lingual messages, and which languages is supported by each.
|
|
Because this information changes often, this matrix is not kept within
|
|
this GNU @code{gettext} manual. This information is often found in
|
|
file @file{ABOUT-NLS} from various distributions, but is also as old as
|
|
the distribution itself. A recent copy of this @file{ABOUT-NLS} file,
|
|
containing up-to-date information, should generally be found on the
|
|
Translation Project sites, and also on most GNU archive sites.
|
|
|
|
@node Installers, End Users, Matrix, Users
|
|
@section Magic for Installers
|
|
|
|
By default, packages fully using GNU @code{gettext}, internally,
|
|
are installed in such a way that they to allow translation of
|
|
messages. At @emph{configuration} time, those packages should
|
|
automatically detect whether the underlying host system provides usable
|
|
@code{catgets} or @code{gettext} functions. If neither is present,
|
|
the GNU @code{gettext} library should be automatically prepared
|
|
and used. Installers may use special options at configuration
|
|
time for changing this behavior. The command @samp{./configure
|
|
--with-included-gettext} bypasses system @code{catgets} or @code{gettext} to
|
|
use GNU @code{gettext} instead, while @samp{./configure --disable-nls}
|
|
produces program totally unable to translate messages.
|
|
|
|
Internationalized packages have usually many @file{@var{ll}.po}
|
|
files. Unless
|
|
translations are disabled, all those available are installed together
|
|
with the package. However, the environment variable @code{LINGUAS}
|
|
may be set, prior to configuration, to limit the installed set.
|
|
@code{LINGUAS} should then contain a space separated list of two-letter
|
|
codes, stating which languages are allowed.
|
|
|
|
@node End Users, , Installers, Users
|
|
@section Magic for End Users
|
|
|
|
We consider here those packages using GNU @code{gettext} internally,
|
|
and for which the installers did not disable translation at
|
|
@emph{configure} time. Then, users only have to set the @code{LANG}
|
|
environment variable to the appropriate @samp{@var{ll}} prior to
|
|
using the programs in the package. @xref{Matrix}. For example,
|
|
let's presume a German site. At the shell prompt, users merely have to
|
|
execute @w{@samp{setenv LANG de}} (in @code{csh}) or @w{@samp{export
|
|
LANG; LANG=de}} (in @code{sh}). They could even do this from their
|
|
@file{.login} or @file{.profile} file.
|
|
|
|
@node Programmers, Translators, Users, Top
|
|
@chapter The Programmer's View
|
|
|
|
@c FIXME: Reorganize whole chapter.
|
|
|
|
One aim of the current message catalog implementation provided by
|
|
GNU @code{gettext} was to use the systems message catalog handling, if the
|
|
installer wishes to do so. So we perhaps should first take a look at
|
|
the solutions we know about. The people in the POSIX committee does not
|
|
manage to agree on one of the semi-official standards which we'll
|
|
describe below. In fact they couldn't agree on anything, so nothing
|
|
decide only to include an example of an interface. The major Unix vendors
|
|
are split in the usage of the two most important specifications: X/Opens
|
|
catgets vs. Uniforums gettext interface. We'll describe them both and
|
|
later explain our solution of this dilemma.
|
|
|
|
@menu
|
|
* catgets:: About @code{catgets}
|
|
* gettext:: About @code{gettext}
|
|
* Comparison:: Comparing the two interfaces
|
|
* Using libintl.a:: Using libintl.a in own programs
|
|
* gettext grok:: Being a @code{gettext} grok
|
|
* Temp Programmers:: Temporary Notes for the Programmers Chapter
|
|
@end menu
|
|
|
|
@node catgets, gettext, Programmers, Programmers
|
|
@section About @code{catgets}
|
|
|
|
The @code{catgets} implementation is defined in the X/Open Portability
|
|
Guide, Volume 3, XSI Supplementary Definitions, Chapter 5. But the
|
|
process of creating this standard seemed to be too slow for some of
|
|
the Unix vendors so they created their implementations on preliminary
|
|
versions of the standard. Of course this leads again to problems while
|
|
writing platform independent programs: even the usage of @code{catgets}
|
|
does not guarantee a unique interface.
|
|
|
|
Another, personal comment on this that only a bunch of committee members
|
|
could have made this interface. They never really tried to program
|
|
using this interface. It is a fast, memory-saving implementation, an
|
|
user can happily live with it. But programmers hate it (at least me and
|
|
some others do@dots{})
|
|
|
|
But we must not forget one point: after all the trouble with transfering
|
|
the rights on Unix(tm) they at last came to X/Open, the very same who
|
|
published this specifications. This leads me to making the prediction
|
|
that this interface will be in future Unix standards (e.g. Spec1170) and
|
|
therefore part of all Unix implementation (implementations, which are
|
|
@emph{allowed} to wear this name).
|
|
|
|
@menu
|
|
* Interface to catgets:: The interface
|
|
* Problems with catgets:: Problems with the @code{catgets} interface?!
|
|
@end menu
|
|
|
|
@node Interface to catgets, Problems with catgets, catgets, catgets
|
|
@subsection The Interface
|
|
|
|
The interface to the @code{catgets} implementation consists of three
|
|
functions which correspond to those used in file access: @code{catopen}
|
|
to open the catalog for using, @code{catgets} for accessing the message
|
|
tables, and @code{catclose} for closing after work is done. Prototypes
|
|
for the functions and the needed definitions are in the
|
|
@code{<nl_types.h>} header file.
|
|
|
|
@code{catopen} is used like in this:
|
|
|
|
@example
|
|
nl_catd catd = catopen ("catalog_name", 0);
|
|
@end example
|
|
|
|
The function takes as the argument the name of the catalog. This usual
|
|
refers to the name of the program or the package. The second parameter
|
|
is not further specified in the standard. I don't even know whether it
|
|
is implemented consistently among various systems. So the common advice
|
|
is to use @code{0} as the value. The return value is a handle to the
|
|
message catalog, equivalent to handles to file returned by @code{open}.
|
|
|
|
This handle is of course used in the @code{catgets} function which can
|
|
be used like this:
|
|
|
|
@example
|
|
char *translation = catgets (catd, set_no, msg_id, "original string");
|
|
@end example
|
|
|
|
The first parameter is this catalog descriptor. The second parameter
|
|
specifies the set of messages in this catalog, in which the message
|
|
described by @code{msg_id} is obtained. @code{catgets} therefore uses a
|
|
three-stage addressing:
|
|
|
|
@display
|
|
catalog name @result{} set number @result{} message ID @result{} translation
|
|
@end display
|
|
|
|
@c Anybody else loving Haskell??? :-) -- Uli
|
|
|
|
The fourth argument is not used to address the translation. It is given
|
|
as a default value in case when one of the addressing stages fail. One
|
|
important thing to remember is that although the return type of catgets
|
|
is @code{char *} the resulting string @emph{must not} be changed. It
|
|
should better @code{const char *}, but the standard is published in
|
|
1988, one year before ANSI C.
|
|
|
|
@noindent
|
|
The last of these function functions is used and behaves as expected:
|
|
|
|
@example
|
|
catclose (catd);
|
|
@end example
|
|
|
|
After this no @code{catgets} call using the descriptor is legal anymore.
|
|
|
|
@node Problems with catgets, , Interface to catgets, catgets
|
|
@subsection Problems with the @code{catgets} Interface?!
|
|
|
|
Now that this descriptions seemed to be really easy where are the
|
|
problem we speak of. In fact the interface could be used in a
|
|
reasonable way, but constructing the message catalogs is a pain. The
|
|
reason for this lies in the third argument of @code{catgets}: the unique
|
|
message ID. This has to be a numeric value for all messages in a single
|
|
set. Perhaps you could imagine the problems keeping such list while
|
|
changing the source code. Add a new message here, remove one there. Of
|
|
course there have been developed a lot of tools helping to organize this
|
|
chaos but one as the other fails in one aspect or the other. We don't
|
|
want to say that the other approach has no problems but they are far
|
|
more easily to manage.
|
|
|
|
@node gettext, Comparison, catgets, Programmers
|
|
@section About @code{gettext}
|
|
|
|
The definition of the @code{gettext} interface comes from a Uniforum
|
|
proposal and it is followed by at least one major Unix vendor
|
|
(Sun) in its last developments. It is not specified in any official
|
|
standard, though.
|
|
|
|
The main points about this solution is that it does not follow the
|
|
method of normal file handling (open-use-close) and that it does not
|
|
burden the programmer so many task, especially the unique key handling.
|
|
Of course here is also a unique key needed, but this key is the
|
|
message itself (how long or short it is). @xref{Comparison} for a
|
|
more detailed comparison of the two methods.
|
|
|
|
The following section contains a rather detailed description of the
|
|
interface. We make it that detailed because this is the interface
|
|
we chose for the GNU @code{gettext} Library. Programmers interested
|
|
in using this library will be interested in this description.
|
|
|
|
@menu
|
|
* Interface to gettext:: The interface
|
|
* Ambiguities:: Solving ambiguities
|
|
* Locating Catalogs:: Locating message catalog files
|
|
* Optimized gettext:: Optimization of the *gettext functions
|
|
@end menu
|
|
|
|
@node Interface to gettext, Ambiguities, gettext, gettext
|
|
@subsection The Interface
|
|
|
|
The minimal functionality an interface must have is a) to select a
|
|
domain the strings are coming from (a single domain for all programs is
|
|
not reasonable because its construction and maintenance is difficult,
|
|
perhaps impossible) and b) to access a string in a selected domain.
|
|
|
|
This is principally the description of the @code{gettext} interface. It
|
|
has an global domain which unqualified usages reference. Of course this
|
|
domain is selectable by the user.
|
|
|
|
@example
|
|
char *textdomain (const char *domain_name);
|
|
@end example
|
|
|
|
This provides the possibility to change or query the current status of
|
|
the current global domain of the @code{LC_MESSAGE} category. The
|
|
argument is a null-terminated string, whose characters must be legal in
|
|
the use in filenames. If the @var{domain_name} argument is @code{NULL},
|
|
the function return the current value. If no value has been set
|
|
before, the name of the default domain is returned: @emph{messages}.
|
|
Please note that although the return value of @code{textdomain} is of
|
|
type @code{char *} no changing is allowed. It is also important to know
|
|
that no checks of the availability are made. If the name is not
|
|
available you will see this by the fact that no translations are provided.
|
|
|
|
@noindent
|
|
To use a domain set by @code{textdomain} the function
|
|
|
|
@example
|
|
char *gettext (const char *msgid);
|
|
@end example
|
|
|
|
is to be used. This is the simplest reasonable form one can imagine.
|
|
The translation of the string @var{msgid} is returned if it is available
|
|
in the current domain. If not available the argument itself is
|
|
returned. If the argument is @code{NULL} the result is undefined.
|
|
|
|
One things which should come into mind is that no explicit dependency to
|
|
the used domain is given. The current value of the domain for the
|
|
@code{LC_MESSAGES} locale is used. If this changes between two
|
|
executions of the same @code{gettext} call in the program, both calls
|
|
reference a different message catalog.
|
|
|
|
For the easiest case, which is normally used in internationalized
|
|
packages, once at the beginning of execution a call to @code{textdomain}
|
|
is issued, setting the domain to a unique name, normally the package
|
|
name. In the following code all strings which have to be translated are
|
|
filtered through the gettext function. That's all, the package speaks
|
|
your language.
|
|
|
|
@node Ambiguities, Locating Catalogs, Interface to gettext, gettext
|
|
@subsection Solving Ambiguities
|
|
|
|
While this single name domain work good for most applications there
|
|
might be the need to get translations from more than one domain. Of
|
|
course one could switch between different domains with calls to
|
|
@code{textdomain}, but this is really not convenient nor is it fast. A
|
|
possible situation could be one case discussing while this writing: all
|
|
error messages of functions in the set of common used functions should
|
|
go into a separate domain @code{error}. By this mean we would only need
|
|
to translate them once.
|
|
|
|
@noindent
|
|
For this reasons there are two more functions to retrieve strings:
|
|
|
|
@example
|
|
char *dgettext (const char *domain_name, const char *msgid);
|
|
char *dcgettext (const char *domain_name, const char *msgid,
|
|
int category);
|
|
@end example
|
|
|
|
Both take an additional argument at the first place, which corresponds
|
|
to the argument of @code{textdomain}. The third argument of
|
|
@code{dcgettext} allows to use another locale but @code{LC_MESSAGES}.
|
|
But I really don't know where this can be useful. If the
|
|
@var{domain_name} is @code{NULL} or @var{category} has an value beside
|
|
the known ones, the result is undefined. It should also be noted that
|
|
this function is not part of the second known implementation of this
|
|
function family, the one found in Solaris.
|
|
|
|
A second ambiguity can arise by the fact, that perhaps more than one
|
|
domain has the same name. This can be solved by specifying where the
|
|
needed message catalog files can be found.
|
|
|
|
@example
|
|
char *bindtextdomain (const char *domain_name,
|
|
const char *dir_name);
|
|
@end example
|
|
|
|
Calling this function binds the given domain to a file in the specified
|
|
directory (how this file is determined follows below). Especially a
|
|
file in the systems default place is not favored against the specified
|
|
file anymore (as it would be by solely using @code{textdomain}). A
|
|
@code{NULL} pointer for the @var{dir_name} parameter returns the binding
|
|
associated with @var{domain_name}. If @var{domain_name} itself is
|
|
@code{NULL} nothing happens and a @code{NULL} pointer is returned. Here
|
|
again as for all the other functions is true that none of the return
|
|
value must be changed!
|
|
|
|
It is important to remember that relative path names for the
|
|
@var{dir_name} parameter can be trouble. Since the path is always
|
|
computed relative to the current directory different results will be
|
|
achieved when the program executes a @code{chdir} command. Relative
|
|
paths should always be avoided to avoid dependencies and
|
|
unreliabilities.
|
|
|
|
@node Locating Catalogs, Optimized gettext, Ambiguities, gettext
|
|
@subsection Locating Message Catalog Files
|
|
|
|
Because many different languages for many different packages have to be
|
|
stored we need some way to add these information to file message catalog
|
|
files. The way usually used in Unix environments is have this encoding
|
|
in the file name. This is also done here. The directory name given in
|
|
@code{bindtextdomain}s second argument (or the default directory),
|
|
followed by the value and name of the locale and the domain name are
|
|
concatenated:
|
|
|
|
@example
|
|
@var{dir_name}/@var{locale}/LC_@var{category}/@var{domain_name}.mo
|
|
@end example
|
|
|
|
The default value for @var{dir_name} is system specific. For the GNU
|
|
library, and for packages adhering to its conventions, it's:
|
|
@example
|
|
/usr/local/share/locale
|
|
@end example
|
|
|
|
@noindent
|
|
@var{locale} is the value of the locale whose name is this
|
|
@code{LC_@var{category}}. For @code{gettext} and @code{dgettext} this
|
|
locale is always @code{LC_MESSAGES}. @code{dcgettext} specifies the
|
|
locale by the third argument.@footnote{Some
|
|
system, eg Ultrix, don't have @code{LC_MESSAGES}. Here we use a more or
|
|
less arbitrary value for it.} @footnote{When the system does not support
|
|
@code{setlocale} its behavior in setting the locale values is simulated
|
|
by looking at the environment variables.}
|
|
|
|
@node Optimized gettext, , Locating Catalogs, gettext
|
|
@subsection Optimization of the *gettext functions
|
|
|
|
At this point of the discussion we should talk about an advantage of the
|
|
GNU @code{gettext} implementation. Some readers might have pointed out
|
|
that an internationalized program might have a poor performance if some
|
|
string has to be translated in an inner loop. While this is unavoidable
|
|
when the string varies from one run of the loop to the other it is
|
|
simply a waste of time when the string is always the same. Take the
|
|
following example:
|
|
|
|
@example
|
|
@group
|
|
@{
|
|
while (@dots{})
|
|
@{
|
|
puts (gettext ("Hello world"));
|
|
@}
|
|
@}
|
|
@end group
|
|
@end example
|
|
|
|
@noindent
|
|
When the locale selection does not change between two runs the resulting
|
|
string is always the same. One way to use this is:
|
|
|
|
@example
|
|
@group
|
|
@{
|
|
str = gettext ("Hello world");
|
|
while (@dots{})
|
|
@{
|
|
puts (str);
|
|
@}
|
|
@}
|
|
@end group
|
|
@end example
|
|
|
|
@noindent
|
|
But this solution is not usable in all situation (e.g. when the locale
|
|
selection changes) nor is it good readable.
|
|
|
|
The GNU C compiler, version 2.7 and above, provide another solution for
|
|
this. To describe this we show here some lines of the
|
|
@file{intl/libgettext.h} file. For an explanation of the expression
|
|
command block see @ref{Statement Exprs, , Statements and Declarations in
|
|
Expressions, gcc, The GNU CC Manual}.
|
|
|
|
@example
|
|
@group
|
|
# if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ >= 7
|
|
extern int _nl_msg_cat_cntr;
|
|
# define dcgettext(domainname, msgid, category) \
|
|
(__extension__ \
|
|
(@{ \
|
|
char *result; \
|
|
if (__builtin_constant_p (msgid)) \
|
|
@{ \
|
|
static char *__translation__; \
|
|
static int __catalog_counter__; \
|
|
if (! __translation__ \
|
|
|| __catalog_counter__ != _nl_msg_cat_cntr) \
|
|
@{ \
|
|
__translation__ = \
|
|
dcgettext__ ((domainname), (msgid), (category)); \
|
|
__catalog_counter__ = _nl_msg_cat_cntr; \
|
|
@} \
|
|
result = __translation__; \
|
|
@} \
|
|
else \
|
|
result = dcgettext__ ((domainname), (msgid), (category)); \
|
|
result; \
|
|
@}))
|
|
# endif
|
|
@end group
|
|
@end example
|
|
|
|
The interesting thing here is the @code{__builtin_constant_p} predicate.
|
|
This is evaluated at compile time and so optimization can take place
|
|
immediately. Here two cases are distinguished: the argument to
|
|
@code{gettext} is not a constant value in which case simply the function
|
|
@code{dcgettext__} is called, the real implementation of the
|
|
@code{dcgettext} function.
|
|
|
|
If the string argument @emph{is} constant we can reuse the once gained
|
|
translation when the locale selection has not changed. This is exactly
|
|
what is done here. The @code{_nl_msg_cat_cntr} variable is defined in
|
|
the @file{loadmsgcat.c} which is available in @file{libintl.a} and is
|
|
changed whenever a new message catalog is loaded.
|
|
|
|
@node Comparison, Using libintl.a, gettext, Programmers
|
|
@section Comparing the Two Interfaces
|
|
|
|
@c FIXME: arguments to catgets vs. gettext
|
|
@c Partly done 950718 -- drepper
|
|
|
|
The following discussion is perhaps a little bit colored. As said
|
|
above we implemented GNU @code{gettext} following the Uniforum
|
|
proposal and this surely has its reasons. But it should show how we
|
|
came to this decision.
|
|
|
|
First we take a look at the developing process. When we write an
|
|
application using NLS provided by @code{gettext} we proceed as always.
|
|
Only when we come to a string which might be seen by the users and thus
|
|
has to be translated we use @code{gettext("@dots{}")} instead of
|
|
@code{"@dots{}"}. At the beginning of each source file (or in a central
|
|
header file) we define
|
|
|
|
@example
|
|
#define gettext(String) (String)
|
|
@end example
|
|
|
|
Even this definition can be avoided when the system supports the
|
|
@code{gettext} function in its C library. When we compile this code the
|
|
result is the same as if no NLS code is used. When you take a look at
|
|
the GNU @code{gettext} code you will see that we use @code{_("@dots{}")}
|
|
instead of @code{gettext("@dots{}")}. This reduces the number of
|
|
additional characters per translatable string to @emph{3} (in words:
|
|
three).
|
|
|
|
When now a production version of the program is needed we simply replace
|
|
the definition
|
|
|
|
@example
|
|
#define _(String) (String)
|
|
@end example
|
|
|
|
@noindent
|
|
by
|
|
|
|
@example
|
|
#include <libintl.h>
|
|
#define _(String) gettext (String)
|
|
@end example
|
|
|
|
@noindent
|
|
Additionally we run the program @file{xgettext} on all source code file
|
|
which contain translatable strings and that's it: we have a running
|
|
program which does not depend on translations to be available, but which
|
|
can use any that becomes available.
|
|
|
|
The same procedure can be done for the @code{gettext_noop} invocations
|
|
(@pxref{Special cases}). First you can define @code{gettext_noop} to a
|
|
no-op macro and later use the definition from @file{libintl.h}. Because
|
|
this name is not used in Suns implementation of @file{libintl.h},
|
|
you should consider the following code for your project:
|
|
|
|
@example
|
|
#ifdef gettext_noop
|
|
# define N_(String) gettext_noop (String)
|
|
#else
|
|
# define N_(String) (String)
|
|
#endif
|
|
@end example
|
|
|
|
@code{N_} is a short form similar to @code{_}. The @file{Makefile} in
|
|
the @file{po/} directory of GNU gettext knows by default both of the
|
|
mentioned short forms so you are invited to follow this proposal for
|
|
your own ease.
|
|
|
|
Now to @code{catgets}. The main problem is the work for the
|
|
programmer. Every time he comes to a translatable string he has to
|
|
define a number (or a symbolic constant) which has also be defined in
|
|
the message catalog file. He also has to take care for duplicate
|
|
entries, duplicate message IDs etc. If he wants to have the same
|
|
quality in the message catalog as the GNU @code{gettext} program
|
|
provides he also has to put the descriptive comments for the strings and
|
|
the location in all source code files in the message catalog. This is
|
|
nearly a Mission: Impossible.
|
|
|
|
But there are also some points people might call advantages speaking for
|
|
@code{catgets}. If you have a single word in a string and this string
|
|
is used in different contexts it is likely that in one or the other
|
|
language the word has different translations. Example:
|
|
|
|
@example
|
|
printf ("%s: %d", gettext ("number"), number_of_errors)
|
|
|
|
printf ("you should see %d %s", number_count,
|
|
number_count == 1 ? gettext ("number") : gettext ("numbers"))
|
|
@end example
|
|
|
|
Here we have to translate two times the string @code{"number"}. Even
|
|
if you do not speak a language beside English it might be possible to
|
|
recognize that the two words have a different meaning. In German the
|
|
first appearance has to be translated to @code{"Anzahl"} and the second
|
|
to @code{"Zahl"}.
|
|
|
|
Now you can say that this example is really esoteric. And you are
|
|
right! This is exactly how we felt about this problem and decide that
|
|
it does not weight that much. The solution for the above problem could
|
|
be very easy:
|
|
|
|
@example
|
|
printf ("%s %d", gettext ("number:"), number_of_errors)
|
|
|
|
printf (number_count == 1 ? gettext ("you should see %d number")
|
|
: gettext ("you should see %d numbers"),
|
|
number_count)
|
|
@end example
|
|
|
|
We believe that we can solve all conflicts with this method. If it is
|
|
difficult one can also consider changing one of the conflicting string a
|
|
little bit. But it is not impossible to overcome.
|
|
|
|
@c Should this be here?
|
|
Translator note: It is perhaps appropriate here to tell those English
|
|
speaking programmers that the plural form of a noun cannot be formed by
|
|
appending a single `s'. Most other languages use different methods.
|
|
Even the above form is not general enough to cope with all languages.
|
|
Rafal Maszkowski <rzm@@mat.uni.torun.pl> reports:
|
|
|
|
@quotation
|
|
In Polish we use e.g. plik (file) this way:
|
|
@example
|
|
1 plik
|
|
2,3,4 pliki
|
|
5-21 pliko'w
|
|
22-24 pliki
|
|
25-31 pliko'w
|
|
@end example
|
|
and so on (o' means 8859-2 oacute which should be rather okreska,
|
|
similar to aogonek).
|
|
@end quotation
|
|
|
|
A workable approach might be to consider methods like the one used for
|
|
@code{LC_TIME} in the POSIX.2 standard. The value of the
|
|
@code{alt_digits} field can be up to 100 strings which represent the
|
|
numbers 1 to 100. Using this in a situation of an internationalized
|
|
program means that an array of translatable strings should be indexed by
|
|
the number which should represent. A small example:
|
|
|
|
@example
|
|
@group
|
|
void
|
|
print_month_info (int month)
|
|
@{
|
|
const char *month_pos[12] =
|
|
@{ N_("first"), N_("second"), N_("third"), N_("fourth"),
|
|
N_("fifth"), N_("sixth"), N_("seventh"), N_("eighth"),
|
|
N_("ninth"), N_("tenth"), N_("eleventh"), N_("twelfth") @};
|
|
printf (_("%s is the %s month\n"), nl_langinfo (MON_1 + month),
|
|
_(month_pos[month]));
|
|
@}
|
|
@end group
|
|
@end example
|
|
|
|
@noindent
|
|
It should be obvious that this method is only reasonable for small
|
|
ranges of numbers.
|
|
|
|
@c catgets allows same original entry to have different translations
|
|
|
|
@node Using libintl.a, gettext grok, Comparison, Programmers
|
|
@section Using libintl.a in own programs
|
|
|
|
Starting with version 0.9.4 the library @code{libintl.h} should be
|
|
self-contained. I.e., you can use it in your own programs without
|
|
providing additional functions. The @file{Makefile} will put the header
|
|
and the library in directories selected using the @code{$(prefix)}.
|
|
|
|
One exception of the above is found on HP-UX systems. Here the C library
|
|
does not contain the @code{alloca} function (and the HP compiler does
|
|
not generate it inlined). But it is not intended to rewrite the whole
|
|
library just because of this dumb system. Instead include the
|
|
@code{alloca} function in all package you use the @code{libintl.a} in.
|
|
|
|
@node gettext grok, Temp Programmers, Using libintl.a, Programmers
|
|
@section Being a @code{gettext} grok
|
|
|
|
To fully exploit the functionality of the GNU @code{gettext} library it
|
|
is surely helpful to read the source code. But for those who don't want
|
|
to spend that much time in reading the (sometimes complicated) code here
|
|
is a list comments:
|
|
|
|
@itemize @bullet
|
|
@item Changing the language at runtime
|
|
|
|
For interactive programs it might be useful to offer a selection of the
|
|
used language at runtime. To understand how to do this one need to know
|
|
how the used language is determined while executing the @code{gettext}
|
|
function. The method which is presented here only works correctly
|
|
with the GNU implementation of the @code{gettext} functions. It is not
|
|
possible with underlying @code{catgets} functions or @code{gettext}
|
|
functions from the systems C library. The exception is of course the
|
|
GNU C Library which uses the GNU @code{gettext} Library for message handling.
|
|
|
|
In the function @code{dcgettext} at every call the current setting of
|
|
the highest priority environment variable is determined and used.
|
|
Highest priority means here the following list with decreasing
|
|
priority:
|
|
|
|
@enumerate
|
|
@item @code{LANGUAGE}
|
|
@item @code{LC_ALL}
|
|
@item @code{LC_xxx}, according to selected locale
|
|
@item @code{LANG}
|
|
@end enumerate
|
|
|
|
Afterwards the path is constructed using the found value and the
|
|
translation file is loaded if available.
|
|
|
|
What is now when the value for, say, @code{LANGUAGE} changes. According
|
|
to the process explained above the new value of this variable is found
|
|
as soon as the @code{dcgettext} function is called. But this also means
|
|
the (perhaps) different message catalog file is loaded. In other
|
|
words: the used language is changed.
|
|
|
|
But there is one little hook. The code for gcc-2.7.0 and up provides
|
|
some optimization. This optimization normally prevents the calling of
|
|
the @code{dcgettext} function as long as no new catalog is loaded. But
|
|
if @code{dcgettext} is not called the program also cannot find the
|
|
@code{LANGUAGE} variable be changed (@pxref{Optimized gettext}). A
|
|
solution for this is very easy. Include the following code in the
|
|
language switching function.
|
|
|
|
@example
|
|
/* Change language. */
|
|
setenv ("LANGUAGE", "fr", 1);
|
|
|
|
/* Make change known. */
|
|
@{
|
|
extern int _nl_msg_cat_cntr;
|
|
++_nl_msg_cat_cntr;
|
|
@}
|
|
@end example
|
|
|
|
The variable @code{_nl_msg_cat_cntr} is defined in @file{loadmsgcat.c}.
|
|
The programmer will find himself in need for a construct like this only
|
|
when developing programs which do run longer and provide the user to
|
|
select the language at runtime. Non-interactive programs (like all
|
|
these little Unix tools) should never need this.
|
|
|
|
@end itemize
|
|
|
|
@node Temp Programmers, , gettext grok, Programmers
|
|
@section Temporary Notes for the Programmers Chapter
|
|
|
|
@menu
|
|
* Temp Implementations:: Temporary - Two Possible Implementations
|
|
* Temp catgets:: Temporary - About @code{catgets}
|
|
* Temp WSI:: Temporary - Why a single implementation
|
|
* Temp Notes:: Temporary - Notes
|
|
@end menu
|
|
|
|
@node Temp Implementations, Temp catgets, Temp Programmers, Temp Programmers
|
|
@subsection Temporary - Two Possible Implementations
|
|
|
|
There are two competing methods for language independent messages:
|
|
the X/Open @code{catgets} method, and the Uniforum @code{gettext}
|
|
method. The @code{catgets} method indexes messages by integers; the
|
|
@code{gettext} method indexes them by their English translations.
|
|
The @code{catgets} method has been around longer and is supported
|
|
by more vendors. The @code{gettext} method is supported by Sun,
|
|
and it has been heard that the COSE multi-vendor initiative is
|
|
supporting it. Neither method is a POSIX standard; the POSIX.1
|
|
committee had a lot of disagreement in this area.
|
|
|
|
Neither one is in the POSIX standard. There was much disagreement
|
|
in the POSIX.1 committee about using the @code{gettext} routines
|
|
vs. @code{catgets} (XPG). In the end the committee couldn't
|
|
agree on anything, so no messaging system was included as part
|
|
of the standard. I believe the informative annex of the standard
|
|
includes the XPG3 messaging interfaces, ``@dots{}as an example of
|
|
a messaging system that has been implemented@dots{}''
|
|
|
|
They were very careful not to say anywhere that you should use one
|
|
set of interfaces over the other. For more on this topic please
|
|
see the Programming for Internationalization FAQ.
|
|
|
|
@node Temp catgets, Temp WSI, Temp Implementations, Temp Programmers
|
|
@subsection Temporary - About @code{catgets}
|
|
|
|
There have been a few discussions of late on the use of
|
|
@code{catgets} as a base. I think it important to present both
|
|
sides of the argument and hence am opting to play devil's advocate
|
|
for a little bit.
|
|
|
|
I'll not deny the fact that @code{catgets} could have been designed
|
|
a lot better. It currently has quite a number of limitations and
|
|
these have already been pointed out.
|
|
|
|
However there is a great deal to be said for consistency and
|
|
standardization. A common recurring problem when writing Unix
|
|
software is the myriad portability problems across Unix platforms.
|
|
It seems as if every Unix vendor had a look at the operating system
|
|
and found parts they could improve upon. Undoubtedly, these
|
|
modifications are probably innovative and solve real problems.
|
|
However, software developers have a hard time keeping up with all
|
|
these changes across so many platforms.
|
|
|
|
And this has prompted the Unix vendors to begin to standardize their
|
|
systems. Hence the impetus for Spec1170. Every major Unix vendor
|
|
has committed to supporting this standard and every Unix software
|
|
developer waits with glee the day they can write software to this
|
|
standard and simply recompile (without having to use autoconf)
|
|
across different platforms.
|
|
|
|
As I understand it, Spec1170 is roughly based upon version 4 of the
|
|
X/Open Portability Guidelines (XPG4). Because @code{catgets} and
|
|
friends are defined in XPG4, I'm led to believe that @code{catgets}
|
|
is a part of Spec1170 and hence will become a standardized component
|
|
of all Unix systems.
|
|
|
|
@node Temp WSI, Temp Notes, Temp catgets, Temp Programmers
|
|
@subsection Temporary - Why a single implementation
|
|
|
|
Now it seems kind of wasteful to me to have two different systems
|
|
installed for accessing message catalogs. If we do want to remedy
|
|
@code{catgets} deficiencies why don't we try to expand @code{catgets}
|
|
(in a compatible manner) rather than implement an entirely new system.
|
|
Otherwise, we'll end up with two message catalog access systems installed
|
|
with an operating system - one set of routines for packages using GNU
|
|
@code{gettext} for their internationalization, and another set of routines
|
|
(catgets) for all other software. Bloated?
|
|
|
|
Supposing another catalog access system is implemented. Which do
|
|
we recommend? At least for Linux, we need to attract as many
|
|
software developers as possible. Hence we need to make it as easy
|
|
for them to port their software as possible. Which means supporting
|
|
@code{catgets}. We will be implementing the @code{glocale} code
|
|
within our @code{libc}, but does this mean we also have to incorporate
|
|
another message catalog access scheme within our @code{libc} as well?
|
|
And what about people who are going to be using the @code{glocale}
|
|
+ non-@code{catgets} routines. When they port their software to
|
|
other platforms, they're now going to have to include the front-end
|
|
(@code{glocale}) code plus the back-end code (the non-@code{catgets}
|
|
access routines) with their software instead of just including the
|
|
@code{glocale} code with their software.
|
|
|
|
Message catalog support is however only the tip of the iceberg.
|
|
What about the data for the other locale categories. They also have
|
|
a number of deficiencies. Are we going to abandon them as well and
|
|
develop another duplicate set of routines (should @code{glocale}
|
|
expand beyond message catalog support)?
|
|
|
|
Like many parts of Unix that can be improved upon, we're stuck with balancing
|
|
compatibility with the past with useful improvements and innovations for
|
|
the future.
|
|
|
|
@c @node Temp DLS, Temp Notes, Temp WSI, Temp Programmers
|
|
@c @subsection Temporary - Double layer solution
|
|
|
|
@c GNU locale implements a @code{gettext}-style interface on top of a
|
|
@c @code{catgets}-style interface.
|
|
|
|
@c This is not needless complexity. It is absolutely vital, because
|
|
@c it enables @code{gettext} to run on top of @code{catgets}, which
|
|
@c enables Linux International to recommend users use it @emph{today}.
|
|
|
|
@c Rewriting @code{gettext} so that it could use @emph{either}
|
|
@c @code{catgets} @emph{or} some simpler mechanism would not break
|
|
@c anything, but would not reduce complexity either. It might be
|
|
@c worth doing, but it isn't urgent.
|
|
|
|
@c In general, simplicity is not enough of a reason to rewrite a
|
|
@c program that works. Simplicity is just one desirable thing.
|
|
@c It is not overridingly important.
|
|
|
|
@node Temp Notes, , Temp WSI, Temp Programmers
|
|
@subsection Temporary - Notes
|
|
|
|
X/Open agreed very late on the standard form so that many
|
|
implementations differ from the final form. Both of my system (old
|
|
Linux catgets and Ultrix-4) have a strange variation.
|
|
|
|
OK. After incorporating the last changes I have to spend some time on
|
|
making the GNU/Linux @code{libc} @code{gettext} functions. So in future
|
|
Solaris is not the only system having @code{gettext}.
|
|
|
|
@node Translators, Maintainers, Programmers, Top
|
|
@chapter The Translator's View
|
|
|
|
@c FIXME: Reorganize whole chapter.
|
|
|
|
@menu
|
|
* Trans Intro 0:: Introduction 0
|
|
* Trans Intro 1:: Introduction 1
|
|
* Discussions:: Discussions
|
|
* Organization:: Organization
|
|
* Information Flow:: Information Flow
|
|
@end menu
|
|
|
|
@node Trans Intro 0, Trans Intro 1, Translators, Translators
|
|
@section Introduction 0
|
|
|
|
GNU is going international! The Translation Project is a way
|
|
to get maintainers, translators and users all together, so GNU will
|
|
gradually become able to speak many native languages.
|
|
|
|
The GNU @code{gettext} tool set contains @emph{everything} maintainers
|
|
need for internationalizing their packages for messages. It also
|
|
contains quite useful tools for helping translators at localizing
|
|
messages to their native language, once a package has already been
|
|
internationalized.
|
|
|
|
To achieve the Translation Project, we need many interested
|
|
people who like their own language and write it well, and who are also
|
|
able to synergize with other translators speaking the same language.
|
|
If you'd like to volunteer to @emph{work} at translating messages,
|
|
please send mail to your translating team.
|
|
|
|
Each team has its own mailing list, courtesy of Linux
|
|
International. You may reach your translating team at the address
|
|
@file{@var{ll}@@li.org}, replacing @var{ll} by the two-letter @w{ISO 639}
|
|
code for your language. Language codes are @emph{not} the same as
|
|
country codes given in @w{ISO 3166}. The following translating teams
|
|
exist:
|
|
|
|
@quotation
|
|
Chinese @code{zh}, Czech @code{cs}, Danish @code{da}, Dutch @code{nl},
|
|
Esperanto @code{eo}, Finnish @code{fi}, French @code{fr}, Irish
|
|
@code{ga}, German @code{de}, Greek @code{el}, Italian @code{it},
|
|
Japanese @code{ja}, Indonesian @code{in}, Norwegian @code{no}, Polish
|
|
@code{pl}, Portuguese @code{pt}, Russian @code{ru}, Spanish @code{es},
|
|
Swedish @code{sv} and Turkish @code{tr}.
|
|
@end quotation
|
|
|
|
@noindent
|
|
For example, you may reach the Chinese translating team by writing to
|
|
@file{zh@@li.org}. When you become a member of the translating team
|
|
for your own language, you may subscribe to its list. For example,
|
|
Swedish people can send a message to @w{@file{sv-request@@li.org}},
|
|
having this message body:
|
|
|
|
@example
|
|
subscribe
|
|
@end example
|
|
|
|
Keep in mind that team members should be interested in @emph{working}
|
|
at translations, or at solving translational difficulties, rather than
|
|
merely lurking around. If your team does not exist yet and you want to
|
|
start one, please write to @w{@file{gnu-translation@@prep.ai.mit.edu}};
|
|
you will then reach the GNU coordinator for all translator teams.
|
|
|
|
A handful of GNU packages have already been adapted and provided
|
|
with message translations for several languages. Translation
|
|
teams have begun to organize, using these packages as a starting
|
|
point. But there are many more packages and many languages for
|
|
which we have no volunteer translators. If you would like to
|
|
volunteer to work at translating messages, please send mail to
|
|
@file{gnu-translation@@prep.ai.mit.edu} indicating what language(s)
|
|
you can work on.
|
|
|
|
@node Trans Intro 1, Discussions, Trans Intro 0, Translators
|
|
@section Introduction 1
|
|
|
|
This is now official, GNU is going international! Here is the
|
|
announcement submitted for the January 1995 GNU Bulletin:
|
|
|
|
@quotation
|
|
A handful of GNU packages have already been adapted and provided
|
|
with message translations for several languages. Translation
|
|
teams have begun to organize, using these packages as a starting
|
|
point. But there are many more packages and many languages
|
|
for which we have no volunteer translators. If you'd like to
|
|
volunteer to work at translating messages, please send mail to
|
|
@samp{gnu-translation@@prep.ai.mit.edu} indicating what language(s)
|
|
you can work on.
|
|
@end quotation
|
|
|
|
This document should answer many questions for those who are curious
|
|
about the process or would like to contribute. Please at least skim
|
|
over it, hoping to cut down a little of the high volume of e-mail
|
|
generated by this collective effort towards GNU internationalization.
|
|
|
|
Most free programming which is widely shared is done in English, and
|
|
currently, English is used as the main communicating language between
|
|
national communities collaborating to the GNU project. This very document
|
|
is written in English. This will not change in the foreseeable future.
|
|
|
|
However, there is a strong appetite from national communities for
|
|
having more software able to write using national language and habits,
|
|
and there is an on-going effort to modify GNU software in such a way
|
|
that it becomes able to do so. The experiments driven so far raised
|
|
an enthusiastic response from pretesters, so we believe that GNU
|
|
internationalization is dedicated to succeed.
|
|
|
|
For suggestion clarifications, additions or corrections to this
|
|
document, please e-mail to @file{gnu-translation@@prep.ai.mit.edu}.
|
|
|
|
@node Discussions, Organization, Trans Intro 1, Translators
|
|
@section Discussions
|
|
|
|
Facing this internationalization effort, a few users expressed their
|
|
concerns. Some of these doubts are presented and discussed, here.
|
|
|
|
@itemize @bullet
|
|
@item Smaller groups
|
|
|
|
Some languages are not spoken by a very large number of people, so people
|
|
speaking them sometimes consider that there may not be all that much
|
|
demand such versions of free software packages. Moreover, many people
|
|
being @emph{into computers}, in some countries, generally seem to prefer
|
|
English versions of their software.
|
|
|
|
On the other end, people might enjoy their own language a lot, and be
|
|
very motivated at providing to themselves the pleasure of having their
|
|
beloved free software speaking their mother tongue. They do themselves
|
|
a personal favor, and do not pay that much attention to the number of
|
|
people beneficiating of their work.
|
|
|
|
@item Misinterpretation
|
|
|
|
Other users are shy to push forward their own language, seeing in this
|
|
some kind of misplaced propaganda. Someone thought there must be some
|
|
users of the language over the networks pestering other people with it.
|
|
|
|
But any spoken language is worth localization, because there are
|
|
people behind the language for whom the language is important and
|
|
dear to their hearts.
|
|
|
|
@item Odd translations
|
|
|
|
The biggest problem is to find the right translations so that
|
|
everybody can understand the messages. Translations are usually a
|
|
little odd. Some people get used to English, to the extent they may
|
|
find translations into their own language ``rather pushy, obnoxious
|
|
and sometimes even hilarious.'' As a French speaking man, I have
|
|
the experience of those instruction manuals for goods, so poorly
|
|
translated in French in Korea or Taiwan@dots{}
|
|
|
|
The fact is that we sometimes have to create a kind of national
|
|
computer culture, and this is not easy without the collaboration of
|
|
many people liking their mother tongue. This is why translations are
|
|
better achieved by people knowing and loving their own language, and
|
|
ready to work together at improving the results they obtain.
|
|
|
|
@item Dependencies over the GPL
|
|
|
|
Some people wonder if using GNU @code{gettext} necessarily brings their package
|
|
under the protective wing of the GNU General Public License, when they
|
|
do not want to make their program free, or want other kinds of freedom.
|
|
The simplest answer is yes.
|
|
|
|
The mere marking of localizable strings in a package, or conditional
|
|
inclusion of a few lines for initialization, is not really including
|
|
GPL'ed code. However, the localization routines themselves are under
|
|
the GPL and would bring the remainder of the package under the GPL
|
|
if they were distributed with it. So, I presume that, for those
|
|
for which this is a problem, it could be circumvented by letting to
|
|
the end installers the burden of assembling a package prepared for
|
|
localization, but not providing the localization routines themselves.
|
|
|
|
@end itemize
|
|
|
|
@node Organization, Information Flow, Discussions, Translators
|
|
@section Organization
|
|
|
|
On a larger scale, the true solution would be to organize some kind of
|
|
fairly precise set up in which volunteers could participate. I gave
|
|
some thought to this idea lately, and realize there will be some
|
|
touchy points. I thought of writing to Richard Stallman to launch
|
|
such a project, but feel it might be good to shake out the ideas
|
|
between ourselves first. Most probably that Linux International has
|
|
some experience in the field already, or would like to orchestrate
|
|
the volunteer work, maybe. Food for thought, in any case!
|
|
|
|
I guess we have to setup something early, somehow, that will help
|
|
many possible contributors of the same language to interlock and avoid
|
|
work duplication, and further be put in contact for solving together
|
|
problems particular to their tongue (in most languages, there are many
|
|
difficulties peculiar to translating technical English). My Swedish
|
|
contributor acknowledged these difficulties, and I'm well aware of
|
|
them for French.
|
|
|
|
This is surely not a technical issue, but we should manage so the
|
|
effort of locale contributors be maximally useful, despite the national
|
|
team layer interface between contributors and maintainers.
|
|
|
|
The Translation Project needs some setup for coordinating language
|
|
coordinators. Localizing evolving programs will surely
|
|
become a permanent and continuous activity in the free software community,
|
|
once well started.
|
|
The setup should be minimally completed and tested before GNU
|
|
@code{gettext} becomes an official reality. The e-mail address
|
|
@file{translation@@iro.umontreal.ca} has been setup for receiving
|
|
offers from volunteers and general e-mail on these topics. This address
|
|
reaches the Translation Project coordinator.
|
|
|
|
@menu
|
|
* Central Coordination:: Central Coordination
|
|
* National Teams:: National Teams
|
|
* Mailing Lists:: Mailing Lists
|
|
@end menu
|
|
|
|
@node Central Coordination, National Teams, Organization, Organization
|
|
@subsection Central Coordination
|
|
|
|
I also think GNU will need sooner than it thinks, that someone setup
|
|
a way to organize and coordinate these groups. Some kind of group
|
|
of groups. My opinion is that it would be good that GNU delegates
|
|
this task to a small group of collaborating volunteers, shortly.
|
|
Perhaps in @file{gnu.announce} a list of this national committee's
|
|
can be published.
|
|
|
|
My role as coordinator would simply be to refer to Ulrich any German
|
|
speaking volunteer interested to localization of free software packages, and
|
|
maybe helping national groups to initially organize, while maintaining
|
|
national registries for until national groups are ready to take over.
|
|
In fact, the coordinator should ease volunteers to get in contact with
|
|
one another for creating national teams, which should then select
|
|
one coordinator per language, or country (regionalized language).
|
|
If well done, the coordination should be useful without being an
|
|
overwhelming task, the time to put delegations in place.
|
|
|
|
@node National Teams, Mailing Lists, Central Coordination, Organization
|
|
@subsection National Teams
|
|
|
|
I suggest we look for volunteer coordinators/editors for individual
|
|
languages. These people will scan contributions of translation files
|
|
for various programs, for their own languages, and will ensure high
|
|
and uniform standards of diction.
|
|
|
|
From my current experience with other people in these days, those who
|
|
provide localizations are very enthusiastic about the process, and are
|
|
more interested in the localization process than in the program they
|
|
localize, and want to do many programs, not just one. This seems
|
|
to confirm that having a coordinator/editor for each language is a
|
|
good idea.
|
|
|
|
We need to choose someone who is good at writing clear and concise
|
|
prose in the language in question. That is hard---we can't check
|
|
it ourselves. So we need to ask a few people to judge each others'
|
|
writing and select the one who is best.
|
|
|
|
I announce my prerelease to a few dozen people, and you would not
|
|
believe all the discussions it generated already. I shudder to think
|
|
what will happen when this will be launched, for true, officially,
|
|
world wide. Who am I to arbitrate between two Czekolsovak users
|
|
contradicting each other, for example?
|
|
|
|
I assume that your German is not much better than my French so that
|
|
I would not be able to judge about these formulations. What I would
|
|
suggest is that for each language there is a group for people who
|
|
maintain the PO files and judge about changes. I suspect there will
|
|
be cultural differences between how such groups of people will behave.
|
|
Some will have relaxed ways, reach consensus easily, and have anyone
|
|
of the group relate to the maintainers, while others will fight to
|
|
death, organize heavy administrations up to national standards, and
|
|
use strict channels.
|
|
|
|
The German team is putting out a good example. Right now, they are
|
|
maybe half a dozen people revising translations of each other and
|
|
discussing the linguistic issues. I do not even have all the names.
|
|
Ulrich Drepper is taking care of coordinating the German team.
|
|
He subscribed to all my pretest lists, so I do not even have to warn
|
|
him specifically of incoming releases.
|
|
|
|
I'm sure, that is a good idea to get teams for each language working
|
|
on translations. That will make the translations better and more
|
|
consistent.
|
|
|
|
@menu
|
|
* Sub-Cultures:: Sub-Cultures
|
|
* Organizational Ideas:: Organizational Ideas
|
|
@end menu
|
|
|
|
@node Sub-Cultures, Organizational Ideas, National Teams, National Teams
|
|
@subsubsection Sub-Cultures
|
|
|
|
Taking French for example, there are a few sub-cultures around computers
|
|
which developed diverging vocabularies. Picking volunteers here and
|
|
there without addressing this problem in an organized way, soon in the
|
|
project, might produce a distasteful mix of internationalized programs,
|
|
and possibly trigger endless quarrels among those who really care.
|
|
|
|
Keeping some kind of unity in the way French localization of
|
|
internationalized programs is achieved is a difficult (and delicate) job.
|
|
Knowing the latin character of French people (:-), if we take this
|
|
the wrong way, we could end up nowhere, or spoil a lot of energies.
|
|
Maybe we should begin to address this problem seriously @emph{before}
|
|
GNU @code{gettext} become officially published. And I suspect that this
|
|
means soon!
|
|
|
|
@node Organizational Ideas, , Sub-Cultures, National Teams
|
|
@subsubsection Organizational Ideas
|
|
|
|
I expect the next big changes after the official release. Please note
|
|
that I use the German translation of the short GPL message. We need
|
|
to set a few good examples before the localization goes out for true
|
|
in the free software community. Here are a few points to discuss:
|
|
|
|
@itemize @bullet
|
|
@item
|
|
Each group should have one FTP server (at least one master).
|
|
|
|
@item
|
|
The files on the server should reflect the latest version (of
|
|
course!) and it should also contain a RCS directory with the
|
|
corresponding archives (I don't have this now).
|
|
|
|
@item
|
|
There should also be a ChangeLog file (this is more useful than the
|
|
RCS archive but can be generated automatically from the later by
|
|
Emacs).
|
|
|
|
@item
|
|
A @dfn{core group} should judge about questionable changes (for now
|
|
this group consists solely by me but I ask some others occasionally;
|
|
this also seems to work).
|
|
|
|
@end itemize
|
|
|
|
@node Mailing Lists, , National Teams, Organization
|
|
@subsection Mailing Lists
|
|
|
|
If we get any inquiries about GNU @code{gettext}, send them on to:
|
|
|
|
@example
|
|
@file{translation@@iro.umontreal.ca}
|
|
@end example
|
|
|
|
The @file{*-pretest} lists are quite useful to me, maybe the idea could
|
|
be generalized to many GNU, and non-GNU packages. But each maintainer
|
|
his/her way!
|
|
|
|
Fran@,{c}ois, we have a mechanism in place here at
|
|
@file{gnu.ai.mit.edu} to track teams, support mailing lists for
|
|
them and log members. We have a slight preference that you use it.
|
|
If this is OK with you, I can get you clued in.
|
|
|
|
Things are changing! A few years ago, when Daniel Fekete and I
|
|
asked for a mailing list for GNU localization, nested at the FSF, we
|
|
were politely invited to organize it anywhere else, and so did we.
|
|
For communicating with my pretesters, I later made a handful of
|
|
mailing lists located at iro.umontreal.ca and administrated by
|
|
@code{majordomo}. These lists have been @emph{very} dependable
|
|
so far@dots{}
|
|
|
|
I suspect that the German team will organize itself a mailing list
|
|
located in Germany, and so forth for other countries. But before they
|
|
organize for true, it could surely be useful to offer mailing lists
|
|
located at the FSF to each national team. So yes, please explain me
|
|
how I should proceed to create and handle them.
|
|
|
|
We should create temporary mailing lists, one per country, to help
|
|
people organize. Temporary, because once regrouped and structured, it
|
|
would be fair the volunteers from country bring back @emph{their} list
|
|
in there and manage it as they want. My feeling is that, in the long
|
|
run, each team should run its own list, from within their country.
|
|
There also should be some central list to which all teams could
|
|
subscribe as they see fit, as long as each team is represented in it.
|
|
|
|
@node Information Flow, , Organization, Translators
|
|
@section Information Flow
|
|
|
|
There will surely be some discussion about this messages after the
|
|
packages are finally released. If people now send you some proposals
|
|
for better messages, how do you proceed? Jim, please note that
|
|
right now, as I put forward nearly a dozen of localizable programs, I
|
|
receive both the translations and the coordination concerns about them.
|
|
|
|
If I put one of my things to pretest, Ulrich receives the announcement
|
|
and passes it on to the German team, who make last minute revisions.
|
|
Then he submits the translation files to me @emph{as the maintainer}.
|
|
For free packages I do not maintain, I would not even hear about it.
|
|
This scheme could be made to work for the whole Translation Project,
|
|
I think. For security reasons, maybe Ulrich (national coordinators,
|
|
in fact) should update central registry kept at the Translation Project
|
|
(Jim, me, or Len's recruits) once in a while.
|
|
|
|
In December/January, I was aggressively ready to internationalize
|
|
all of GNU, giving myself the duty of one small GNU package per week
|
|
or so, taking many weeks or months for bigger packages. But it does
|
|
not work this way. I first did all the things I'm responsible for.
|
|
I've nothing against some missionary work on other maintainers, but
|
|
I'm also loosing a lot of energy over it---same debates over again.
|
|
|
|
And when the first localized packages are released we'll get a lot of
|
|
responses about ugly translations :-). Surely, and we need to have
|
|
beforehand a fairly good idea about how to handle the information
|
|
flow between the national teams and the package maintainers.
|
|
|
|
Please start saving somewhere a quick history of each PO file. I know
|
|
for sure that the file format will change, allowing for comments.
|
|
It would be nice that each file has a kind of log, and references for
|
|
those who want to submit comments or gripes, or otherwise contribute.
|
|
I sent a proposal for a fast and flexible format, but it is not
|
|
receiving acceptance yet by the GNU deciders. I'll tell you when I
|
|
have more information about this.
|
|
|
|
@node Maintainers, Conclusion, Translators, Top
|
|
@chapter The Maintainer's View
|
|
|
|
The maintainer of a package has many responsibilities. One of them
|
|
is ensuring that the package will install easily on many platforms,
|
|
and that the magic we described earlier (@pxref{Users}) will work
|
|
for installers and end users.
|
|
|
|
Of course, there are many possible ways by which GNU @code{gettext}
|
|
might be integrated in a distribution, and this chapter does not cover
|
|
them in all generality. Instead, it details one possible approach which
|
|
is especially adequate for many free software distributions following GNU
|
|
standards, or even better, Gnits standards, because GNU @code{gettext}
|
|
is purposely for helping the internationalization of the whole GNU
|
|
project, and as many other good free packages as possible. So, the
|
|
maintainer's view presented here presumes that the package already has
|
|
a @file{configure.in} file and uses GNU Autoconf.
|
|
|
|
Nevertheless, GNU @code{gettext} may surely be useful for free packages
|
|
not following GNU standards and conventions, but the maintainers of such
|
|
packages might have to show imagination and initiative in organizing
|
|
their distributions so @code{gettext} work for them in all situations.
|
|
There are surely many, out there.
|
|
|
|
Even if @code{gettext} methods are now stabilizing, slight adjustments
|
|
might be needed between successive @code{gettext} versions, so you
|
|
should ideally revise this chapter in subsequent releases, looking
|
|
for changes.
|
|
|
|
@menu
|
|
* Flat and Non-Flat:: Flat or Non-Flat Directory Structures
|
|
* Prerequisites:: Prerequisite Works
|
|
* gettextize Invocation:: Invoking the @code{gettextize} Program
|
|
* Adjusting Files:: Files You Must Create or Alter
|
|
@end menu
|
|
|
|
@node Flat and Non-Flat, Prerequisites, Maintainers, Maintainers
|
|
@section Flat or Non-Flat Directory Structures
|
|
|
|
Some free software packages are distributed as @code{tar} files which unpack
|
|
in a single directory, these are said to be @dfn{flat} distributions.
|
|
Other free software packages have a one level hierarchy of subdirectories, using
|
|
for example a subdirectory named @file{doc/} for the Texinfo manual and
|
|
man pages, another called @file{lib/} for holding functions meant to
|
|
replace or complement C libraries, and a subdirectory @file{src/} for
|
|
holding the proper sources for the package. These other distributions
|
|
are said to be @dfn{non-flat}.
|
|
|
|
For now, we cannot say much about flat distributions. A flat
|
|
directory structure has the disadvantage of increasing the difficulty
|
|
of updating to a new version of GNU @code{gettext}. Also, if you have
|
|
many PO files, this could somewhat pollute your single directory.
|
|
In the GNU @code{gettext} distribution, the @file{misc/} directory
|
|
contains a shell script named @file{combine-sh}. That script may
|
|
be used for combining all the C files of the @file{intl/} directory
|
|
into a pair of C files (one @file{.c} and one @file{.h}). Those two
|
|
generated files would fit more easily in a flat directory structure,
|
|
and you will then have to add these two files to your project.
|
|
|
|
Maybe because GNU @code{gettext} itself has a non-flat structure,
|
|
we have more experience with this approach, and this is what will be
|
|
described in the remaining of this chapter. Some maintainers might
|
|
use this as an opportunity to unflatten their package structure.
|
|
Only later, once gained more experience adapting GNU @code{gettext}
|
|
to flat distributions, we might add some notes about how to proceed
|
|
in flat situations.
|
|
|
|
@node Prerequisites, gettextize Invocation, Flat and Non-Flat, Maintainers
|
|
@section Prerequisite Works
|
|
|
|
There are some works which are required for using GNU @code{gettext}
|
|
in one of your package. These works have some kind of generality
|
|
that escape the point by point descriptions used in the remainder
|
|
of this chapter. So, we describe them here.
|
|
|
|
@itemize @bullet
|
|
@item
|
|
Before attempting to use you should install some other packages first.
|
|
Ensure that recent versions of GNU @code{m4}, GNU Autoconf and GNU
|
|
@code{gettext} are already installed at your site, and if not, proceed
|
|
to do this first. If you got to install these things, beware that
|
|
GNU @code{m4} must be fully installed before GNU Autoconf is even
|
|
@emph{configured}.
|
|
|
|
To further ease the task of a package maintainer the @code{automake}
|
|
package was designed and implemented. GNU @code{gettext} now uses this
|
|
tool and the @file{Makefile}s in the @file{intl/} and @file{po/}
|
|
therefore know about all the goals necessary for using @code{automake}
|
|
and @file{libintl} in one project.
|
|
|
|
Those four packages are only needed to you, as a maintainer; the
|
|
installers of your own package and end users do not really need any of
|
|
GNU @code{m4}, GNU Autoconf, GNU @code{gettext}, or GNU @code{automake}
|
|
for successfully installing and running your package, with messages
|
|
properly translated. But this is not completely true if you provide
|
|
internationalized shell scripts within your own package: GNU
|
|
@code{gettext} shall then be installed at the user site if the end users
|
|
want to see the translation of shell script messages.
|
|
|
|
@item
|
|
Your package should use Autoconf and have a @file{configure.in} file.
|
|
If it does not, you have to learn how. The Autoconf documentation
|
|
is quite well written, it is a good idea that you print it and get
|
|
familiar with it.
|
|
|
|
@item
|
|
Your C sources should have already been modified according to
|
|
instructions given earlier in this manual. @xref{Sources}.
|
|
|
|
@item
|
|
Your @file{po/} directory should receive all PO files submitted to you
|
|
by the translator teams, each having @file{@var{ll}.po} as a name.
|
|
This is not usually easy to get translation
|
|
work done before your package gets internationalized and available!
|
|
Since the cycle has to start somewhere, the easiest for the maintainer
|
|
is to start with absolutely no PO files, and wait until various
|
|
translator teams get interested in your package, and submit PO files.
|
|
|
|
@end itemize
|
|
|
|
It is worth adding here a few words about how the maintainer should
|
|
ideally behave with PO files submissions. As a maintainer, your role is
|
|
to authentify the origin of the submission as being the representative
|
|
of the appropriate translating teams of the Translation Project (forward
|
|
the submission to @file{translation@@iro.umontreal.ca} in case of doubt),
|
|
to ensure that the PO file format is not severely broken and does not
|
|
prevent successful installation, and for the rest, to merely to put these
|
|
PO files in @file{po/} for distribution.
|
|
|
|
As a maintainer, you do not have to take on your shoulders the
|
|
responsibility of checking if the translations are adequate or
|
|
complete, and should avoid diving into linguistic matters. Translation
|
|
teams drive themselves and are fully responsible of their linguistic
|
|
choices for the Translation Project. Keep in mind that translator teams are @emph{not}
|
|
driven by maintainers. You can help by carefully redirecting all
|
|
communications and reports from users about linguistic matters to the
|
|
appropriate translation team, or explain users how to reach or join
|
|
their team. The simplest might be to send them the @file{ABOUT-NLS} file.
|
|
|
|
Maintainers should @emph{never ever} apply PO file bug reports
|
|
themselves, short-cutting translation teams. If some translator has
|
|
difficulty to get some of her points through her team, it should not be
|
|
an issue for her to directly negotiate translations with maintainers.
|
|
Teams ought to settle their problems themselves, if any. If you, as
|
|
a maintainer, ever think there is a real problem with a team, please
|
|
never try to @emph{solve} a team's problem on your own.
|
|
|
|
@node gettextize Invocation, Adjusting Files, Prerequisites, Maintainers
|
|
@section Invoking the @code{gettextize} Program
|
|
|
|
Some files are consistently and identically needed in every package
|
|
internationalized through GNU @code{gettext}. As a matter of
|
|
convenience, the @code{gettextize} program puts all these files right
|
|
in your package. This program has the following synopsis:
|
|
|
|
@example
|
|
gettextize [ @var{option}@dots{} ] [ @var{directory} ]
|
|
@end example
|
|
|
|
@noindent
|
|
and accepts the following options:
|
|
|
|
@table @samp
|
|
@item -c
|
|
@itemx --copy
|
|
Copy the needed files instead of making symbolic links. Using links
|
|
would allow the package to always use the latest @code{gettext} code
|
|
available on the system, but it might disturb some mechanism the
|
|
maintainer is used to apply to the sources. Because running
|
|
@code{gettextize} is easy there shouldn't be problems with using copies.
|
|
|
|
@item -f
|
|
@itemx --force
|
|
Force replacement of files which already exist.
|
|
|
|
@item -h
|
|
@itemx --help
|
|
Display this help and exit.
|
|
|
|
@item --version
|
|
Output version information and exit.
|
|
|
|
@end table
|
|
|
|
If @var{directory} is given, this is the top level directory of a
|
|
package to prepare for using GNU @code{gettext}. If not given, it
|
|
is assumed that the current directory is the top level directory of
|
|
such a package.
|
|
|
|
The program @code{gettextize} provides the following files. However,
|
|
no existing file will be replaced unless the option @code{--force}
|
|
(@code{-f}) is specified.
|
|
|
|
@enumerate
|
|
@item
|
|
The @file{ABOUT-NLS} file is copied in the main directory of your package,
|
|
the one being at the top level. This file gives the main indications
|
|
about how to install and use the Native Language Support features
|
|
of your program. You might elect to use a more recent copy of this
|
|
@file{ABOUT-NLS} file than the one provided through @code{gettextize},
|
|
if you have one handy. You may also fetch a more recent copy of file
|
|
@file{ABOUT-NLS} from Translation Project sites, and from most GNU
|
|
archive sites.
|
|
|
|
@item
|
|
A @file{po/} directory is created for eventually holding
|
|
all translation files, but initially only containing the file
|
|
@file{po/Makefile.in.in} from the GNU @code{gettext} distribution.
|
|
(beware the double @samp{.in} in the file name). If the @file{po/}
|
|
directory already exists, it will be preserved along with the files
|
|
it contains, and only @file{Makefile.in.in} will be overwritten.
|
|
|
|
@item
|
|
A @file{intl/} directory is created and filled with most of the files
|
|
originally in the @file{intl/} directory of the GNU @code{gettext}
|
|
distribution. Also, if option @code{--force} (@code{-f}) is given,
|
|
the @file{intl/} directory is emptied first.
|
|
|
|
@end enumerate
|
|
|
|
If your site support symbolic links, @code{gettextize} will not
|
|
actually copy the files into your package, but establish symbolic
|
|
links instead. This avoids duplicating the disk space needed in
|
|
all packages. Merely using the @samp{-h} option while creating the
|
|
@code{tar} archive of your distribution will resolve each link by an
|
|
actual copy in the distribution archive. So, to insist, you really
|
|
should use @samp{-h} option with @code{tar} within your @code{dist}
|
|
goal of your main @file{Makefile.in}.
|
|
|
|
It is interesting to understand that most new files for supporting
|
|
GNU @code{gettext} facilities in one package go in @file{intl/}
|
|
and @file{po/} subdirectories. One distinction between these two
|
|
directories is that @file{intl/} is meant to be completely identical
|
|
in all packages using GNU @code{gettext}, while all newly created
|
|
files, which have to be different, go into @file{po/}. There is a
|
|
common @file{Makefile.in.in} in @file{po/}, because the @file{po/}
|
|
directory needs its own @file{Makefile}, and it has been designed so
|
|
it can be identical in all packages.
|
|
|
|
@node Adjusting Files, , gettextize Invocation, Maintainers
|
|
@section Files You Must Create or Alter
|
|
|
|
Besides files which are automatically added through @code{gettextize},
|
|
there are many files needing revision for properly interacting with
|
|
GNU @code{gettext}. If you are closely following GNU standards for
|
|
Makefile engineering and auto-configuration, the adaptations should
|
|
be easier to achieve. Here is a point by point description of the
|
|
changes needed in each.
|
|
|
|
So, here comes a list of files, each one followed by a description of
|
|
all alterations it needs. Many examples are taken out from the GNU
|
|
@code{gettext} @value{VERSION} distribution itself. You may indeed
|
|
refer to the source code of the GNU @code{gettext} package, as it
|
|
is intended to be a good example and master implementation for using
|
|
its own functionality.
|
|
|
|
@menu
|
|
* po/POTFILES.in:: @file{POTFILES.in} in @file{po/}
|
|
* configure.in:: @file{configure.in} at top level
|
|
* aclocal:: @file{aclocal.m4} at top level
|
|
* acconfig:: @file{acconfig.h} at top level
|
|
* Makefile:: @file{Makefile.in} at top level
|
|
* src/Makefile:: @file{Makefile.in} in @file{src/}
|
|
@end menu
|
|
|
|
@node po/POTFILES.in, configure.in, Adjusting Files, Adjusting Files
|
|
@subsection @file{POTFILES.in} in @file{po/}
|
|
|
|
The @file{po/} directory should receive a file named
|
|
@file{POTFILES.in}. This file tells which files, among all program
|
|
sources, have marked strings needing translation. Here is an example
|
|
of such a file:
|
|
|
|
@example
|
|
@group
|
|
# List of source files containing translatable strings.
|
|
# Copyright (C) 1995 Free Software Foundation, Inc.
|
|
|
|
# Common library files
|
|
lib/error.c
|
|
lib/getopt.c
|
|
lib/xmalloc.c
|
|
|
|
# Package source files
|
|
src/gettextp.c
|
|
src/msgfmt.c
|
|
src/xgettext.c
|
|
@end group
|
|
@end example
|
|
|
|
@noindent
|
|
Dashed comments and white lines are ignored. All other lines
|
|
list those source files containing strings marked for translation
|
|
(@pxref{Mark Keywords}), in a notation relative to the top level
|
|
of your whole distribution, rather than the location of the
|
|
@file{POTFILES.in} file itself.
|
|
|
|
@node configure.in, aclocal, po/POTFILES.in, Adjusting Files
|
|
@subsection @file{configure.in} at top level
|
|
|
|
@enumerate
|
|
@item Declare the package and version.
|
|
|
|
This is done by a set of lines like these:
|
|
|
|
@example
|
|
PACKAGE=gettext
|
|
VERSION=@value{VERSION}
|
|
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
|
|
AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
|
|
AC_SUBST(PACKAGE)
|
|
AC_SUBST(VERSION)
|
|
@end example
|
|
|
|
@noindent
|
|
Of course, you replace @samp{gettext} with the name of your package,
|
|
and @samp{@value{VERSION}} by its version numbers, exactly as they
|
|
should appear in the packaged @code{tar} file name of your distribution
|
|
(@file{gettext-@value{VERSION}.tar.gz}, here).
|
|
|
|
@item Declare the available translations.
|
|
|
|
This is done by defining @code{ALL_LINGUAS} to the white separated,
|
|
quoted list of available languages, in a single line, like this:
|
|
|
|
@example
|
|
ALL_LINGUAS="de fr"
|
|
@end example
|
|
|
|
@noindent
|
|
This example means that German and French PO files are available, so
|
|
that these languages are currently supported by your package. If you
|
|
want to further restrict, at installation time, the set of installed
|
|
languages, this should not be done by modifying @code{ALL_LINGUAS} in
|
|
@file{configure.in}, but rather by using the @code{LINGUAS} environment
|
|
variable (@pxref{Installers}).
|
|
|
|
@item Check for internationalization support.
|
|
|
|
Here is the main @code{m4} macro for triggering internationalization
|
|
support. Just add this line to @file{configure.in}:
|
|
|
|
@example
|
|
AM_GNU_GETTEXT
|
|
@end example
|
|
|
|
@noindent
|
|
This call is purposely simple, even if it generates a lot of configure
|
|
time checking and actions.
|
|
|
|
@item Have output files created.
|
|
|
|
The @code{AC_OUTPUT} directive, at the end of your @file{configure.in}
|
|
file, needs to be modified in two ways:
|
|
|
|
@example
|
|
AC_OUTPUT([@var{existing configuration files} intl/Makefile po/Makefile.in],
|
|
@var{existing additional actions}])
|
|
@end example
|
|
|
|
The modification to the first argument to @code{AC_OUTPUT} asks
|
|
for substitution in the @file{intl/} and @file{po/} directories.
|
|
Note the @samp{.in} suffix used for @file{po/} only. This is because
|
|
the distributed file is really @file{po/Makefile.in.in}.
|
|
|
|
@end enumerate
|
|
|
|
@node aclocal, acconfig, configure.in, Adjusting Files
|
|
@subsection @file{aclocal.m4} at top level
|
|
|
|
If you do not have an @file{aclocal.m4} file in your distribution,
|
|
the simplest is taking a copy of @file{aclocal.m4} from
|
|
GNU @code{gettext}. But to be precise, you only need macros
|
|
@code{AM_LC_MESSAGES}, @code{AM_WITH_NLS} and @code{AM_GNU_GETTEXT},
|
|
and @code{AM_PATH_PROG_WITH_TEST}, which is called by @code{AM_WITH_NLS},
|
|
so you may use an editor and remove macros you do not need.
|
|
|
|
If you already have an @file{aclocal.m4} file, then you will have
|
|
to merge the said macros into your @file{aclocal.m4}. Note that if
|
|
you are upgrading from a previous release of GNU @code{gettext}, you
|
|
should most probably @emph{replace} the said macros, as they usually
|
|
change a little from one release of GNU @code{gettext} to the next.
|
|
Their contents may vary as we get more experience with strange systems
|
|
out there.
|
|
|
|
These macros check for the internationalization support functions
|
|
and related informations. Hopefully, once stabilized, these macros
|
|
might be integrated in the standard Autoconf set, because this
|
|
piece of @code{m4} code will be the same for all projects using GNU
|
|
@code{gettext}.
|
|
|
|
@node acconfig, Makefile, aclocal, Adjusting Files
|
|
@subsection @file{acconfig.h} at top level
|
|
|
|
If you do not have an @file{acconfig.h} file in your distribution, the
|
|
simplest is use take a copy of @file{acconfig.h} from GNU
|
|
@code{gettext}. But to be precise, you only need the lines and comments
|
|
for @code{ENABLE_NLS}, @code{HAVE_CATGETS}, @code{HAVE_GETTEXT} and
|
|
@code{HAVE_LC_MESSAGES}, @code{HAVE_STPCPY}, @code{PACKAGE} and
|
|
@code{VERSION}, so you may use an editor and remove everything else. If
|
|
you already have an @file{acconfig.h} file, then you should merge the
|
|
said definitions into your @file{acconfig.h}.
|
|
|
|
@node Makefile, src/Makefile, acconfig, Adjusting Files
|
|
@subsection @file{Makefile.in} at top level
|
|
|
|
Here are a few modifications you need to make to your main, top-level
|
|
@file{Makefile.in} file.
|
|
|
|
@enumerate
|
|
@item
|
|
Add the following lines near the beginning of your @file{Makefile.in},
|
|
so the @samp{dist:} goal will work properly (as explained further down):
|
|
|
|
@example
|
|
PACKAGE = @@PACKAGE@@
|
|
VERSION = @@VERSION@@
|
|
@end example
|
|
|
|
@item
|
|
Add file @file{ABOUT-NLS} to the @code{DISTFILES} definition, so the file gets
|
|
distributed.
|
|
|
|
@item
|
|
Wherever you process subdirectories in your @file{Makefile.in}, be sure
|
|
you also process dir subdirectories @samp{intl} and @samp{po}. Special
|
|
rules in the @file{Makefiles} take care for the case where no
|
|
internationalization is wanted.
|
|
|
|
If you are using Makefiles, either generated by automake, or hand-written
|
|
so they carefully follow the GNU coding standards, the effected goals for
|
|
which the new subdirectories must be handled include @samp{installdirs},
|
|
@samp{install}, @samp{uninstall}, @samp{clean}, @samp{distclean}.
|
|
|
|
Here is an example of a canonical order of processing. In this
|
|
example, we also define @code{SUBDIRS} in @code{Makefile.in} for it
|
|
to be further used in the @samp{dist:} goal.
|
|
|
|
@example
|
|
SUBDIRS = doc lib @@INTLSUB@@ src @@POSUB@@
|
|
@end example
|
|
|
|
@noindent
|
|
that you will have to adapt to your own package.
|
|
|
|
@item
|
|
A delicate point is the @samp{dist:} goal, as both
|
|
@file{intl/Makefile} and @file{po/Makefile} will later assume that the
|
|
proper directory has been set up from the main @file{Makefile}. Here is
|
|
an example at what the @samp{dist:} goal might look like:
|
|
|
|
@example
|
|
distdir = $(PACKAGE)-$(VERSION)
|
|
dist: Makefile
|
|
rm -fr $(distdir)
|
|
mkdir $(distdir)
|
|
chmod 777 $(distdir)
|
|
for file in $(DISTFILES); do \
|
|
ln $$file $(distdir) 2>/dev/null || cp -p $$file $(distdir); \
|
|
done
|
|
for subdir in $(SUBDIRS); do \
|
|
mkdir $(distdir)/$$subdir || exit 1; \
|
|
chmod 777 $(distdir)/$$subdir; \
|
|
(cd $$subdir && $(MAKE) $@@) || exit 1; \
|
|
done
|
|
tar chozf $(distdir).tar.gz $(distdir)
|
|
rm -fr $(distdir)
|
|
@end example
|
|
|
|
@end enumerate
|
|
|
|
@node src/Makefile, , Makefile, Adjusting Files
|
|
@subsection @file{Makefile.in} in @file{src/}
|
|
|
|
Some of the modifications made in the main @file{Makefile.in} will
|
|
also be needed in the @file{Makefile.in} from your package sources,
|
|
which we assume here to be in the @file{src/} subdirectory. Here are
|
|
all the modifications needed in @file{src/Makefile.in}:
|
|
|
|
@enumerate
|
|
@item
|
|
In view of the @samp{dist:} goal, you should have these lines near the
|
|
beginning of @file{src/Makefile.in}:
|
|
|
|
@example
|
|
PACKAGE = @@PACKAGE@@
|
|
VERSION = @@VERSION@@
|
|
@end example
|
|
|
|
@item
|
|
If not done already, you should guarantee that @code{top_srcdir}
|
|
gets defined. This will serve for @code{cpp} include files. Just add
|
|
the line:
|
|
|
|
@example
|
|
top_srcdir = @@top_srcdir@@
|
|
@end example
|
|
|
|
@item
|
|
You might also want to define @code{subdir} as @samp{src}, later
|
|
allowing for almost uniform @samp{dist:} goals in all your
|
|
@file{Makefile.in}. At list, the @samp{dist:} goal below assume that
|
|
you used:
|
|
|
|
@example
|
|
subdir = src
|
|
@end example
|
|
|
|
@item
|
|
You should ensure that the final linking will use @code{@@INTLLIBS@@} as
|
|
a library. An easy way to achieve this is to manage that it gets into
|
|
@code{LIBS}, like this:
|
|
|
|
@example
|
|
LIBS = @@INTLLIBS@@ @@LIBS@@
|
|
@end example
|
|
|
|
In most packages internationalized with GNU @code{gettext}, one will
|
|
find a directory @file{lib/} in which a library containing some helper
|
|
functions will be build. (You need at least the few functions which the
|
|
GNU @code{gettext} Library itself needs.) However some of the functions
|
|
in the @file{lib/} also give messages to the user which of course should be
|
|
translated, too. Taking care of this it is not enough to place the support
|
|
library (say @file{libsupport.a}) just between the @code{@@INTLLIBS@@}
|
|
and @code{@@LIBS@@} in the above example. Instead one has to write this:
|
|
|
|
@example
|
|
LIBS = ../lib/libsupport.a @@INTLLIBS@@ ../lib/libsupport.a @@LIBS@@
|
|
@end example
|
|
|
|
@item
|
|
You should also ensure that directory @file{intl/} will be searched for
|
|
C preprocessor include files in all circumstances. So, you have to
|
|
manage so both @samp{-I../intl} and @samp{-I$(top_srcdir)/intl} will
|
|
be given to the C compiler.
|
|
|
|
@item
|
|
Your @samp{dist:} goal has to conform with others. Here is a
|
|
reasonable definition for it:
|
|
|
|
@example
|
|
distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
|
|
dist: Makefile $(DISTFILES)
|
|
for file in $(DISTFILES); do \
|
|
ln $$file $(distdir) 2>/dev/null || cp -p $$file $(distdir); \
|
|
done
|
|
@end example
|
|
|
|
@end enumerate
|
|
|
|
@node Conclusion, Country Codes, Maintainers, Top
|
|
@chapter Concluding Remarks
|
|
|
|
We would like to conclude this GNU @code{gettext} manual by presenting
|
|
an history of the Translation Project so far. We finally give
|
|
a few pointers for those who want to do further research or readings
|
|
about Native Language Support matters.
|
|
|
|
@menu
|
|
* History:: History of GNU @code{gettext}
|
|
* References:: Related Readings
|
|
@end menu
|
|
|
|
@node History, References, Conclusion, Conclusion
|
|
@section History of GNU @code{gettext}
|
|
|
|
Internationalization concerns and algorithms have been informally
|
|
and casually discussed for years in GNU, sometimes around GNU
|
|
@code{libc}, maybe around the incoming @code{Hurd}, or otherwise
|
|
(nobody clearly remembers). And even then, when the work started for
|
|
real, this was somewhat independently of these previous discussions.
|
|
|
|
This all began in July 1994, when Patrick D'Cruze had the idea and
|
|
initiative of internationalizing version 3.9.2 of GNU @code{fileutils}.
|
|
He then asked Jim Meyering, the maintainer, how to get those changes
|
|
folded into an official release. That first draft was full of
|
|
@code{#ifdef}s and somewhat disconcerting, and Jim wanted to find
|
|
nicer ways. Patrick and Jim shared some tries and experimentations
|
|
in this area. Then, feeling that this might eventually have a deeper
|
|
impact on GNU, Jim wanted to know what standards were, and contacted
|
|
Richard Stallman, who very quickly and verbally described an overall
|
|
design for what was meant to become @code{glocale}, at that time.
|
|
|
|
Jim implemented @code{glocale} and got a lot of exhausting feedback
|
|
from Patrick and Richard, of course, but also from Mitchum DSouza
|
|
(who wrote a @code{catgets}-like package), Roland McGrath, maybe David
|
|
MacKenzie, Fran@,{c}ois Pinard, and Paul Eggert, all pushing and
|
|
pulling in various directions, not always compatible, to the extent
|
|
that after a couple of test releases, @code{glocale} was torn apart.
|
|
|
|
While Jim took some distance and time and became dad for a second
|
|
time, Roland wanted to get GNU @code{libc} internationalized, and
|
|
got Ulrich Drepper involved in that project. Instead of starting
|
|
from @code{glocale}, Ulrich rewrote something from scratch, but
|
|
more conformant to the set of guidelines who emerged out of the
|
|
@code{glocale} effort. Then, Ulrich got people from the previous
|
|
forum to involve themselves into this new project, and the switch
|
|
from @code{glocale} to what was first named @code{msgutils}, renamed
|
|
@code{nlsutils}, and later @code{gettext}, became officially accepted
|
|
by Richard in May 1995 or so.
|
|
|
|
Let's summarize by saying that Ulrich Drepper wrote GNU @code{gettext}
|
|
in April 1995. The first official release of the package, including
|
|
PO mode, occurred in July 1995, and was numbered 0.7. Other people
|
|
contributed to the effort by providing a discussion forum around
|
|
Ulrich, writing little pieces of code, or testing. These are quoted
|
|
in the @code{THANKS} file which comes with the GNU @code{gettext}
|
|
distribution.
|
|
|
|
While this was being done, Fran@,{c}ois adapted half a dozen of
|
|
GNU packages to @code{glocale} first, then later to @code{gettext},
|
|
putting them in pretest, so providing along the way an effective
|
|
user environment for fine tuning the evolving tools. He also took
|
|
the responsibility of organizing and coordinating the Translation
|
|
Project. After nearly a year of informal exchanges between people from
|
|
many countries, translator teams started to exist in May 1995, through
|
|
the creation and support by Patrick D'Cruze of twenty unmoderated
|
|
mailing lists for that many native languages, and two moderated
|
|
lists: one for reaching all teams at once, the other for reaching
|
|
all willing maintainers of internationalized free software packages.
|
|
|
|
Fran@,{c}ois also wrote PO mode in June 1995 with the collaboration
|
|
of Greg McGary, as a kind of contribution to Ulrich's package.
|
|
He also gave a hand with the GNU @code{gettext} Texinfo manual.
|
|
|
|
@node References, , History, Conclusion
|
|
@section Related Readings
|
|
|
|
Eugene H. Dorr (@file{dorre@@well.com}) maintains an interesting
|
|
bibliography on internationalization matters, called
|
|
@cite{Internationalization Reference List}, which is available as:
|
|
@example
|
|
ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/i18n-books.txt
|
|
@end example
|
|
|
|
Michael Gschwind (@file{mike@@vlsivie.tuwien.ac.at}) maintains a
|
|
Frequently Asked Questions (FAQ) list, entitled @cite{Programming for
|
|
Internationalisation}. This FAQ discusses writing programs which
|
|
can handle different language conventions, character sets, etc.;
|
|
and is applicable to all character set encodings, with particular
|
|
emphasis on @w{ISO 8859-1}. It is regularly published in Usenet
|
|
groups @file{comp.unix.questions}, @file{comp.std.internat},
|
|
@file{comp.software.international}, @file{comp.lang.c},
|
|
@file{comp.windows.x}, @file{comp.std.c}, @file{comp.answers}
|
|
and @file{news.answers}. The home location of this document is:
|
|
@example
|
|
ftp://ftp.vlsivie.tuwien.ac.at/pub/8bit/ISO-programming
|
|
@end example
|
|
|
|
Patrick D'Cruze (@file{pdcruze@@li.org}) wrote a tutorial about NLS
|
|
matters, and Jochen Hein (@file{Hein@@student.tu-clausthal.de}) took
|
|
over the responsibility of maintaining it. It may be found as:
|
|
@example
|
|
ftp://sunsite.unc.edu/pub/Linux/utils/nls/catalogs/Incoming/...
|
|
...locale-tutorial-0.8.txt.gz
|
|
@end example
|
|
@noindent
|
|
This site is mirrored in:
|
|
@example
|
|
ftp://ftp.ibp.fr/pub/linux/sunsite/
|
|
@end example
|
|
|
|
A French version of the same tutorial should be findable at:
|
|
@example
|
|
ftp://ftp.ibp.fr/pub/linux/french/docs/
|
|
@end example
|
|
@noindent
|
|
together with French translations of many Linux-related documents.
|
|
|
|
@node Country Codes, , Conclusion, Top
|
|
@appendix Country Codes
|
|
|
|
The @w{ISO 639} standard defines two character codes for many countries.
|
|
All abreviations for countries or languages used in the Translation
|
|
Project should come from this standard.
|
|
|
|
@table @samp
|
|
@include iso-apdx.texi
|
|
@end table
|
|
|
|
@contents
|
|
@bye
|
|
|
|
@c Local variables:
|
|
@c texinfo-column-for-description: 32
|
|
@c End:
|