jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: GNU gettext utilities: 8. Editing PO Files jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:
[ << ][ >> ]           [Top][Contents][Index][ ? ]
jpayne@68: jpayne@68:
jpayne@68: jpayne@68: jpayne@68:

8. Editing PO Files

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.1 KDE's PO File Editor

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.2 GNOME's PO File Editor

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3 Emacs's PO File Editor

jpayne@68: jpayne@68: jpayne@68:

For those of you being jpayne@68: the lucky users of Emacs, PO mode has been specifically created jpayne@68: for providing a cozy environment for editing or modifying PO files. jpayne@68: While editing a PO file, PO mode allows for the easy browsing of jpayne@68: auxiliary and compendium PO files, as well as for following references into jpayne@68: the set of C program sources from which PO files have been derived. jpayne@68: It has a few special features, among which are the interactive marking jpayne@68: of program strings as translatable, and the validation of PO files jpayne@68: with easy repositioning to PO file lines showing errors. jpayne@68:

jpayne@68:

For the beginning, besides main PO mode commands jpayne@68: (see section Main PO mode Commands), you should know how to move between entries jpayne@68: (see section Entry Positioning), and how to handle untranslated entries jpayne@68: (see section Untranslated Entries). jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.1 Completing GNU gettext Installation

jpayne@68: jpayne@68:

Once you have received, unpacked, configured and compiled the GNU jpayne@68: gettext distribution, the ‘make install’ command puts in jpayne@68: place the programs xgettext, msgfmt, gettext, and jpayne@68: msgmerge, as well as their available message catalogs. To jpayne@68: top off a comfortable installation, you might also want to make the jpayne@68: PO mode available to your Emacs users. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

During the installation of the PO mode, you might want to modify your jpayne@68: file ‘.emacs’, once and for all, so it contains a few lines looking jpayne@68: like: jpayne@68:

jpayne@68:
 
(setq auto-mode-alist
jpayne@68:       (cons '("\\.po\\'\\|\\.po\\." . po-mode) auto-mode-alist))
jpayne@68: (autoload 'po-mode "po-mode" "Major mode for translators to edit PO files" t)
jpayne@68: 
jpayne@68: jpayne@68:

Later, whenever you edit some ‘.po’ jpayne@68: file, or any file having the string ‘.po.’ within its name, jpayne@68: Emacs loads ‘po-mode.elc’ (or ‘po-mode.el’) as needed, and jpayne@68: automatically activates PO mode commands for the associated buffer. jpayne@68: The string PO appears in the mode line for any buffer for jpayne@68: which PO mode is active. Many PO files may be active at once in a jpayne@68: single Emacs session. jpayne@68:

jpayne@68:

If you are using Emacs version 20 or newer, and have already installed jpayne@68: the appropriate international fonts on your system, you may also tell jpayne@68: Emacs how to determine automatically the coding system of every PO file. jpayne@68: This will often (but not always) cause the necessary fonts to be loaded jpayne@68: and used for displaying the translations on your Emacs screen. For this jpayne@68: to happen, add the lines: jpayne@68:

jpayne@68:
 
(modify-coding-system-alist 'file "\\.po\\'\\|\\.po\\."
jpayne@68:                             'po-find-file-coding-system)
jpayne@68: (autoload 'po-find-file-coding-system "po-mode")
jpayne@68: 
jpayne@68: jpayne@68:

to your ‘.emacs’ file. If, with this, you still see boxes instead jpayne@68: of international characters, try a different font set (via Shift Mouse jpayne@68: button 1). jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.2 Main PO mode Commands

jpayne@68: jpayne@68:

After setting up Emacs with something similar to the lines in jpayne@68: Completing GNU gettext Installation, PO mode is activated for a window when Emacs finds a jpayne@68: PO file in that window. This puts the window read-only and establishes a jpayne@68: po-mode-map, which is a genuine Emacs mode, in a way that is not derived jpayne@68: from text mode in any way. Functions found on po-mode-hook, jpayne@68: if any, will be executed. jpayne@68:

jpayne@68:

When PO mode is active in a window, the letters ‘PO’ appear jpayne@68: in the mode line for that window. The mode line also displays how jpayne@68: many entries of each kind are held in the PO file. For example, jpayne@68: the string ‘132t+3f+10u+2o’ would tell the translator that the jpayne@68: PO mode contains 132 translated entries (see section Translated Entries, jpayne@68: 3 fuzzy entries (see section Fuzzy Entries), 10 untranslated entries jpayne@68: (see section Untranslated Entries) and 2 obsolete entries (see section Obsolete Entries). Zero-coefficients items are not shown. So, in this example, if jpayne@68: the fuzzy entries were unfuzzied, the untranslated entries were translated jpayne@68: and the obsolete entries were deleted, the mode line would merely display jpayne@68: ‘145t’ for the counters. jpayne@68:

jpayne@68:

The main PO commands are those which do not fit into the other categories of jpayne@68: subsequent sections. These allow for quitting PO mode or for managing windows jpayne@68: in special ways. jpayne@68:

jpayne@68:
jpayne@68:
_
jpayne@68:
jpayne@68:

Undo last modification to the PO file (po-undo). jpayne@68:

jpayne@68:
jpayne@68:
Q
jpayne@68:
jpayne@68:

Quit processing and save the PO file (po-quit). jpayne@68:

jpayne@68:
jpayne@68:
q
jpayne@68:
jpayne@68:

Quit processing, possibly after confirmation (po-confirm-and-quit). jpayne@68:

jpayne@68:
jpayne@68:
0
jpayne@68:
jpayne@68:

Temporary leave the PO file window (po-other-window). jpayne@68:

jpayne@68:
jpayne@68:
?
jpayne@68:
h
jpayne@68:
jpayne@68: jpayne@68:

Show help about PO mode (po-help). jpayne@68:

jpayne@68:
jpayne@68:
=
jpayne@68:
jpayne@68:

Give some PO file statistics (po-statistics). jpayne@68:

jpayne@68:
jpayne@68:
V
jpayne@68:
jpayne@68:

Batch validate the format of the whole PO file (po-validate). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The command _ (po-undo) interfaces to the Emacs jpayne@68: undo facility. See (emacs)Undo section `Undoing Changes' in The Emacs Editor. Each time _ is typed, modifications which the translator jpayne@68: did to the PO file are undone a little more. For the purpose of jpayne@68: undoing, each PO mode command is atomic. This is especially true for jpayne@68: the <RET> command: the whole edition made by using a single jpayne@68: use of this command is undone at once, even if the edition itself jpayne@68: implied several actions. However, while in the editing window, one jpayne@68: can undo the edition work quite parsimoniously. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The commands Q (po-quit) and q jpayne@68: (po-confirm-and-quit) are used when the translator is done with the jpayne@68: PO file. The former is a bit less verbose than the latter. If the file jpayne@68: has been modified, it is saved to disk first. In both cases, and prior to jpayne@68: all this, the commands check if any untranslated messages remain in the jpayne@68: PO file and, if so, the translator is asked if she really wants to leave jpayne@68: off working with this PO file. This is the preferred way of getting rid jpayne@68: of an Emacs PO file buffer. Merely killing it through the usual command jpayne@68: C-x k (kill-buffer) is not the tidiest way to proceed. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The command 0 (po-other-window) is another, softer way, jpayne@68: to leave PO mode, temporarily. It just moves the cursor to some other jpayne@68: Emacs window, and pops one if necessary. For example, if the translator jpayne@68: just got PO mode to show some source context in some other, she might jpayne@68: discover some apparent bug in the program source that needs correction. jpayne@68: This command allows the translator to change sex, become a programmer, jpayne@68: and have the cursor right into the window containing the program she jpayne@68: (or rather he) wants to modify. By later getting the cursor back jpayne@68: in the PO file window, or by asking Emacs to edit this file once again, jpayne@68: PO mode is then recovered. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The command h (po-help) displays a summary of all available PO jpayne@68: mode commands. The translator should then type any character to resume jpayne@68: normal PO mode operations. The command ? has the same effect jpayne@68: as h. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The command = (po-statistics) computes the total number of jpayne@68: entries in the PO file, the ordinal of the current entry (counted from jpayne@68: 1), the number of untranslated entries, the number of obsolete entries, jpayne@68: and displays all these numbers. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The command V (po-validate) launches msgfmt in jpayne@68: checking and verbose jpayne@68: mode over the current PO file. This command first offers to save the jpayne@68: current PO file on disk. The msgfmt tool, from GNU gettext, jpayne@68: has the purpose of creating a MO file out of a PO file, and PO mode uses jpayne@68: the features of this program for checking the overall format of a PO file, jpayne@68: as well as all individual entries. jpayne@68:

jpayne@68: jpayne@68:

The program msgfmt runs asynchronously with Emacs, so the jpayne@68: translator regains control immediately while her PO file is being studied. jpayne@68: Error output is collected in the Emacs ‘*compilation*’ buffer, jpayne@68: displayed in another window. The regular Emacs command C-x` jpayne@68: (next-error), as well as other usual compile commands, allow the jpayne@68: translator to reposition quickly to the offending parts of the PO file. jpayne@68: Once the cursor is on the line in error, the translator may decide on jpayne@68: any PO mode action which would help correcting the error. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.3 Entry Positioning

jpayne@68: jpayne@68:

The cursor in a PO file window is almost always part of jpayne@68: an entry. The only exceptions are the special case when the cursor jpayne@68: is after the last entry in the file, or when the PO file is jpayne@68: empty. The entry where the cursor is found to be is said to be the jpayne@68: current entry. Many PO mode commands operate on the current entry, jpayne@68: so moving the cursor does more than allowing the translator to browse jpayne@68: the PO file, this also selects on which entry commands operate. jpayne@68:

jpayne@68: jpayne@68:

Some PO mode commands alter the position of the cursor in a specialized jpayne@68: way. A few of those special purpose positioning are described here, jpayne@68: the others are described in following sections (for a complete list try jpayne@68: C-h m): jpayne@68:

jpayne@68:
jpayne@68:
.
jpayne@68:
jpayne@68:

Redisplay the current entry (po-current-entry). jpayne@68:

jpayne@68:
jpayne@68:
n
jpayne@68:
jpayne@68:

Select the entry after the current one (po-next-entry). jpayne@68:

jpayne@68:
jpayne@68:
p
jpayne@68:
jpayne@68:

Select the entry before the current one (po-previous-entry). jpayne@68:

jpayne@68:
jpayne@68:
<
jpayne@68:
jpayne@68:

Select the first entry in the PO file (po-first-entry). jpayne@68:

jpayne@68:
jpayne@68:
>
jpayne@68:
jpayne@68:

Select the last entry in the PO file (po-last-entry). jpayne@68:

jpayne@68:
jpayne@68:
m
jpayne@68:
jpayne@68:

Record the location of the current entry for later use jpayne@68: (po-push-location). jpayne@68:

jpayne@68:
jpayne@68:
r
jpayne@68:
jpayne@68:

Return to a previously saved entry location (po-pop-location). jpayne@68:

jpayne@68:
jpayne@68:
x
jpayne@68:
jpayne@68:

Exchange the current entry location with the previously saved one jpayne@68: (po-exchange-location). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68:

Any Emacs command able to reposition the cursor may be used jpayne@68: to select the current entry in PO mode, including commands which jpayne@68: move by characters, lines, paragraphs, screens or pages, and search jpayne@68: commands. However, there is a kind of standard way to display the jpayne@68: current entry in PO mode, which usual Emacs commands moving jpayne@68: the cursor do not especially try to enforce. The command . jpayne@68: (po-current-entry) has the sole purpose of redisplaying the jpayne@68: current entry properly, after the current entry has been changed by jpayne@68: means external to PO mode, or the Emacs screen otherwise altered. jpayne@68:

jpayne@68:

It is yet to be decided if PO mode helps the translator, or otherwise jpayne@68: irritates her, by forcing a rigid window disposition while she jpayne@68: is doing her work. We originally had quite precise ideas about jpayne@68: how windows should behave, but on the other hand, anyone used to jpayne@68: Emacs is often happy to keep full control. Maybe a fixed window jpayne@68: disposition might be offered as a PO mode option that the translator jpayne@68: might activate or deactivate at will, so it could be offered on an jpayne@68: experimental basis. If nobody feels a real need for using it, or jpayne@68: a compulsion for writing it, we should drop this whole idea. jpayne@68: The incentive for doing it should come from translators rather than jpayne@68: programmers, as opinions from an experienced translator are surely jpayne@68: more worth to me than opinions from programmers thinking about jpayne@68: how others should do translation. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The commands n (po-next-entry) and p jpayne@68: (po-previous-entry) move the cursor the entry following, jpayne@68: or preceding, the current one. If n is given while the jpayne@68: cursor is on the last entry of the PO file, or if p jpayne@68: is given while the cursor is on the first entry, no move is done. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The commands < (po-first-entry) and > jpayne@68: (po-last-entry) move the cursor to the first entry, or last jpayne@68: entry, of the PO file. When the cursor is located past the last jpayne@68: entry in a PO file, most PO mode commands will return an error saying jpayne@68: ‘After last entry’. Moreover, the commands < and > jpayne@68: have the special property of being able to work even when the cursor jpayne@68: is not into some PO file entry, and one may use them for nicely jpayne@68: correcting this situation. But even these commands will fail on a jpayne@68: truly empty PO file. There are development plans for the PO mode for it jpayne@68: to interactively fill an empty PO file from sources. See section Marking Translatable Strings. jpayne@68:

jpayne@68:

The translator may decide, before working at the translation of jpayne@68: a particular entry, that she needs to browse the remainder of the jpayne@68: PO file, maybe for finding the terminology or phraseology used jpayne@68: in related entries. She can of course use the standard Emacs idioms jpayne@68: for saving the current cursor location in some register, and use that jpayne@68: register for getting back, or else, use the location ring. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

PO mode offers another approach, by which cursor locations may be saved jpayne@68: onto a special stack. The command m (po-push-location) jpayne@68: merely adds the location of current entry to the stack, pushing jpayne@68: the already saved locations under the new one. The command jpayne@68: r (po-pop-location) consumes the top stack element and jpayne@68: repositions the cursor to the entry associated with that top element. jpayne@68: This position is then lost, for the next r will move the cursor jpayne@68: to the previously saved location, and so on until no locations remain jpayne@68: on the stack. jpayne@68:

jpayne@68:

If the translator wants the position to be kept on the location stack, jpayne@68: maybe for taking a look at the entry associated with the top jpayne@68: element, then go elsewhere with the intent of getting back later, she jpayne@68: ought to use m immediately after r. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The command x (po-exchange-location) simultaneously jpayne@68: repositions the cursor to the entry associated with the top element of jpayne@68: the stack of saved locations, and replaces that top element with the jpayne@68: location of the current entry before the move. Consequently, repeating jpayne@68: the x command toggles alternatively between two entries. jpayne@68: For achieving this, the translator will position the cursor on the jpayne@68: first entry, use m, then position to the second entry, and jpayne@68: merely use x for making the switch. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.4 Normalizing Strings in Entries

jpayne@68: jpayne@68:

There are many different ways for encoding a particular string into a jpayne@68: PO file entry, because there are so many different ways to split and jpayne@68: quote multi-line strings, and even, to represent special characters jpayne@68: by backslashed escaped sequences. Some features of PO mode rely on jpayne@68: the ability for PO mode to scan an already existing PO file for a jpayne@68: particular string encoded into the msgid field of some entry. jpayne@68: Even if PO mode has internally all the built-in machinery for jpayne@68: implementing this recognition easily, doing it fast is technically jpayne@68: difficult. To facilitate a solution to this efficiency problem, jpayne@68: we decided on a canonical representation for strings. jpayne@68:

jpayne@68:

A conventional representation of strings in a PO file is currently jpayne@68: under discussion, and PO mode experiments with a canonical representation. jpayne@68: Having both xgettext and PO mode converging towards a uniform jpayne@68: way of representing equivalent strings would be useful, as the internal jpayne@68: normalization needed by PO mode could be automatically satisfied jpayne@68: when using xgettext from GNU gettext. An explicit jpayne@68: PO mode normalization should then be only necessary for PO files jpayne@68: imported from elsewhere, or for when the convention itself evolves. jpayne@68:

jpayne@68:

So, for achieving normalization of at least the strings of a given jpayne@68: PO file needing a canonical representation, the following PO mode jpayne@68: command is available: jpayne@68:

jpayne@68: jpayne@68:
jpayne@68:
M-x po-normalize
jpayne@68:
jpayne@68:

Tidy the whole PO file by making entries more uniform. jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68:

The special command M-x po-normalize, which has no associated jpayne@68: keys, revises all entries, ensuring that strings of both original jpayne@68: and translated entries use uniform internal quoting in the PO file. jpayne@68: It also removes any crumb after the last entry. This command may be jpayne@68: useful for PO files freshly imported from elsewhere, or if we ever jpayne@68: improve on the canonical quoting format we use. This canonical format jpayne@68: is not only meant for getting cleaner PO files, but also for greatly jpayne@68: speeding up msgid string lookup for some other PO mode commands. jpayne@68:

jpayne@68:

M-x po-normalize presently makes three passes over the entries. jpayne@68: The first implements heuristics for converting PO files for GNU jpayne@68: gettext 0.6 and earlier, in which msgid and msgstr jpayne@68: fields were using K&R style C string syntax for multi-line strings. jpayne@68: These heuristics may fail for comments not related to obsolete jpayne@68: entries and ending with a backslash; they also depend on subsequent jpayne@68: passes for finalizing the proper commenting of continued lines for jpayne@68: obsolete entries. This first pass might disappear once all oldish PO jpayne@68: files would have been adjusted. The second and third pass normalize jpayne@68: all msgid and msgstr strings respectively. They also jpayne@68: clean out those trailing backslashes used by XView's msgfmt jpayne@68: for continued lines. jpayne@68:

jpayne@68: jpayne@68:

Having such an explicit normalizing command allows for importing PO jpayne@68: files from other sources, but also eases the evolution of the current jpayne@68: convention, evolution driven mostly by aesthetic concerns, as of now. jpayne@68: It is easy to make suggested adjustments at a later time, as the jpayne@68: normalizing command and eventually, other GNU gettext tools jpayne@68: should greatly automate conformance. A description of the canonical jpayne@68: string format is given below, for the particular benefit of those not jpayne@68: having Emacs handy, and who would nevertheless want to handcraft jpayne@68: their PO files in nice ways. jpayne@68:

jpayne@68: jpayne@68:

Right now, in PO mode, strings are single line or multi-line. A string jpayne@68: goes multi-line if and only if it has embedded newlines, that jpayne@68: is, if it matches ‘[^\n]\n+[^\n]’. So, we would have: jpayne@68:

jpayne@68:
 
msgstr "\n\nHello, world!\n\n\n"
jpayne@68: 
jpayne@68: jpayne@68:

but, replacing the space by a newline, this becomes: jpayne@68:

jpayne@68:
 
msgstr ""
jpayne@68: "\n"
jpayne@68: "\n"
jpayne@68: "Hello,\n"
jpayne@68: "world!\n"
jpayne@68: "\n"
jpayne@68: "\n"
jpayne@68: 
jpayne@68: jpayne@68:

We are deliberately using a caricatural example, here, to make the jpayne@68: point clearer. Usually, multi-lines are not that bad looking. jpayne@68: It is probable that we will implement the following suggestion. jpayne@68: We might lump together all initial newlines into the empty string, jpayne@68: and also all newlines introducing empty lines (that is, for n jpayne@68: > 1, the n-1'th last newlines would go together on a separate jpayne@68: string), so making the previous example appear: jpayne@68:

jpayne@68:
 
msgstr "\n\n"
jpayne@68: "Hello,\n"
jpayne@68: "world!\n"
jpayne@68: "\n\n"
jpayne@68: 
jpayne@68: jpayne@68:

There are a few yet undecided little points about string normalization, jpayne@68: to be documented in this manual, once these questions settle. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.5 Translated Entries

jpayne@68: jpayne@68:

Each PO file entry for which the msgstr field has been filled with jpayne@68: a translation, and which is not marked as fuzzy (see section Fuzzy Entries), jpayne@68: is said to be a translated entry. Only translated entries will jpayne@68: later be compiled by GNU msgfmt and become usable in programs. jpayne@68: Other entry types will be excluded; translation will not occur for them. jpayne@68:

jpayne@68: jpayne@68:

Some commands are more specifically related to translated entry processing. jpayne@68:

jpayne@68:
jpayne@68:
t
jpayne@68:
jpayne@68:

Find the next translated entry (po-next-translated-entry). jpayne@68:

jpayne@68:
jpayne@68:
T
jpayne@68:
jpayne@68:

Find the previous translated entry (po-previous-translated-entry). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The commands t (po-next-translated-entry) and T jpayne@68: (po-previous-translated-entry) move forwards or backwards, chasing jpayne@68: for an translated entry. If none is found, the search is extended and jpayne@68: wraps around in the PO file buffer. jpayne@68:

jpayne@68: jpayne@68:

Translated entries usually result from the translator having edited in jpayne@68: a translation for them, Modifying Translations. However, if the jpayne@68: variable po-auto-fuzzy-on-edit is not nil, the entry having jpayne@68: received a new translation first becomes a fuzzy entry, which ought to jpayne@68: be later unfuzzied before becoming an official, genuine translated entry. jpayne@68: See section Fuzzy Entries. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.6 Fuzzy Entries

jpayne@68: jpayne@68:

Each PO file entry may have a set of attributes, which are jpayne@68: qualities given a name and explicitly associated with the translation, jpayne@68: using a special system comment. One of these attributes jpayne@68: has the name fuzzy, and entries having this attribute are said jpayne@68: to have a fuzzy translation. They are called fuzzy entries, for short. jpayne@68:

jpayne@68:

Fuzzy entries, even if they account for translated entries for jpayne@68: most other purposes, usually call for revision by the translator. jpayne@68: Those may be produced by applying the program msgmerge to jpayne@68: update an older translated PO files according to a new PO template jpayne@68: file, when this tool hypothesises that some new msgid has jpayne@68: been modified only slightly out of an older one, and chooses to pair jpayne@68: what it thinks to be the old translation for the new modified entry. jpayne@68: The slight alteration in the original string (the msgid string) jpayne@68: should often be reflected in the translated string, and this requires jpayne@68: the intervention of the translator. For this reason, msgmerge jpayne@68: might mark some entries as being fuzzy. jpayne@68:

jpayne@68: jpayne@68:

Also, the translator may decide herself to mark an entry as fuzzy jpayne@68: for her own convenience, when she wants to remember that the entry jpayne@68: has to be later revisited. So, some commands are more specifically jpayne@68: related to fuzzy entry processing. jpayne@68:

jpayne@68:
jpayne@68:
f
jpayne@68:
jpayne@68:

Find the next fuzzy entry (po-next-fuzzy-entry). jpayne@68:

jpayne@68:
jpayne@68:
F
jpayne@68:
jpayne@68:

Find the previous fuzzy entry (po-previous-fuzzy-entry). jpayne@68:

jpayne@68:
jpayne@68:
<TAB>
jpayne@68:
jpayne@68:

Remove the fuzzy attribute of the current entry (po-unfuzzy). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The commands f (po-next-fuzzy-entry) and F jpayne@68: (po-previous-fuzzy-entry) move forwards or backwards, chasing for jpayne@68: a fuzzy entry. If none is found, the search is extended and wraps jpayne@68: around in the PO file buffer. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The command <TAB> (po-unfuzzy) removes the fuzzy jpayne@68: attribute associated with an entry, usually leaving it translated. jpayne@68: Further, if the variable po-auto-select-on-unfuzzy has not jpayne@68: the nil value, the <TAB> command will automatically chase jpayne@68: for another interesting entry to work on. The initial value of jpayne@68: po-auto-select-on-unfuzzy is nil. jpayne@68:

jpayne@68:

The initial value of po-auto-fuzzy-on-edit is nil. However, jpayne@68: if the variable po-auto-fuzzy-on-edit is set to t, any entry jpayne@68: edited through the <RET> command is marked fuzzy, as a way to jpayne@68: ensure some kind of double check, later. In this case, the usual paradigm jpayne@68: is that an entry becomes fuzzy (if not already) whenever the translator jpayne@68: modifies it. If she is satisfied with the translation, she then uses jpayne@68: <TAB> to pick another entry to work on, clearing the fuzzy attribute jpayne@68: on the same blow. If she is not satisfied yet, she merely uses <SPC> jpayne@68: to chase another entry, leaving the entry fuzzy. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The translator may also use the <DEL> command jpayne@68: (po-fade-out-entry) over any translated entry to mark it as being jpayne@68: fuzzy, when she wants to easily leave a trace she wants to later return jpayne@68: working at this entry. jpayne@68:

jpayne@68:

Also, when time comes to quit working on a PO file buffer with the q jpayne@68: command, the translator is asked for confirmation, if fuzzy string jpayne@68: still exists. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.7 Untranslated Entries

jpayne@68: jpayne@68:

When xgettext originally creates a PO file, unless told jpayne@68: otherwise, it initializes the msgid field with the untranslated jpayne@68: string, and leaves the msgstr string to be empty. Such entries, jpayne@68: having an empty translation, are said to be untranslated entries. jpayne@68: Later, when the programmer slightly modifies some string right in jpayne@68: the program, this change is later reflected in the PO file jpayne@68: by the appearance of a new untranslated entry for the modified string. jpayne@68:

jpayne@68:

The usual commands moving from entry to entry consider untranslated jpayne@68: entries on the same level as active entries. Untranslated entries jpayne@68: are easily recognizable by the fact they end with ‘msgstr ""’. jpayne@68:

jpayne@68: jpayne@68:

The work of the translator might be (quite naively) seen as the process jpayne@68: of seeking for an untranslated entry, editing a translation for jpayne@68: it, and repeating these actions until no untranslated entries remain. jpayne@68: Some commands are more specifically related to untranslated entry jpayne@68: processing. jpayne@68:

jpayne@68:
jpayne@68:
u
jpayne@68:
jpayne@68:

Find the next untranslated entry (po-next-untranslated-entry). jpayne@68:

jpayne@68:
jpayne@68:
U
jpayne@68:
jpayne@68:

Find the previous untranslated entry (po-previous-untransted-entry). jpayne@68:

jpayne@68:
jpayne@68:
k
jpayne@68:
jpayne@68:

Turn the current entry into an untranslated one (po-kill-msgstr). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The commands u (po-next-untranslated-entry) and U jpayne@68: (po-previous-untransted-entry) move forwards or backwards, jpayne@68: chasing for an untranslated entry. If none is found, the search is jpayne@68: extended and wraps around in the PO file buffer. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

An entry can be turned back into an untranslated entry by jpayne@68: merely emptying its translation, using the command k jpayne@68: (po-kill-msgstr). See section Modifying Translations. jpayne@68:

jpayne@68:

Also, when time comes to quit working on a PO file buffer jpayne@68: with the q command, the translator is asked for confirmation, jpayne@68: if some untranslated string still exists. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.8 Obsolete Entries

jpayne@68: jpayne@68:

By obsolete PO file entries, we mean those entries which are jpayne@68: commented out, usually by msgmerge when it found that the jpayne@68: translation is not needed anymore by the package being localized. jpayne@68:

jpayne@68:

The usual commands moving from entry to entry consider obsolete jpayne@68: entries on the same level as active entries. Obsolete entries are jpayne@68: easily recognizable by the fact that all their lines start with jpayne@68: #, even those lines containing msgid or msgstr. jpayne@68:

jpayne@68:

Commands exist for emptying the translation or reinitializing it jpayne@68: to the original untranslated string. Commands interfacing with the jpayne@68: kill ring may force some previously saved text into the translation. jpayne@68: The user may interactively edit the translation. All these commands jpayne@68: may apply to obsolete entries, carefully leaving the entry obsolete jpayne@68: after the fact. jpayne@68:

jpayne@68: jpayne@68:

Moreover, some commands are more specifically related to obsolete jpayne@68: entry processing. jpayne@68:

jpayne@68:
jpayne@68:
o
jpayne@68:
jpayne@68:

Find the next obsolete entry (po-next-obsolete-entry). jpayne@68:

jpayne@68:
jpayne@68:
O
jpayne@68:
jpayne@68:

Find the previous obsolete entry (po-previous-obsolete-entry). jpayne@68:

jpayne@68:
jpayne@68:
<DEL>
jpayne@68:
jpayne@68:

Make an active entry obsolete, or zap out an obsolete entry jpayne@68: (po-fade-out-entry). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The commands o (po-next-obsolete-entry) and O jpayne@68: (po-previous-obsolete-entry) move forwards or backwards, jpayne@68: chasing for an obsolete entry. If none is found, the search is jpayne@68: extended and wraps around in the PO file buffer. jpayne@68:

jpayne@68:

PO mode does not provide ways for un-commenting an obsolete entry jpayne@68: and making it active, because this would reintroduce an original jpayne@68: untranslated string which does not correspond to any marked string jpayne@68: in the program sources. This goes with the philosophy of never jpayne@68: introducing useless msgid values. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

However, it is possible to comment out an active entry, so making jpayne@68: it obsolete. GNU gettext utilities will later react to the jpayne@68: disappearance of a translation by using the untranslated string. jpayne@68: The command <DEL> (po-fade-out-entry) pushes the current entry jpayne@68: a little further towards annihilation. If the entry is active (it is a jpayne@68: translated entry), then it is first made fuzzy. If it is already fuzzy, jpayne@68: then the entry is merely commented out, with confirmation. If the entry jpayne@68: is already obsolete, then it is completely deleted from the PO file. jpayne@68: It is easy to recycle the translation so deleted into some other PO file jpayne@68: entry, usually one which is untranslated. See section Modifying Translations. jpayne@68:

jpayne@68:

Here is a quite interesting problem to solve for later development of jpayne@68: PO mode, for those nights you are not sleepy. The idea would be that jpayne@68: PO mode might become bright enough, one of these days, to make good jpayne@68: guesses at retrieving the most probable candidate, among all obsolete jpayne@68: entries, for initializing the translation of a newly appeared string. jpayne@68: I think it might be a quite hard problem to do this algorithmically, as jpayne@68: we have to develop good and efficient measures of string similarity. jpayne@68: Right now, PO mode completely lets the decision to the translator, jpayne@68: when the time comes to find the adequate obsolete translation, it jpayne@68: merely tries to provide handy tools for helping her to do so. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.9 Modifying Translations

jpayne@68: jpayne@68:

PO mode prevents direct modification of the PO file, by the usual jpayne@68: means Emacs gives for altering a buffer's contents. By doing so, jpayne@68: it pretends helping the translator to avoid little clerical errors jpayne@68: about the overall file format, or the proper quoting of strings, jpayne@68: as those errors would be easily made. Other kinds of errors are jpayne@68: still possible, but some may be caught and diagnosed by the batch jpayne@68: validation process, which the translator may always trigger by the jpayne@68: V command. For all other errors, the translator has to rely on jpayne@68: her own judgment, and also on the linguistic reports submitted to her jpayne@68: by the users of the translated package, having the same mother tongue. jpayne@68:

jpayne@68:

When the time comes to create a translation, correct an error diagnosed jpayne@68: mechanically or reported by a user, the translators have to resort to jpayne@68: using the following commands for modifying the translations. jpayne@68:

jpayne@68:
jpayne@68:
<RET>
jpayne@68:
jpayne@68:

Interactively edit the translation (po-edit-msgstr). jpayne@68:

jpayne@68:
jpayne@68:
<LFD>
jpayne@68:
C-j
jpayne@68:
jpayne@68: jpayne@68:

Reinitialize the translation with the original, untranslated string jpayne@68: (po-msgid-to-msgstr). jpayne@68:

jpayne@68:
jpayne@68:
k
jpayne@68:
jpayne@68:

Save the translation on the kill ring, and delete it (po-kill-msgstr). jpayne@68:

jpayne@68:
jpayne@68:
w
jpayne@68:
jpayne@68:

Save the translation on the kill ring, without deleting it jpayne@68: (po-kill-ring-save-msgstr). jpayne@68:

jpayne@68:
jpayne@68:
y
jpayne@68:
jpayne@68:

Replace the translation, taking the new from the kill ring jpayne@68: (po-yank-msgstr). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The command <RET> (po-edit-msgstr) opens a new Emacs jpayne@68: window meant to edit in a new translation, or to modify an already existing jpayne@68: translation. The new window contains a copy of the translation taken from jpayne@68: the current PO file entry, all ready for edition, expunged of all quoting jpayne@68: marks, fully modifiable and with the complete extent of Emacs modifying jpayne@68: commands. When the translator is done with her modifications, she may use jpayne@68: C-c C-c to close the subedit window with the automatically requoted jpayne@68: results, or C-c C-k to abort her modifications. See section Details of Sub Edition, jpayne@68: for more information. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The command <LFD> (po-msgid-to-msgstr) initializes, or jpayne@68: reinitializes the translation with the original string. This command is jpayne@68: normally used when the translator wants to redo a fresh translation of jpayne@68: the original string, disregarding any previous work. jpayne@68:

jpayne@68: jpayne@68:

It is possible to arrange so, whenever editing an untranslated jpayne@68: entry, the <LFD> command be automatically executed. If you set jpayne@68: po-auto-edit-with-msgid to t, the translation gets jpayne@68: initialised with the original string, in case none exists already. jpayne@68: The default value for po-auto-edit-with-msgid is nil. jpayne@68:

jpayne@68: jpayne@68:

In fact, whether it is best to start a translation with an empty jpayne@68: string, or rather with a copy of the original string, is a matter of jpayne@68: taste or habit. Sometimes, the source language and the jpayne@68: target language are so different that is simply best to start writing jpayne@68: on an empty page. At other times, the source and target languages jpayne@68: are so close that it would be a waste to retype a number of words jpayne@68: already being written in the original string. A translator may also jpayne@68: like having the original string right under her eyes, as she will jpayne@68: progressively overwrite the original text with the translation, even jpayne@68: if this requires some extra editing work to get rid of the original. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The command k (po-kill-msgstr) merely empties the jpayne@68: translation string, so turning the entry into an untranslated jpayne@68: one. But while doing so, its previous contents is put apart in jpayne@68: a special place, known as the kill ring. The command w jpayne@68: (po-kill-ring-save-msgstr) has also the effect of taking a jpayne@68: copy of the translation onto the kill ring, but it otherwise leaves jpayne@68: the entry alone, and does not remove the translation from the jpayne@68: entry. Both commands use exactly the Emacs kill ring, which is shared jpayne@68: between buffers, and which is well known already to Emacs lovers. jpayne@68:

jpayne@68:

The translator may use k or w many times in the course jpayne@68: of her work, as the kill ring may hold several saved translations. jpayne@68: From the kill ring, strings may later be reinserted in various jpayne@68: Emacs buffers. In particular, the kill ring may be used for moving jpayne@68: translation strings between different entries of a single PO file jpayne@68: buffer, or if the translator is handling many such buffers at once, jpayne@68: even between PO files. jpayne@68:

jpayne@68:

To facilitate exchanges with buffers which are not in PO mode, the jpayne@68: translation string put on the kill ring by the k command is fully jpayne@68: unquoted before being saved: external quotes are removed, multi-line jpayne@68: strings are concatenated, and backslash escaped sequences are turned jpayne@68: into their corresponding characters. In the special case of obsolete jpayne@68: entries, the translation is also uncommented prior to saving. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The command y (po-yank-msgstr) completely replaces the jpayne@68: translation of the current entry by a string taken from the kill ring. jpayne@68: Following Emacs terminology, we then say that the replacement jpayne@68: string is yanked into the PO file buffer. jpayne@68: See (emacs)Yanking section `Yanking' in The Emacs Editor. jpayne@68: The first time y is used, the translation receives the value of jpayne@68: the most recent addition to the kill ring. If y is typed once jpayne@68: again, immediately, without intervening keystrokes, the translation jpayne@68: just inserted is taken away and replaced by the second most recent jpayne@68: addition to the kill ring. By repeating y many times in a row, jpayne@68: the translator may travel along the kill ring for saved strings, jpayne@68: until she finds the string she really wanted. jpayne@68:

jpayne@68:

When a string is yanked into a PO file entry, it is fully and jpayne@68: automatically requoted for complying with the format PO files should jpayne@68: have. Further, if the entry is obsolete, PO mode then appropriately jpayne@68: push the inserted string inside comments. Once again, translators jpayne@68: should not burden themselves with quoting considerations besides, of jpayne@68: course, the necessity of the translated string itself respective to jpayne@68: the program using it. jpayne@68:

jpayne@68:

Note that k or w are not the only commands pushing strings jpayne@68: on the kill ring, as almost any PO mode command replacing translation jpayne@68: strings (or the translator comments) automatically saves the old string jpayne@68: on the kill ring. The main exceptions to this general rule are the jpayne@68: yanking commands themselves. jpayne@68:

jpayne@68: jpayne@68:

To better illustrate the operation of killing and yanking, let's jpayne@68: use an actual example, taken from a common situation. When the jpayne@68: programmer slightly modifies some string right in the program, his jpayne@68: change is later reflected in the PO file by the appearance jpayne@68: of a new untranslated entry for the modified string, and the fact jpayne@68: that the entry translating the original or unmodified string becomes jpayne@68: obsolete. In many cases, the translator might spare herself some work jpayne@68: by retrieving the unmodified translation from the obsolete entry, jpayne@68: then initializing the untranslated entry msgstr field with jpayne@68: this retrieved translation. Once this done, the obsolete entry is jpayne@68: not wanted anymore, and may be safely deleted. jpayne@68:

jpayne@68:

When the translator finds an untranslated entry and suspects that a jpayne@68: slight variant of the translation exists, she immediately uses m jpayne@68: to mark the current entry location, then starts chasing obsolete jpayne@68: entries with o, hoping to find some translation corresponding jpayne@68: to the unmodified string. Once found, she uses the <DEL> command jpayne@68: for deleting the obsolete entry, knowing that <DEL> also kills jpayne@68: the translation, that is, pushes the translation on the kill ring. jpayne@68: Then, r returns to the initial untranslated entry, and y jpayne@68: then yanks the saved translation right into the msgstr jpayne@68: field. The translator is then free to use <RET> for fine jpayne@68: tuning the translation contents, and maybe to later use u, jpayne@68: then m again, for going on with the next untranslated string. jpayne@68:

jpayne@68:

When some sequence of keys has to be typed over and over again, the jpayne@68: translator may find it useful to become better acquainted with the Emacs jpayne@68: capability of learning these sequences and playing them back under request. jpayne@68: See (emacs)Keyboard Macros section `Keyboard Macros' in The Emacs Editor. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.10 Modifying Comments

jpayne@68: jpayne@68:

Any translation work done seriously will raise many linguistic jpayne@68: difficulties, for which decisions have to be made, and the choices jpayne@68: further documented. These documents may be saved within the jpayne@68: PO file in form of translator comments, which the translator jpayne@68: is free to create, delete, or modify at will. These comments may jpayne@68: be useful to herself when she returns to this PO file after a while. jpayne@68:

jpayne@68:

Comments not having whitespace after the initial ‘#’, for example, jpayne@68: those beginning with ‘#.’ or ‘#:’, are not translator jpayne@68: comments, they are exclusively created by other gettext tools. jpayne@68: So, the commands below will never alter such system added comments, jpayne@68: they are not meant for the translator to modify. See section The Format of PO Files. jpayne@68:

jpayne@68:

The following commands are somewhat similar to those modifying translations, jpayne@68: so the general indications given for those apply here. See section Modifying Translations. jpayne@68:

jpayne@68:
jpayne@68:
#
jpayne@68:
jpayne@68:

Interactively edit the translator comments (po-edit-comment). jpayne@68:

jpayne@68:
jpayne@68:
K
jpayne@68:
jpayne@68:

Save the translator comments on the kill ring, and delete it jpayne@68: (po-kill-comment). jpayne@68:

jpayne@68:
jpayne@68:
W
jpayne@68:
jpayne@68:

Save the translator comments on the kill ring, without deleting it jpayne@68: (po-kill-ring-save-comment). jpayne@68:

jpayne@68:
jpayne@68:
Y
jpayne@68:
jpayne@68:

Replace the translator comments, taking the new from the kill ring jpayne@68: (po-yank-comment). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68:

These commands parallel PO mode commands for modifying the translation jpayne@68: strings, and behave much the same way as they do, except that they handle jpayne@68: this part of PO file comments meant for translator usage, rather jpayne@68: than the translation strings. So, if the descriptions given below are jpayne@68: slightly succinct, it is because the full details have already been given. jpayne@68: See section Modifying Translations. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The command # (po-edit-comment) opens a new Emacs window jpayne@68: containing a copy of the translator comments on the current PO file entry. jpayne@68: If there are no such comments, PO mode understands that the translator wants jpayne@68: to add a comment to the entry, and she is presented with an empty screen. jpayne@68: Comment marks (#) and the space following them are automatically jpayne@68: removed before edition, and reinstated after. For translator comments jpayne@68: pertaining to obsolete entries, the uncommenting and recommenting operations jpayne@68: are done twice. Once in the editing window, the keys C-c C-c jpayne@68: allow the translator to tell she is finished with editing the comment. jpayne@68: See section Details of Sub Edition, for further details. jpayne@68:

jpayne@68: jpayne@68:

Functions found on po-subedit-mode-hook, if any, are executed after jpayne@68: the string has been inserted in the edit buffer. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The command K (po-kill-comment) gets rid of all jpayne@68: translator comments, while saving those comments on the kill ring. jpayne@68: The command W (po-kill-ring-save-comment) takes jpayne@68: a copy of the translator comments on the kill ring, but leaves jpayne@68: them undisturbed in the current entry. The command Y jpayne@68: (po-yank-comment) completely replaces the translator comments jpayne@68: by a string taken at the front of the kill ring. When this command jpayne@68: is immediately repeated, the comments just inserted are withdrawn, jpayne@68: and replaced by other strings taken along the kill ring. jpayne@68:

jpayne@68:

On the kill ring, all strings have the same nature. There is no jpayne@68: distinction between translation strings and translator jpayne@68: comments strings. So, for example, let's presume the translator jpayne@68: has just finished editing a translation, and wants to create a new jpayne@68: translator comment to document why the previous translation was jpayne@68: not good, just to remember what was the problem. Foreseeing that she jpayne@68: will do that in her documentation, the translator may want to quote jpayne@68: the previous translation in her translator comments. To do so, she jpayne@68: may initialize the translator comments with the previous translation, jpayne@68: still at the head of the kill ring. Because editing already pushed the jpayne@68: previous translation on the kill ring, she merely has to type M-w jpayne@68: prior to #, and the previous translation will be right there, jpayne@68: all ready for being introduced by some explanatory text. jpayne@68:

jpayne@68:

On the other hand, presume there are some translator comments already jpayne@68: and that the translator wants to add to those comments, instead jpayne@68: of wholly replacing them. Then, she should edit the comment right jpayne@68: away with #. Once inside the editing window, she can use the jpayne@68: regular Emacs commands C-y (yank) and M-y jpayne@68: (yank-pop) to get the previous translation where she likes. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.11 Details of Sub Edition

jpayne@68: jpayne@68:

The PO subedit minor mode has a few peculiarities worth being described jpayne@68: in fuller detail. It installs a few commands over the usual editing set jpayne@68: of Emacs, which are described below. jpayne@68:

jpayne@68:
jpayne@68:
C-c C-c
jpayne@68:
jpayne@68:

Complete edition (po-subedit-exit). jpayne@68:

jpayne@68:
jpayne@68:
C-c C-k
jpayne@68:
jpayne@68:

Abort edition (po-subedit-abort). jpayne@68:

jpayne@68:
jpayne@68:
C-c C-a
jpayne@68:
jpayne@68:

Consult auxiliary PO files (po-subedit-cycle-auxiliary). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The window's contents represents a translation for a given message, jpayne@68: or a translator comment. The translator may modify this window to jpayne@68: her heart's content. Once this is done, the command C-c C-c jpayne@68: (po-subedit-exit) may be used to return the edited translation into jpayne@68: the PO file, replacing the original translation, even if it moved out of jpayne@68: sight or if buffers were switched. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

If the translator becomes unsatisfied with her translation or comment, jpayne@68: to the extent she prefers keeping what was existent prior to the jpayne@68: <RET> or # command, she may use the command C-c C-k jpayne@68: (po-subedit-abort) to merely get rid of edition, while preserving jpayne@68: the original translation or comment. Another way would be for her to exit jpayne@68: normally with C-c C-c, then type U once for undoing the jpayne@68: whole effect of last edition. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The command C-c C-a (po-subedit-cycle-auxiliary) jpayne@68: allows for glancing through translations jpayne@68: already achieved in other languages, directly while editing the current jpayne@68: translation. This may be quite convenient when the translator is fluent jpayne@68: at many languages, but of course, only makes sense when such completed jpayne@68: auxiliary PO files are already available to her (see section Consulting Auxiliary PO Files). jpayne@68:

jpayne@68:

Functions found on po-subedit-mode-hook, if any, are executed after jpayne@68: the string has been inserted in the edit buffer. jpayne@68:

jpayne@68:

While editing her translation, the translator should pay attention to not jpayne@68: inserting unwanted <RET> (newline) characters at the end of jpayne@68: the translated string if those are not meant to be there, or to removing jpayne@68: such characters when they are required. Since these characters are not jpayne@68: visible in the editing buffer, they are easily introduced by mistake. jpayne@68: To help her, <RET> automatically puts the character < jpayne@68: at the end of the string being edited, but this < is not really jpayne@68: part of the string. On exiting the editing window with C-c C-c, jpayne@68: PO mode automatically removes such < and all whitespace added after jpayne@68: it. If the translator adds characters after the terminating <, it jpayne@68: looses its delimiting property and integrally becomes part of the string. jpayne@68: If she removes the delimiting <, then the edited string is taken jpayne@68: as is, with all trailing newlines, even if invisible. Also, if jpayne@68: the translated string ought to end itself with a genuine <, then jpayne@68: the delimiting < may not be removed; so the string should appear, jpayne@68: in the editing window, as ending with two < in a row. jpayne@68:

jpayne@68: jpayne@68:

When a translation (or a comment) is being edited, the translator may move jpayne@68: the cursor back into the PO file buffer and freely move to other entries, jpayne@68: browsing at will. If, with an edition pending, the translator wanders in the jpayne@68: PO file buffer, she may decide to start modifying another entry. Each entry jpayne@68: being edited has its own subedit buffer. It is possible to simultaneously jpayne@68: edit the translation and the comment of a single entry, or to jpayne@68: edit entries in different PO files, all at once. Typing <RET> jpayne@68: on a field already being edited merely resumes that particular edit. Yet, jpayne@68: the translator should better be comfortable at handling many Emacs windows! jpayne@68:

jpayne@68: jpayne@68:

Pending subedits may be completed or aborted in any order, regardless jpayne@68: of how or when they were started. When many subedits are pending and the jpayne@68: translator asks for quitting the PO file (with the q command), subedits jpayne@68: are automatically resumed one at a time, so she may decide for each of them. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.12 C Sources Context

jpayne@68: jpayne@68:

PO mode is particularly powerful when used with PO files jpayne@68: created through GNU gettext utilities, as those utilities jpayne@68: insert special comments in the PO files they generate. jpayne@68: Some of these special comments relate the PO file entry to jpayne@68: exactly where the untranslated string appears in the program sources. jpayne@68:

jpayne@68:

When the translator gets to an untranslated entry, she is fairly jpayne@68: often faced with an original string which is not as informative as jpayne@68: it normally should be, being succinct, cryptic, or otherwise ambiguous. jpayne@68: Before choosing how to translate the string, she needs to understand jpayne@68: better what the string really means and how tight the translation has jpayne@68: to be. Most of the time, when problems arise, the only way left to make jpayne@68: her judgment is looking at the true program sources from where this jpayne@68: string originated, searching for surrounding comments the programmer jpayne@68: might have put in there, and looking around for helping clues of jpayne@68: any kind. jpayne@68:

jpayne@68:

Surely, when looking at program sources, the translator will receive jpayne@68: more help if she is a fluent programmer. However, even if she is jpayne@68: not versed in programming and feels a little lost in C code, the jpayne@68: translator should not be shy at taking a look, once in a while. jpayne@68: It is most probable that she will still be able to find some of the jpayne@68: hints she needs. She will learn quickly to not feel uncomfortable jpayne@68: in program code, paying more attention to programmer's comments, jpayne@68: variable and function names (if he dared choosing them well), and jpayne@68: overall organization, than to the program code itself. jpayne@68:

jpayne@68: jpayne@68:

The following commands are meant to help the translator at getting jpayne@68: program source context for a PO file entry. jpayne@68:

jpayne@68:
jpayne@68:
s
jpayne@68:
jpayne@68:

Resume the display of a program source context, or cycle through them jpayne@68: (po-cycle-source-reference). jpayne@68:

jpayne@68:
jpayne@68:
M-s
jpayne@68:
jpayne@68:

Display of a program source context selected by menu jpayne@68: (po-select-source-reference). jpayne@68:

jpayne@68:
jpayne@68:
S
jpayne@68:
jpayne@68:

Add a directory to the search path for source files jpayne@68: (po-consider-source-path). jpayne@68:

jpayne@68:
jpayne@68:
M-S
jpayne@68:
jpayne@68:

Delete a directory from the search path for source files jpayne@68: (po-ignore-source-path). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

The commands s (po-cycle-source-reference) and M-s jpayne@68: (po-select-source-reference) both open another window displaying jpayne@68: some source program file, and already positioned in such a way that jpayne@68: it shows an actual use of the string to be translated. By doing jpayne@68: so, the command gives source program context for the string. But if jpayne@68: the entry has no source context references, or if all references jpayne@68: are unresolved along the search path for program sources, then the jpayne@68: command diagnoses this as an error. jpayne@68:

jpayne@68:

Even if s (or M-s) opens a new window, the cursor stays jpayne@68: in the PO file window. If the translator really wants to jpayne@68: get into the program source window, she ought to do it explicitly, jpayne@68: maybe by using command O. jpayne@68:

jpayne@68:

When s is typed for the first time, or for a PO file entry which jpayne@68: is different of the last one used for getting source context, then the jpayne@68: command reacts by giving the first context available for this entry, jpayne@68: if any. If some context has already been recently displayed for the jpayne@68: current PO file entry, and the translator wandered off to do other jpayne@68: things, typing s again will merely resume, in another window, jpayne@68: the context last displayed. In particular, if the translator moved jpayne@68: the cursor away from the context in the source file, the command will jpayne@68: bring the cursor back to the context. By using s many times jpayne@68: in a row, with no other commands intervening, PO mode will cycle to jpayne@68: the next available contexts for this particular entry, getting back jpayne@68: to the first context once the last has been shown. jpayne@68:

jpayne@68:

The command M-s behaves differently. Instead of cycling through jpayne@68: references, it lets the translator choose a particular reference among jpayne@68: many, and displays that reference. It is best used with completion, jpayne@68: if the translator types <TAB> immediately after M-s, in jpayne@68: response to the question, she will be offered a menu of all possible jpayne@68: references, as a reminder of which are the acceptable answers. jpayne@68: This command is useful only where there are really many contexts jpayne@68: available for a single string to translate. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

Program source files are usually found relative to where the PO jpayne@68: file stands. As a special provision, when this fails, the file is jpayne@68: also looked for, but relative to the directory immediately above it. jpayne@68: Those two cases take proper care of most PO files. However, it might jpayne@68: happen that a PO file has been moved, or is edited in a different jpayne@68: place than its normal location. When this happens, the translator jpayne@68: should tell PO mode in which directory normally sits the genuine PO jpayne@68: file. Many such directories may be specified, and all together, they jpayne@68: constitute what is called the search path for program sources. jpayne@68: The command S (po-consider-source-path) is used to interactively jpayne@68: enter a new directory at the front of the search path, and the command jpayne@68: M-S (po-ignore-source-path) is used to select, with completion, jpayne@68: one of the directories she does not want anymore on the search path. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.3.13 Consulting Auxiliary PO Files

jpayne@68: jpayne@68:

PO mode is able to help the knowledgeable translator, being fluent in jpayne@68: many languages, at taking advantage of translations already achieved jpayne@68: in other languages she just happens to know. It provides these other jpayne@68: language translations as additional context for her own work. Moreover, jpayne@68: it has features to ease the production of translations for many languages jpayne@68: at once, for translators preferring to work in this way. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

An auxiliary PO file is an existing PO file meant for the same jpayne@68: package the translator is working on, but targeted to a different mother jpayne@68: tongue language. Commands exist for declaring and handling auxiliary jpayne@68: PO files, and also for showing contexts for the entry under work. jpayne@68:

jpayne@68:

Here are the auxiliary file commands available in PO mode. jpayne@68:

jpayne@68:
jpayne@68:
a
jpayne@68:
jpayne@68:

Seek auxiliary files for another translation for the same entry jpayne@68: (po-cycle-auxiliary). jpayne@68:

jpayne@68:
jpayne@68:
C-c C-a
jpayne@68:
jpayne@68:

Switch to a particular auxiliary file (po-select-auxiliary). jpayne@68:

jpayne@68:
jpayne@68:
A
jpayne@68:
jpayne@68:

Declare this PO file as an auxiliary file (po-consider-as-auxiliary). jpayne@68:

jpayne@68:
jpayne@68:
M-A
jpayne@68:
jpayne@68:

Remove this PO file from the list of auxiliary files jpayne@68: (po-ignore-as-auxiliary). jpayne@68:

jpayne@68:
jpayne@68:
jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

Command A (po-consider-as-auxiliary) adds the current jpayne@68: PO file to the list of auxiliary files, while command M-A jpayne@68: (po-ignore-as-auxiliary just removes it. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The command a (po-cycle-auxiliary) seeks all auxiliary PO jpayne@68: files, round-robin, searching for a translated entry in some other language jpayne@68: having an msgid field identical as the one for the current entry. jpayne@68: The found PO file, if any, takes the place of the current PO file in jpayne@68: the display (its window gets on top). Before doing so, the current PO jpayne@68: file is also made into an auxiliary file, if not already. So, a jpayne@68: in this newly displayed PO file will seek another PO file, and so on, jpayne@68: so repeating a will eventually yield back the original PO file. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

The command C-c C-a (po-select-auxiliary) asks the translator jpayne@68: for her choice of a particular auxiliary file, with completion, and jpayne@68: then switches to that selected PO file. The command also checks if jpayne@68: the selected file has an msgid field identical as the one for jpayne@68: the current entry, and if yes, this entry becomes current. Otherwise, jpayne@68: the cursor of the selected file is left undisturbed. jpayne@68:

jpayne@68:

For all this to work fully, auxiliary PO files will have to be normalized, jpayne@68: in that way that msgid fields should be written exactly jpayne@68: the same way. It is possible to write msgid fields in various jpayne@68: ways for representing the same string, different writing would break the jpayne@68: proper behaviour of the auxiliary file commands of PO mode. This is not jpayne@68: expected to be much a problem in practice, as most existing PO files have jpayne@68: their msgid entries written by the same GNU gettext tools. jpayne@68:

jpayne@68: jpayne@68:

However, PO files initially created by PO mode itself, while marking jpayne@68: strings in source files, are normalised differently. So are PO jpayne@68: files resulting of the ‘M-x normalize’ command. Until these jpayne@68: discrepancies between PO mode and other GNU gettext tools get jpayne@68: fully resolved, the translator should stay aware of normalisation issues. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.4 Using Translation Compendia

jpayne@68: jpayne@68:

A compendium is a special PO file containing a set of jpayne@68: translations recurring in many different packages. The translator can jpayne@68: use gettext tools to build a new compendium, to add entries to her jpayne@68: compendium, and to initialize untranslated entries, or to update jpayne@68: already translated entries, from translations kept in the compendium. jpayne@68:

jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.4.1 Creating Compendia

jpayne@68: jpayne@68:

Basically every PO file consisting of translated entries only can be jpayne@68: declared as a valid compendium. Often the translator wants to have jpayne@68: special compendia; let's consider two cases: concatenating PO jpayne@68: files and extracting a message subset from a PO file. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

8.4.1.1 Concatenate PO Files

jpayne@68: jpayne@68:

To concatenate several valid PO files into one compendium file you can jpayne@68: use ‘msgcomm’ or ‘msgcat’ (the latter preferred): jpayne@68:

jpayne@68:
 
msgcat -o compendium.po file1.po file2.po
jpayne@68: 
jpayne@68: jpayne@68:

By default, msgcat will accumulate divergent translations jpayne@68: for the same string. Those occurrences will be marked as fuzzy jpayne@68: and highly visible decorated; calling msgcat on jpayne@68: ‘file1.po’: jpayne@68:

jpayne@68:
 
#: src/hello.c:200
jpayne@68: #, c-format
jpayne@68: msgid "Report bugs to <%s>.\n"
jpayne@68: msgstr "Comunicar `bugs' a <%s>.\n"
jpayne@68: 
jpayne@68: jpayne@68:

and ‘file2.po’: jpayne@68:

jpayne@68:
 
#: src/bye.c:100
jpayne@68: #, c-format
jpayne@68: msgid "Report bugs to <%s>.\n"
jpayne@68: msgstr "Comunicar \"bugs\" a <%s>.\n"
jpayne@68: 
jpayne@68: jpayne@68:

will result in: jpayne@68:

jpayne@68:
 
#: src/hello.c:200 src/bye.c:100
jpayne@68: #, fuzzy, c-format
jpayne@68: msgid "Report bugs to <%s>.\n"
jpayne@68: msgstr ""
jpayne@68: "#-#-#-#-#  file1.po  #-#-#-#-#\n"
jpayne@68: "Comunicar `bugs' a <%s>.\n"
jpayne@68: "#-#-#-#-#  file2.po  #-#-#-#-#\n"
jpayne@68: "Comunicar \"bugs\" a <%s>.\n"
jpayne@68: 
jpayne@68: jpayne@68:

The translator will have to resolve this “conflict” manually; she jpayne@68: has to decide whether the first or the second version is appropriate jpayne@68: (or provide a new translation), to delete the “marker lines”, and jpayne@68: finally to remove the fuzzy mark. jpayne@68:

jpayne@68:

If the translator knows in advance the first found translation of a jpayne@68: message is always the best translation she can make use to the jpayne@68: ‘--use-first’ switch: jpayne@68:

jpayne@68:
 
msgcat --use-first -o compendium.po file1.po file2.po
jpayne@68: 
jpayne@68: jpayne@68:

A good compendium file must not contain fuzzy or untranslated jpayne@68: entries. If input files are “dirty” you must preprocess the input jpayne@68: files or postprocess the result using ‘msgattrib --translated --no-fuzzy’. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

8.4.1.2 Extract a Message Subset from a PO File

jpayne@68: jpayne@68:

Nobody wants to translate the same messages again and again; thus you jpayne@68: may wish to have a compendium file containing ‘getopt.c’ messages. jpayne@68:

jpayne@68:

To extract a message subset (e.g., all ‘getopt.c’ messages) from an jpayne@68: existing PO file into one compendium file you can use ‘msggrep’: jpayne@68:

jpayne@68:
 
msggrep --location src/getopt.c -o compendium.po file.po
jpayne@68: 
jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.4.2 Using Compendia

jpayne@68: jpayne@68:

You can use a compendium file to initialize a translation from scratch jpayne@68: or to update an already existing translation. jpayne@68:

jpayne@68: jpayne@68: jpayne@68:

8.4.2.1 Initialize a New Translation File

jpayne@68: jpayne@68:

Since a PO file with translations does not exist the translator can jpayne@68: merely use ‘/dev/null’ to fake the “old” translation file. jpayne@68:

jpayne@68:
 
msgmerge --compendium compendium.po -o file.po /dev/null file.pot
jpayne@68: 
jpayne@68: jpayne@68: jpayne@68: jpayne@68:

8.4.2.2 Update an Existing Translation File

jpayne@68: jpayne@68:

Concatenate the compendium file(s) and the existing PO, merge the jpayne@68: result with the POT file and remove the obsolete entries (optional, jpayne@68: here done using ‘msgattrib’): jpayne@68:

jpayne@68:
 
msgcat --use-first -o update.po compendium1.po compendium2.po file.po
jpayne@68: msgmerge update.po file.pot | msgattrib --no-obsolete > file.po
jpayne@68: 
jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68: jpayne@68:
[ << ][ >> ]           [Top][Contents][Index][ ? ]
jpayne@68:

jpayne@68: jpayne@68: This document was generated by Bruno Haible on February, 21 2024 using texi2html 1.78a. jpayne@68: jpayne@68:
jpayne@68: jpayne@68:

jpayne@68: jpayne@68: