1*983afe33SPhil Shafer 2*983afe33SPhil ShaferHowtos: Focused Directions 3*983afe33SPhil Shafer========================== 4*983afe33SPhil Shafer 5*983afe33SPhil ShaferThis section provides task-oriented instructions for selected tasks. 6*983afe33SPhil ShaferIf you have a task that needs instructions, please open a request as 7*983afe33SPhil Shaferan enhancement issue on github. 8*983afe33SPhil Shafer 9*983afe33SPhil ShaferHowto: Report bugs 10*983afe33SPhil Shafer------------------ 11*983afe33SPhil Shafer 12*983afe33SPhil Shaferlibxo uses github to track bugs or request enhancements. Please use 13*983afe33SPhil Shaferthe following URL: 14*983afe33SPhil Shafer 15*983afe33SPhil Shafer https://github.com/Juniper/libxo/issues 16*983afe33SPhil Shafer 17*983afe33SPhil ShaferHowto: Install libxo 18*983afe33SPhil Shafer-------------------- 19*983afe33SPhil Shafer 20*983afe33SPhil Shaferlibxo is open source, under a new BSD license. Source code is 21*983afe33SPhil Shaferavailable on github, as are recent releases. To get the most 22*983afe33SPhil Shafercurrent release, please visit: 23*983afe33SPhil Shafer 24*983afe33SPhil Shafer https://github.com/Juniper/libxo/releases 25*983afe33SPhil Shafer 26*983afe33SPhil ShaferAfter downloading and untarring the source code, building involves the 27*983afe33SPhil Shaferfollowing steps:: 28*983afe33SPhil Shafer 29*983afe33SPhil Shafer sh bin/setup.sh 30*983afe33SPhil Shafer cd build 31*983afe33SPhil Shafer ../configure 32*983afe33SPhil Shafer make 33*983afe33SPhil Shafer make test 34*983afe33SPhil Shafer sudo make install 35*983afe33SPhil Shafer 36*983afe33SPhil Shaferlibxo uses a distinct "*build*" directory to keep generated files 37*983afe33SPhil Shaferseparated from source files. 38*983afe33SPhil Shafer 39*983afe33SPhil Shafer.. index:: configure 40*983afe33SPhil Shafer 41*983afe33SPhil ShaferUse "`../configure --help`" to display available configuration 42*983afe33SPhil Shaferoptions, which include the following:: 43*983afe33SPhil Shafer 44*983afe33SPhil Shafer --enable-warnings Turn on compiler warnings 45*983afe33SPhil Shafer --enable-debug Turn on debugging 46*983afe33SPhil Shafer --enable-text-only Turn on text-only rendering 47*983afe33SPhil Shafer --enable-printflike Enable use of GCC __printflike attribute 48*983afe33SPhil Shafer --disable-libxo-options Turn off support for LIBXO_OPTIONS 49*983afe33SPhil Shafer --with-gettext=PFX Specify location of gettext installation 50*983afe33SPhil Shafer --with-libslax-prefix=PFX Specify location of libslax config 51*983afe33SPhil Shafer 52*983afe33SPhil ShaferCompiler warnings are a very good thing, but recent compiler version 53*983afe33SPhil Shaferhave added some very pedantic checks. While every attempt is made to 54*983afe33SPhil Shaferkeep libxo code warning-free, warnings are now optional. If you are 55*983afe33SPhil Shaferdoing development work on libxo, it is required that you 56*983afe33SPhil Shaferuse --enable-warnings to keep the code warning free, but most users 57*983afe33SPhil Shaferneed not use this option. 58*983afe33SPhil Shafer 59*983afe33SPhil Shafer.. index:: --enable-text-only 60*983afe33SPhil Shafer 61*983afe33SPhil Shaferlibxo provides the `--enable-text-only` option to reduce the 62*983afe33SPhil Shaferfootprint of the library for smaller installations. XML, JSON, and 63*983afe33SPhil ShaferHTML rendering logic is removed. 64*983afe33SPhil Shafer 65*983afe33SPhil Shafer.. index:: --with-gettext 66*983afe33SPhil Shafer 67*983afe33SPhil ShaferThe gettext library does not provide a simple means of learning its 68*983afe33SPhil Shaferlocation, but libxo will look for it in /usr and /opt/local. If 69*983afe33SPhil Shaferinstalled elsewhere, the installer will need to provide this 70*983afe33SPhil Shaferinformation using the "`--with-gettext=/dir/path`" option. 71*983afe33SPhil Shafer 72*983afe33SPhil Shafer.. index:: libslax 73*983afe33SPhil Shafer 74*983afe33SPhil Shaferlibslax is not required by libxo; it contains the "oxtradoc" program 75*983afe33SPhil Shaferused to format documentation. 76*983afe33SPhil Shafer 77*983afe33SPhil ShaferFor additional information, see :ref:`building`. 78*983afe33SPhil Shafer 79*983afe33SPhil ShaferHowto: Convert command line applications 80*983afe33SPhil Shafer---------------------------------------- 81*983afe33SPhil Shafer 82*983afe33SPhil ShaferCommon question: How do I convert an existing command line application? 83*983afe33SPhil Shafer 84*983afe33SPhil ShaferThere are four basic steps for converting command line application to 85*983afe33SPhil Shaferuse libxo:: 86*983afe33SPhil Shafer 87*983afe33SPhil Shafer- Setting up the context 88*983afe33SPhil Shafer- Converting printf calls 89*983afe33SPhil Shafer- Creating hierarchy 90*983afe33SPhil Shafer- Converting error functions 91*983afe33SPhil Shafer 92*983afe33SPhil ShaferSetting up the context 93*983afe33SPhil Shafer~~~~~~~~~~~~~~~~~~~~~~ 94*983afe33SPhil Shafer 95*983afe33SPhil ShaferTo use libxo, you'll need to include the "xo.h" header file in your 96*983afe33SPhil Shafersource code files:: 97*983afe33SPhil Shafer 98*983afe33SPhil Shafer #include <libxo/xo.h> 99*983afe33SPhil Shafer 100*983afe33SPhil ShaferIn your main() function, you'll need to call xo_parse_args to handling 101*983afe33SPhil Shaferargument parsing (:ref:`xo_parse_args`). This function removes 102*983afe33SPhil Shaferlibxo-specific arguments the program's argv and returns either the 103*983afe33SPhil Shafernumber of remaining arguments or -1 to indicate an error:: 104*983afe33SPhil Shafer 105*983afe33SPhil Shafer int 106*983afe33SPhil Shafer main (int argc, char **argv) 107*983afe33SPhil Shafer { 108*983afe33SPhil Shafer argc = xo_parse_args(argc, argv); 109*983afe33SPhil Shafer if (argc < 0) 110*983afe33SPhil Shafer return argc; 111*983afe33SPhil Shafer .... 112*983afe33SPhil Shafer } 113*983afe33SPhil Shafer 114*983afe33SPhil Shafer.. index:: atexit 115*983afe33SPhil Shafer.. index:: xo_finish_atexit 116*983afe33SPhil Shafer 117*983afe33SPhil ShaferAt the bottom of your main(), you'll need to call xo_finish() to 118*983afe33SPhil Shafercomplete output processing for the default handle (:ref:`handles`). This 119*983afe33SPhil Shaferis required to flush internal information buffers. libxo provides the 120*983afe33SPhil Shaferxo_finish_atexit function that is suitable for use with the 121*983afe33SPhil Shafer:manpage:`atexit(3)` function:: 122*983afe33SPhil Shafer 123*983afe33SPhil Shafer atexit(xo_finish_atexit); 124*983afe33SPhil Shafer 125*983afe33SPhil ShaferConverting printf Calls 126*983afe33SPhil Shafer~~~~~~~~~~~~~~~~~~~~~~~ 127*983afe33SPhil Shafer 128*983afe33SPhil ShaferThe second task is inspecting code for :manpage:`printf(3)` calls and 129*983afe33SPhil Shaferreplacing them with xo_emit() calls. The format strings are similar 130*983afe33SPhil Shaferin task, but libxo format strings wrap output fields in braces. The 131*983afe33SPhil Shaferfollowing two calls produce identical text output:: 132*983afe33SPhil Shafer 133*983afe33SPhil Shafer OLD:: 134*983afe33SPhil Shafer printf("There are %d %s events\n", count, etype); 135*983afe33SPhil Shafer 136*983afe33SPhil Shafer NEW:: 137*983afe33SPhil Shafer xo_emit("There are {:count/%d} {:event} events\n", count, etype); 138*983afe33SPhil Shafer 139*983afe33SPhil Shafer"count" and "event" are used as names for JSON and XML output. The 140*983afe33SPhil Shafer"count" field uses the format "%d" and "event" uses the default "%s" 141*983afe33SPhil Shaferformat. Both are "value" roles, which is the default role. 142*983afe33SPhil Shafer 143*983afe33SPhil ShaferSince text outside of output fields is passed verbatim, other roles 144*983afe33SPhil Shaferare less important, but their proper use can help make output more 145*983afe33SPhil Shaferuseful. The "note" and "label" roles allow HTML output to recognize 146*983afe33SPhil Shaferthe relationship between text and the associated values, allowing 147*983afe33SPhil Shaferappropriate "hover" and "onclick" behavior. Using the "units" role 148*983afe33SPhil Shaferallows the presentation layer to perform conversions when needed. The 149*983afe33SPhil Shafer"warning" and "error" roles allows use of color and font to draw 150*983afe33SPhil Shaferattention to warnings. The "padding" role makes the use of vital 151*983afe33SPhil Shaferwhitespace more clear (:ref:`padding-role`). 152*983afe33SPhil Shafer 153*983afe33SPhil ShaferThe "*title*" role indicates the headings of table and sections. This 154*983afe33SPhil Shaferallows HTML output to use CSS to make this relationship more obvious:: 155*983afe33SPhil Shafer 156*983afe33SPhil Shafer OLD:: 157*983afe33SPhil Shafer printf("Statistics:\n"); 158*983afe33SPhil Shafer 159*983afe33SPhil Shafer NEW:: 160*983afe33SPhil Shafer xo_emit("{T:Statistics}:\n"); 161*983afe33SPhil Shafer 162*983afe33SPhil ShaferThe "*color*" roles controls foreground and background colors, as well 163*983afe33SPhil Shaferas effects like bold and underline (see :ref:`color-role`):: 164*983afe33SPhil Shafer 165*983afe33SPhil Shafer NEW:: 166*983afe33SPhil Shafer xo_emit("{C:bold}required{C:}\n"); 167*983afe33SPhil Shafer 168*983afe33SPhil ShaferFinally, the start- and stop-anchor roles allow justification and 169*983afe33SPhil Shaferpadding over multiple fields (see :ref:`anchor-role`):: 170*983afe33SPhil Shafer 171*983afe33SPhil Shafer OLD:: 172*983afe33SPhil Shafer snprintf(buf, sizeof(buf), "(%u/%u/%u)", min, ave, max); 173*983afe33SPhil Shafer printf("%30s", buf); 174*983afe33SPhil Shafer 175*983afe33SPhil Shafer NEW:: 176*983afe33SPhil Shafer xo_emit("{[:30}({:minimum/%u}/{:average/%u}/{:maximum/%u}{]:}", 177*983afe33SPhil Shafer min, ave, max); 178*983afe33SPhil Shafer 179*983afe33SPhil ShaferCreating Hierarchy 180*983afe33SPhil Shafer~~~~~~~~~~~~~~~~~~ 181*983afe33SPhil Shafer 182*983afe33SPhil ShaferText output doesn't have any sort of hierarchy, but XML and JSON 183*983afe33SPhil Shaferrequire this. Typically applications use indentation to represent 184*983afe33SPhil Shaferthese relationship:: 185*983afe33SPhil Shafer 186*983afe33SPhil Shafer OLD:: 187*983afe33SPhil Shafer printf("table %d\n", tnum); 188*983afe33SPhil Shafer for (i = 0; i < tmax; i++) { 189*983afe33SPhil Shafer printf(" %s %d\n", table[i].name, table[i].size); 190*983afe33SPhil Shafer } 191*983afe33SPhil Shafer 192*983afe33SPhil Shafer NEW:: 193*983afe33SPhil Shafer xo_emit("{T:/table %d}\n", tnum); 194*983afe33SPhil Shafer xo_open_list("table"); 195*983afe33SPhil Shafer for (i = 0; i < tmax; i++) { 196*983afe33SPhil Shafer xo_open_instance("table"); 197*983afe33SPhil Shafer xo_emit("{P: }{k:name} {:size/%d}\n", 198*983afe33SPhil Shafer table[i].name, table[i].size); 199*983afe33SPhil Shafer xo_close_instance("table"); 200*983afe33SPhil Shafer } 201*983afe33SPhil Shafer xo_close_list("table"); 202*983afe33SPhil Shafer 203*983afe33SPhil ShaferThe open and close list functions are used before and after the list, 204*983afe33SPhil Shaferand the open and close instance functions are used before and after 205*983afe33SPhil Shafereach instance with in the list. 206*983afe33SPhil Shafer 207*983afe33SPhil ShaferTypically these developer looks for a "for" loop as an indication of 208*983afe33SPhil Shaferwhere to put these calls. 209*983afe33SPhil Shafer 210*983afe33SPhil ShaferIn addition, the open and close container functions allow for 211*983afe33SPhil Shaferorganization levels of hierarchy:: 212*983afe33SPhil Shafer 213*983afe33SPhil Shafer OLD:: 214*983afe33SPhil Shafer printf("Paging information:\n"); 215*983afe33SPhil Shafer printf(" Free: %lu\n", free); 216*983afe33SPhil Shafer printf(" Active: %lu\n", active); 217*983afe33SPhil Shafer printf(" Inactive: %lu\n", inactive); 218*983afe33SPhil Shafer 219*983afe33SPhil Shafer NEW:: 220*983afe33SPhil Shafer xo_open_container("paging-information"); 221*983afe33SPhil Shafer xo_emit("{P: }{L:Free: }{:free/%lu}\n", free); 222*983afe33SPhil Shafer xo_emit("{P: }{L:Active: }{:active/%lu}\n", active); 223*983afe33SPhil Shafer xo_emit("{P: }{L:Inactive: }{:inactive/%lu}\n", inactive); 224*983afe33SPhil Shafer xo_close_container("paging-information"); 225*983afe33SPhil Shafer 226*983afe33SPhil ShaferConverting Error Functions 227*983afe33SPhil Shafer~~~~~~~~~~~~~~~~~~~~~~~~~~ 228*983afe33SPhil Shafer 229*983afe33SPhil Shaferlibxo provides variants of the standard error and warning functions, 230*983afe33SPhil Shafer:manpage:`err(3)` and :manpage:`warn(3)`. There are two variants, one 231*983afe33SPhil Shaferfor putting the errors on standard error, and the other writes the 232*983afe33SPhil Shafererrors and warnings to the handle using the appropriate encoding 233*983afe33SPhil Shaferstyle:: 234*983afe33SPhil Shafer 235*983afe33SPhil Shafer OLD:: 236*983afe33SPhil Shafer err(1, "cannot open output file: %s", file); 237*983afe33SPhil Shafer 238*983afe33SPhil Shafer NEW:: 239*983afe33SPhil Shafer xo_err(1, "cannot open output file: %s", file); 240*983afe33SPhil Shafer xo_emit_err(1, "cannot open output file: {:filename}", file); 241*983afe33SPhil Shafer 242*983afe33SPhil Shafer.. index:: xo_finish 243*983afe33SPhil Shafer 244*983afe33SPhil ShaferCall xo_finish 245*983afe33SPhil Shafer~~~~~~~~~~~~~~ 246*983afe33SPhil Shafer 247*983afe33SPhil ShaferOne important item: call `xo_finish` at the end of your program so 248*983afe33SPhil Shaferensure that all buffered data is written out. You can call it 249*983afe33SPhil Shaferexplicitly call it, or use :manpage:`atexit(3)` to have 250*983afe33SPhil Shafer`xo_finish_atexit` called implicitly on exit:: 251*983afe33SPhil Shafer 252*983afe33SPhil Shafer OLD:: 253*983afe33SPhil Shafer exit(0); 254*983afe33SPhil Shafer 255*983afe33SPhil Shafer NEW:: 256*983afe33SPhil Shafer xo_finish(); 257*983afe33SPhil Shafer exit(0); 258*983afe33SPhil Shafer 259*983afe33SPhil ShaferHowto: Use "xo" in Shell Scripts 260*983afe33SPhil Shafer-------------------------------- 261*983afe33SPhil Shafer 262*983afe33SPhil Shafer.. admonition:: Needed 263*983afe33SPhil Shafer 264*983afe33SPhil Shafer Documentation is needed for this area. 265*983afe33SPhil Shafer 266*983afe33SPhil Shafer.. index:: Internationalization (i18n) 267*983afe33SPhil Shafer.. index:: gettext 268*983afe33SPhil Shafer.. index:: xopo 269*983afe33SPhil Shafer 270*983afe33SPhil Shafer.. _i18n: 271*983afe33SPhil Shafer 272*983afe33SPhil ShaferHowto: Internationalization (i18n) 273*983afe33SPhil Shafer----------------------------------------------- 274*983afe33SPhil Shafer 275*983afe33SPhil Shafer How do I use libxo to support internationalization? 276*983afe33SPhil Shafer 277*983afe33SPhil Shaferlibxo allows format and field strings to be used a keys into message 278*983afe33SPhil Shafercatalogs to enable translation into a user's native language by 279*983afe33SPhil Shaferinvoking the standard :manpage:`gettext(3)` functions. 280*983afe33SPhil Shafer 281*983afe33SPhil Shafergettext setup is a bit complicated: text strings are extracted from 282*983afe33SPhil Shafersource files into "*portable object template*" (.pot) files using the 283*983afe33SPhil Shafer`xgettext` command. For each language, this template file is used as 284*983afe33SPhil Shaferthe source for a message catalog in the "*portable object*" (.po) 285*983afe33SPhil Shaferformat, which are translated by hand and compiled into "*machine 286*983afe33SPhil Shaferobject*" (.mo) files using the `msgfmt` command. The .mo files are 287*983afe33SPhil Shaferthen typically installed in the /usr/share/locale or 288*983afe33SPhil Shafer/opt/local/share/locale directories. At run time, the user's language 289*983afe33SPhil Shafersettings are used to select a .mo file which is searched for matching 290*983afe33SPhil Shafermessages. Text strings in the source code are used as keys to look up 291*983afe33SPhil Shaferthe native language strings in the .mo file. 292*983afe33SPhil Shafer 293*983afe33SPhil ShaferSince the xo_emit format string is used as the key into the message 294*983afe33SPhil Shafercatalog, libxo removes unimportant field formatting and modifiers from 295*983afe33SPhil Shaferthe format string before use so that minor formatting changes will not 296*983afe33SPhil Shaferimpact the expensive translation process. We don't want a developer 297*983afe33SPhil Shaferchange such as changing "/%06d" to "/%08d" to force hand inspection of 298*983afe33SPhil Shaferall .po files. The simplified version can be generated for a single 299*983afe33SPhil Shafermessage using the `xopo -s $text` command, or an entire .pot can be 300*983afe33SPhil Shafertranslated using the `xopo -f $input -o $output` command:: 301*983afe33SPhil Shafer 302*983afe33SPhil Shafer EXAMPLE: 303*983afe33SPhil Shafer % xopo -s "There are {:count/%u} {:event/%.6s} events\n" 304*983afe33SPhil Shafer There are {:count} {:event} events\n 305*983afe33SPhil Shafer 306*983afe33SPhil Shafer Recommended workflow: 307*983afe33SPhil Shafer # Extract text messages 308*983afe33SPhil Shafer xgettext --default-domain=foo --no-wrap \ 309*983afe33SPhil Shafer --add-comments --keyword=xo_emit --keyword=xo_emit_h \ 310*983afe33SPhil Shafer --keyword=xo_emit_warn -C -E -n --foreign-user \ 311*983afe33SPhil Shafer -o foo.pot.raw foo.c 312*983afe33SPhil Shafer 313*983afe33SPhil Shafer # Simplify format strings for libxo 314*983afe33SPhil Shafer xopo -f foo.pot.raw -o foo.pot 315*983afe33SPhil Shafer 316*983afe33SPhil Shafer # For a new language, just copy the file 317*983afe33SPhil Shafer cp foo.pot po/LC/my_lang/foo.po 318*983afe33SPhil Shafer 319*983afe33SPhil Shafer # For an existing language: 320*983afe33SPhil Shafer msgmerge --no-wrap po/LC/my_lang/foo.po \ 321*983afe33SPhil Shafer foo.pot -o po/LC/my_lang/foo.po.new 322*983afe33SPhil Shafer 323*983afe33SPhil Shafer # Now the hard part: translate foo.po using tools 324*983afe33SPhil Shafer # like poedit or emacs' po-mode 325*983afe33SPhil Shafer 326*983afe33SPhil Shafer # Compile the finished file; Use of msgfmt's "-v" option is 327*983afe33SPhil Shafer # strongly encouraged, so that "fuzzy" entries are reported. 328*983afe33SPhil Shafer msgfmt -v -o po/my_lang/LC_MESSAGES/foo.mo po/my_lang/foo.po 329*983afe33SPhil Shafer 330*983afe33SPhil Shafer # Install the .mo file 331*983afe33SPhil Shafer sudo cp po/my_lang/LC_MESSAGES/foo.mo \ 332*983afe33SPhil Shafer /opt/local/share/locale/my_lang/LC_MESSAGE/ 333*983afe33SPhil Shafer 334*983afe33SPhil ShaferOnce these steps are complete, you can use the `gettext` command to 335*983afe33SPhil Shafertest the message catalog:: 336*983afe33SPhil Shafer 337*983afe33SPhil Shafer gettext -d foo -e "some text" 338*983afe33SPhil Shafer 339*983afe33SPhil Shaferi18n and xo_emit 340*983afe33SPhil Shafer~~~~~~~~~~~~~~~~ 341*983afe33SPhil Shafer 342*983afe33SPhil ShaferThere are three features used in libxo used to support i18n: 343*983afe33SPhil Shafer 344*983afe33SPhil Shafer- The "{G:}" role looks for a translation of the format string. 345*983afe33SPhil Shafer- The "{g:}" modifier looks for a translation of the field. 346*983afe33SPhil Shafer- The "{p:}" modifier looks for a pluralized version of the field. 347*983afe33SPhil Shafer 348*983afe33SPhil ShaferTogether these three flags allows a single function call to give 349*983afe33SPhil Shafernative language support, as well as libxo's normal XML, JSON, and HTML 350*983afe33SPhil Shafersupport:: 351*983afe33SPhil Shafer 352*983afe33SPhil Shafer printf(gettext("Received %zu %s from {g:server} server\n"), 353*983afe33SPhil Shafer counter, ngettext("byte", "bytes", counter), 354*983afe33SPhil Shafer gettext("web")); 355*983afe33SPhil Shafer 356*983afe33SPhil Shafer xo_emit("{G:}Received {:received/%zu} {Ngp:byte,bytes} " 357*983afe33SPhil Shafer "from {g:server} server\n", counter, "web"); 358*983afe33SPhil Shafer 359*983afe33SPhil Shaferlibxo will see the "{G:}" role and will first simplify the format 360*983afe33SPhil Shaferstring, removing field formats and modifiers:: 361*983afe33SPhil Shafer 362*983afe33SPhil Shafer "Received {:received} {N:byte,bytes} from {:server} server\n" 363*983afe33SPhil Shafer 364*983afe33SPhil Shaferlibxo calls :manpage:`gettext(3)` with that string to get a localized 365*983afe33SPhil Shaferversion. If your language were *Pig Latin*, the result might look 366*983afe33SPhil Shaferlike:: 367*983afe33SPhil Shafer 368*983afe33SPhil Shafer "Eceivedray {:received} {N:byte,bytes} omfray " 369*983afe33SPhil Shafer "{:server} erversay\n" 370*983afe33SPhil Shafer 371*983afe33SPhil ShaferNote the field names do not change and they should not be translated. 372*983afe33SPhil ShaferThe contents of the note ("byte,bytes") should also not be translated, 373*983afe33SPhil Shafersince the "g" modifier will need the untranslated value as the key for 374*983afe33SPhil Shaferthe message catalog. 375*983afe33SPhil Shafer 376*983afe33SPhil ShaferThe field "{g:server}" requests the rendered value of the field be 377*983afe33SPhil Shafertranslated using :manpage:`gettext(3)`. In this example, "web" would 378*983afe33SPhil Shaferbe used. 379*983afe33SPhil Shafer 380*983afe33SPhil ShaferThe field "{Ngp:byte,bytes}" shows an example of plural form using the 381*983afe33SPhil Shafer"{p:}" modifier with the "{g:}" modifier. The base singular and plural 382*983afe33SPhil Shaferforms appear inside the field, separated by a comma. At run time, 383*983afe33SPhil Shaferlibxo uses the previous field's numeric value to decide which form to 384*983afe33SPhil Shaferuse by calling :manpage:`ngettext(3)`. 385*983afe33SPhil Shafer 386*983afe33SPhil ShaferIf a domain name is needed, it can be supplied as the content of the 387*983afe33SPhil Shafer{G:} role. Domain names remain in use throughout the format string 388*983afe33SPhil Shaferuntil cleared with another domain name:: 389*983afe33SPhil Shafer 390*983afe33SPhil Shafer printf(dgettext("dns", "Host %s not found: %d(%s)\n"), 391*983afe33SPhil Shafer name, errno, dgettext("strerror", strerror(errno))); 392*983afe33SPhil Shafer 393*983afe33SPhil Shafer xo_emit("{G:dns}Host {:hostname} not found: " 394*983afe33SPhil Shafer "%d({G:strerror}{g:%m})\n", name, errno); 395