LOCALE:...:MAN.3PM(1)
πΈ NAME πΈ
Locale::Po4a::Man β this is the LOCALE:...:MAN.3PM(1) manual page (aka MAN.3PM(1)) from User Contributed Perl Documentation, and it's all about converting manual pages from/to PO files. π
π DESCRIPTION π
Okay so the po4a project β PO for anything β has one big goal: make translations easier, and honestly even more importantly, make maintaining those translations easier. It does that by using gettext tools in places where people didn't really expect them, like documentation. β¨
Locale::Po4a::Man is the module that helps you translate documentation written in nroff format β yes, the language of manual pages β into other [human] languages. π
π¦ TRANSLATING WITH PO4A::MAN π¦
This module tries pretty hard to make a translator's life easier, no cap. The text it shows to translators is not a verbatim copy of what's in the man page. The cruder, messier parts of nroff are hidden away so translators literally can't mess them up. π
π Text wrapping π
Unindented paragraphs get automatically rewrapped for the translator. This can cause some minor differences in the generated output, because the rewrapping rules groff uses aren't very clear β sometimes two spaces after a parenthesis are preserved, for example. π
Anyway, the difference is only about where the extra spaces land in a wrapped paragraph, and I think it's worth it. π«Ά
β¨ Font specification β¨
The first change is all about font change specifications. In nroff there are several different ways to say whether a word should be small, bold, or italic. In the text to translate, there's only one way, borrowed from POD β the Perl online documentation format β and it's giving iconic:
I<text>β italic text, equivalent to\fItext\fPor".I text"B<text>β bold text, equivalent to\fBtext\fPor".B text"R<text>β roman text, equivalent to\fRtext\fPCW<text>β constant width text, equivalent to\f(CWtext\fPor".CW text"
π Quick heads-up, bestie: the CW face is not available for all groff devices. It is not recommended to use it. It is provided for your convenience.
π Automatic characters transliteration π
po4a automatically transliterates some characters to make translation β or reviewing a translation β easier. Here's the list, bestie:
- hyphens β Hyphens (
-) and minus signs (\-) in man pages are all transliterated as simple dashes (-) in the PO file. Then all dashes are transliterated into roff minus signs (\-) when the translation is inserted into the output document. Translators can force a hyphen by using the roff glyph'\[hy]'in their translations. π - non-breaking spaces β Translators can use non-breaking spaces in their translations. These non-breaking spaces (
0xA0in latin1) will be transliterated into a roff non-breaking space ('\ '). π¦ - quotes transliterations β These two quote chars:
`` and ''
are respectively transliterated into \*(lq and \*(rq. To avoid these transliterations, translators can insert a zero width roff character (i.e., using \& or '\&' respectively). β¨
π Putting '<' and '>' in translations π
Since these chars are used to delimit parts under font modification, you can't use them verbatim. Use E<lt> and E<gt> instead β as in POD, one more time. π
π OPTIONS ACCEPTED BY THIS MODULE π
These are this module's particular options, bestie:
debugβ Activate debugging for some internal mechanisms of this module. Use the source to see which parts can be debugged. πverboseβ Increase verbosity. π£οΈgroff_codeβ This option controls the behavior of the module when it encounters a.de,.ie, or.ifsection. It can take the following values:failβ This is the default value. The module will fail when a.de,.ie, or.ifsection is encountered. πverbatimβ Indicates that the.de,.ie, or.ifsections must be copied as is from the original to the translated document. πtranslateβ Indicates that the.de,.ie, or.ifsections will be proposed for the translation. You should only use this option if a translatable string is contained in one of these sections. Otherwise,verbatimshould be preferred. β¨
generatedβ This option specifies that the file was generated, and that po4a should not try to detect if the man page was generated from another format. This option is mandatory to use po4a on generated man pages. Note that translating generated pages instead of source ones is often more fragile, and thus a bad idea. πmdocβ This option is only useful for mdoc pages. It selects a stricter support of the mdoc format by telling po4a not to translate the'NAME'section. mdoc pages whose'NAME'section is translated won't generate any header or footer. According to thegroff_mdocpage, theNAME,SYNOPSIS, andDESCRIPTIONsections are mandatory. There are no known issues with translatedSYNOPSISorDESCRIPTIONsection, but you can also specify these sections this way:
-o mdoc=NAME,SYNOPSIS,DESCRIPTION
This mdoc issue can also be solved with an addendum like this one:
PO4A-HEADER:mode=before;position=^.Dd
.TH DOCUMENT_TITLE 1 "Month day, year" OS "Section Name"
The following options specify the behavior of a user-defined macro (with a .de request), or of a classical macro that is not supported by po4a. They take as argument a comma-separated list of macros. For example:
-o noarg=FO,OB,AR -o translate_joined=BA,ZQ,UX
π Note: if a macro is not supported by po4a and if you consider that it is a standard roff macro, you should submit it to the po4a development team.
untranslatedβuntranslatedindicates that this macro (and its arguments) don't have to be translated. π«noargβnoargis likeuntranslated, except that po4a will verify that no argument is added to this macro. π§translate_joinedβtranslate_joinedindicates that po4a must propose to translate the arguments of the macro. π«Άtranslate_eachβ Withtranslate_each, the arguments will also be proposed for the translation, except that each one will be translated separately. πΈno_wrapβ This option takes as argument a list of comma-separated couplesbegin:end, wherebeginandendare commands that delimit the begin and end of a section that should not be rewrapped.
π Note: no test is done to ensure that an end command matches its begin command; any ending command stops theno_wrapmode. If you have a begin (respectively end) macro that has no end (respectively begin), you can specify an existing end (likefi) or begin (likenf) as a counterpart. These macros (and their arguments) won't be translated.
inlineβ This option specifies a list of comma-separated macros that must not split the current paragraph. The string to translate will then containfoo <.bar baz qux> quux, wherebaris the command that should be inlined, andbaz quxits arguments. π¦unknown_macrosβ This option indicates how po4a should behave when an unknown macro is found. By default, po4a fails with a warning. It can take the following values:failed(the default value),untranslated,noarg,translate_joined, ortranslate_each(see above for an explanation of these values). π
π οΈ AUTHORING MAN PAGES COMPLIANT WITH PO4A::MAN π οΈ
Okay so here's the tea, bestie: this module is still super limited, and it's always gonna be that way, because it's not a real nroff interpreter. Like yeah, somebody could build a real nroff interpreter so authors could use all the existing macros, or even define new ones in their pages, but we didn't want to. It'd be too difficult, and we didn't think it was necessary. We genuinely think that if manpage authors want their stuff translated, they may have to adapt a little to make translators' lives easier.
So the man parser implemented in po4a has some known limitations we're really not inclined to correct, and those are gonna be pitfalls you have to dodge if you want translators to take care of your documentation. Vibe check your man page before you ship it, fr fr.
π« Don't program in nroff π«
nroff is a complete programming language, with macro definition, conditionals and so on. Since this parser isn't a fully featured nroff interpreter, it will fail on pages using these facilities. (There are about 200 such pages on my box.) Not the flex you think it is, bestie.
π§° Use the plain macro set π§°
There are still some macros which are not supported by po4a::man. This is only because I failed to find any documentation about them. Here is the list of unsupported macros used on my box. Note that this list isn't exhaustive, since the program fails on the first encountered unsupported macro. If you have any information about some of these macros, I'll happily add support for them. Because of these macros, about 250 pages on my box are inaccessible to po4a::man.
.. ." .AT .b .bank
.BE ..br .Bu .BUGS .BY
.ce .dbmmanage .do .En
.EP .EX .Fi .hw .i
.Id .l .LO .mf
.N .na .NF .nh .nl
.Nm .ns .NXR .OPTIONS .PB
.pp .PR .PRE .PU .REq
.RH .rn .S< .sh .SI
.splitfont .Sx .T .TF .The
.TT .UC .ul .Vb .zZ
Big yikes energy, but now you know.
π Hiding text from po4a π
Sometimes the author knows that some parts are not translatable and should not be extracted by po4a. For example, an option may accept an other argument, and other may also appear as the last item of a list. In the first case, other should not be translatable. And in the second case, other should be translated.
In such case, the author can avoid po4a extracting some strings by using some special groff constructs:
.if !'po4a'hide' .B other
(This will require the -o groff_code=verbatim option.)
A new macro can also be defined to automate this:
.de IR_untranslated
. IR \\$@
..
.IR_untranslated \-q ", " \-\-quiet
(This will require the options -o groff_code=verbatim and -o untranslated=IR_untranslated; with this construct, the .if !'po4a'hide' conditional is not strictly needed since po4a will not parse the internal of the macro definition.)
Or using an alias:
.als IR_untranslated IR
.IR_untranslated \-q ", " \-\-quiet
This will require the -o untranslated=als,IR_untranslated option. Slay, translators understood.
π Conclusion π
To summarise this section: keep it simple, and don't try to be clever while authoring your man pages. A lot of things are possible in nroff, and not supported by this parser. For example, don't try to mess with \c to interrupt the text processing (like 40 pages on my box do). Or be sure to put the macro arguments on the same line as the macro itself. I know that it's valid in nroff, but it would complicate the parser too much to be handled.
Of course, another possibility is to use another format, more translator friendly (like POD using po4a::pod, or one of the XML family like SGML), but thanks to po4a::man it isn't needed anymore. That being said, if the source format of your documentation is POD, or XML, it may be clever to translate the source format and not this generated one. In most cases, po4a::man will detect generated pages and issue a warning. It will even refuse to process POD generated pages, because those pages are perfectly handled by po4a::pod, and because their nroff counterpart defines a lot of new macros I didn't want to write support for. On my box, 1432 of the 4323 pages are generated from POD and will be ignored by po4a::man.
In most cases, po4a::man will detect the problem and refuse to process the page, issuing an adapted message. In some rare cases, the program will complete without warning, but the output will be wrong. Such cases are called "bugs" ;) If you encounter such a case, be sure to report this, along with a fix when possibleβ¦ manifesting bug reports with patches β¨
π STATUS OF THIS MODULE π
This module can be used for most of the existing man pages. Iconic behaviour, honestly.
Some tests are regularly run on Linux boxes:
- one third of the pages are refused because they were generated from another format supported by po4a (e.g. POD or SGML).
- 10% of the remaining pages are rejected with an error (e.g. a
groffmacro is not supported). - Then, less than 1% of the pages are accepted silently by po4a, but with significant issues (i.e. missing words, or new words inserted).
- The other pages are usually handled without differences more important than spacing differences or line rewrapped (font issues in less than 10% of the processed pages).
π SEE ALSO π
π AUTHORS π
- Denis Barbier
<barbier@linuxfr.org> - Nicolas FranΓ§ois
<nicolas.francois@centraliens.net> - Martin Quinson
(mquinson#debian.org)
π COPYRIGHT AND LICENSE π
Copyright Β© 2002-2008 SPI, Inc.
This program is free software; you may redistribute it and/or modify it under the terms of GPL v2.0 or later (see the COPYING file).
π That's the whole page, bestie! It's from perl v5.42.0, dated 2025-07-13, and it's the LOCALE:...:MAN.3PM(1) manual page. Byeee! π«Άβ¨
π¦ where this page comes from
- alpine 3.23: po4a-doc 0.74-r0 Β· GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms