Translate Texinfo files using po4a
Texinfo
Texinfo is a
brilliant hypertext system that predates HTML. You access it with info, which
is a text mode application. The content consists of a number of nodes.
Each node is an information element. You access the nodes through menus,
hyperlinks, and indices. Also you can "walk" through a info file with
keys like [ and ]. See info info.
Leveraging the power of TeX, Texinfo files can be used to produce gorgeous looking PDF files, like the GNU books. Compared to generating PDF files from LaTeX, generating PDF files from Texinfo is incredible fast.
po4a
The po4a (PO for anything) eases documentation translations and their maintenance.
This is what this website says:
It extracts the translatable material from the original document, and places it into a PO file that is adapted to the translation process. Once this PO file is updated by the translator, po4a re-injects the translation into the structure of the original document to generate a translated document.
po4a supports several documentation formats, including Texinfo.
Workflow
In general, the workflow is something like this:
- Create a PO-file from the orginal Texinfo file.
- Add the translations to the PO-file.
- Generate a translated Texinfo file.
- Use the translated Texinfo file like any other Texinfo file, e.g., create an Info file and a PDF with it.
When the original Texinfo file changes:
- Update the PO-file.
- Add or change translations where needed.
- Generate a new translated Texinfo file.
Store the original Texinfo file
In order for the update of the PO-file to work, you'll need both the original Texinfo file as well as the new version of the Texinfo file. It is therefor important to keep a copy of the original Texinfo file.
In the examples below, two versions of the Texinfo file are mentioned:
testinfo-v1.texi: this represents the original file to be translated.testinfo-v2.texi: this represents a new version of the file to be translated.
Create a PO-file
To create the PO-file from the original Texinfo file, using the following command.
po4a-updatepo \
--format texinfo \
--master testinfo-v1.texi \
--po testinfo.po
Replace testinfo-v1.texi with the name of the original Texinfo file.
Replace testinfo.po with the desired name of the PO-file.
Translating the PO-file
The PO-file contains a lot of strings and paragraphs to be translated.
Translating strings
The entry for a string in the PO-file is something like this:
#. type: menuentry
#: testinfo-v2.texi:30
msgid "Fundamental stuff"
msgstr ""
The first line containing the type differs for the roles of the string in the Texinfo document.
- The line starting with
msgidis a line to be translated. - The line starting with
msgstris where the translation must be paced.
Translating paragraphs
The entry for a paragraph looks something likes this:
#. type: Plain text
#: testinfo.texi:24
msgid ""
"In this chapter I define the concepts that will be used throughout the rest "
"of the document. Moreover, measures of efficiencies as well as bounds of "
"complexity will be introduced."
msgstr ""
The translation of the paragraph must be placed right below the line starting
with msgstr:
#. type: Plain text
#: testinfo.texi:24
msgid ""
"In this chapter I define the concepts that will be used throughout the rest "
"of the document. Moreover, measures of efficiencies as well as bounds of "
"complexity will be introduced."
msgstr ""
"In dit hoofdstuk definieer ik de concepten die gebruikt worden in de rest "
" ... "
The lines in the translated paragraph start with a double quote (") and
end with a space and a double quote.
The last line of the translated paragraph ends with a double quote without a space, just like the last line of the paragraph in the original language.
(Example text copied from Writing Documentation, Part IV: Texinfo on Linux Gazette.)
Texinfo commands in paragraphs
Texinfo commands require special formatting of the lines.
For this, we make use of the \n formatting in the strings and paragraphs:
String example:
#. type: smallexample
#: testinfo.texi:1421
#, no-wrap
msgid "Original line to be translated\n"
msgstr "Translated line\n"
Sometimes po4a has recognized the Texinfo command and treated as such, which can be seen at the type of the PO-element, as here above.
Other times the Texinfo command appears inside a paragraphs to be translated.
Here we make uses of careful \n formatting in the translated paragraph:
" ... "
"Some text inside the paragraph\n"
"@ifnottex \n@xref{Some-ref}.\n@end ifnottex\n"
"@iftex \n@xref{Some-other-ref}. \n@end iftex\n"
"Some other text inside the paragraph. "
" ... "
Not: the \n is directly followed by a double quote, without a space before
the double quote.
Update a PO-file
When later the original Texinfo file gets an update, we have to reflect those changes in our translated file.
Here's how to update the PO-file. Note the use of the name of the new
version of the Texinfo file (testinfo-v2.texi) and the name of original
file the PO-file was created with (testinfo-v1.texi).
po4a-updatepo \
--format texinfo \
--master testinfo-v2.texi \
--previous testinfo-v1.texi \
--po testinfo.po
The PO-file in the command above is the same file we created in the first step and has been filled with our translations.
How to recognize changes in the updated PO-file
After running the po4a-updatepo command, the PO-file with our translations
is changed. po4a has merged the changes into it.
This means we must go through the PO-file again, to add or change translations. Below follows how to recognize new text, deleted text and changed text.
New text
New lines and paragraphs can be recognized by an empty msgstr. Example:
msgid "Very new chapter"
msgstr ""
Deleted text
Deleted text can be recognized by a pound char (#) at the start of the msgid and msgstr lines. Example:
#~ msgid "This line will be deleted in the next version."
#~ msgstr "Deze regel wordt in de volgende versie verwijderd."
Changed lines
Changed lines are preceded by a line with #| msgid at the start. Example:
#| msgid "This line will be changed in the next version."
msgid "This line is now changed in this version."
msgstr "Deze regel wordt in de nieuwe vesie gewijzigd."
- The line starting with
#| msgidis the line as it was in the previous version of the Texinfo file. - The line starting with
msgidis the line as it is in the new version of the Texinfo file. - The
msgstrcontains the previous translation, is no longer valid and must be changed into a translation of the new text.
Create translated texinfo file
po4a-translate \
--format texinfo \
--master testinfo-v2.texi \
--po testinfo.po \
--localized testinfo-nl.texi
Here, the input file testinfo-v2.texi is used as an example. The
output file is testinfo-nl.texi, the Texinfo file that is generated
using the PO-file and the Texinfo file it was created from.
For convenience, create a Makefile for this:
testinfo-nl.texi: testinfo.po
po4a-translate \
--format texinfo \
--master testinfo-v2.texi \
--po testinfo.po \
--localized testinfo-nl.texi
When only a part of the translation has been done, po4a will refuse
to generate the Texinfo output file. This can be configured by using
the switch -k, e.g., -k 30 to generate an output file
when at least 30% of the translation has been done. The default is
80%.
Generate a PDF file from the texinfo file with the translation
makeinfo --pdf testinfo-nl.texi
To add this to the Makefile, you could do something like this:
testinfo-nl.pdf: testinfo-nl.texi testinfo.po
makeinfo --pdf testinfo-nl.texi
testinfo-nl.texi: testinfo-nl.po
po4a-translate \
--format texinfo \
--master testinfo.texi \
--po testinfo.po \
--localized testinfo-nl.texi
When there are some non fatal errors, the makeinfo command can be extended
with the switch ---force to generate an output file even when
there are errors.
Editing PO-files with Emacs
Here follow some tips for working in Emacs.
Spell check
When working on the PO file and inserting translations, the file will contain text in two languages, the original language and the language we are translating to.
An easy way to spellcheck a single entry is by
marking it as a region and run M-x flyspell-region.
First, set the dictionary to be used with M-x ispell-change-dictionary.
Flyspell-mode
Flyspell-mode checks your spelling while you type. Just enable it
--after having changed to the right dictionary-- with: ````
M-x flyspell-mode
Curly braces
Texinfo uses a lot of curly braces. Make live easier and enable
electric-pair-mode:
M-x electric-pair-mode
This will let Emacs insert the closing curly brace for you.
.dir-locals.el
Set several options automagically with a file named
.dir-locals.el in your directory, for example:
((nil . ((ispell-local-dictionary . "nl")
(abbrev-mode . t)
(eval . (flyspell-mode))
(eval . (electric-pair-mode))
(eval . (company-mode)))))
Where nl is the Dutch dictionary.
View local info file in Info-mode
To open in a local info file in info-mode, use C-u C-h i.
Working with paragraphs
For me, this works convenient:
- First, write the paragraph with the translation just as normal text.
- Next, when needed, correct the paragraph using
fill-paragraph, normally withM-q. - Third, surround each line with double quotes, with a space before the double at the end of the line.
- Make sure the last line just ends with a double quote, not a space and double quote.
Some small Elisp functions can help:
(defun my/quote-region ()
"Surround each line in the region with quotes."
(interactive)
(save-excursion
(save-restriction
(narrow-to-region (region-beginning) (region-end))
(goto-char (point-min))
(replace-regexp "^" "\"")
(goto-char (point-min))
(replace-regexp "$" " \""))))
(defun my/unquote-region ()
"Remove quotes around the lines in the region."
(interactive)
(save-excursion
(save-restriction
(narrow-to-region (region-beginning) (region-end))
(goto-char (point-min))
(replace-regexp "^\"" "")
(goto-char (point-min))
(replace-regexp "\"$" ""))))
(defun my/unquote-region-and-fill-paragraph ()
"Remove quotes around the lines in the region and fill-paragraph"
(interactive)
(save-excursion
(save-restriction
(narrow-to-region (region-beginning) (region-end))
(goto-char (point-min))
(replace-regexp "^\"" "")
(goto-char (point-min))
(replace-regexp "\"$" "")
(goto-char (point-min))
(fill-paragraph))))
Example key bindings:
(define-key global-map (kbd "C-c n q") #'my/quote-region)
(define-key global-map (kbd "C-c n Q") #'my/unquote-region)
(define-key global-map (kbd "C-c n m") #'my/unquote-region-and-fill-paragraph)
The function my/quote-region can be improved: it leaves a space before the double quote on the last line.
Webrings
100% made with ♥ by a human — no cookies, no trackers.
Proud member of the 250kb.club,
the no-JS.club,
the Blogroll.Club,
and the Bukmark.Club.
Don’t let a billionaire’s algorithm control what you read — use an RSS feed reader.
Most recent pages All tags Sitemap RSS of Gophersite
