Write a .po or .pot file corresponding to a message database
Source:R/write_po_file.R
write_po_file.Rd
Serialize a message database in the .po
and .pot
formats
recognized by the gettext ecosystem.
Usage
write_po_file(
message_data,
po_file,
metadata,
width = 79L,
wrap_at_newline = TRUE,
use_base_rules = metadata$package %chin% .potools$base_package_names
)
po_metadata(
package = "",
version = "",
language = "",
author = "",
email = "",
bugs = "",
copyright = NULL,
...
)
# S3 method for po_metadata
format(x, template = FALSE, use_plurals = FALSE, ...)
# S3 method for po_metadata
print(x, ...)
Arguments
- message_data
data.table
, as returned fromget_message_data()
. NB: R creates separate domains for R and C/C++ code; it is recommended you do the same by filtering theget_message_data
output formessage_source == "R"
ormessage_source == "src"
. Other approaches are untested.- po_file
Character vector giving a destination path. Paths ending in
.pot
will be written with template files (e.g.,msgstr
entries will be blanked).- metadata
A
po_metadata
object as returned bypo_metadata()
.- width
Numeric governing the wrapping width of the output file. Default is
79L
to match the behavior of thexgettext
utility.Inf
turns off wrapping (except for file source markers comments).- wrap_at_newline
Logical, default
TRUE
to match thexgettext
utility's behavior. IfTRUE
, anymsgid
ormsgstr
will always be wrapped at an internal newline (i.e., literally matching\n
).- use_base_rules
Logical; Should internal behavior match base behavior as strictly as possible?
TRUE
if being run on a base package (i.e.,base
or one of the default packages likeutils
,graphics
, etc.). See Details.- package
Character; the name of the package being translated.
- version
Character; the version of the package being translated.
- language
Character; the language of the
msgstr
. Seetranslate_package()
for details.- author
Character; an author (combined with
email
) to whom to attribute the translations (asLast-Translator
).Character; an e-mail address associated with
author
.- bugs
Character; a URL where issues with the translations can be reported.
- copyright
An object used to construct the initial Copyright reference in the output. If
NULL
, no such comment is written. If alist
, it should the following structure:year
: Required, A year or hyphen-separated range of yearsholder
: Required, The name of the copyright holdertitle
: Optional, A title for the.po
additional
: Optional, A character vector of additional lines for the copyright comment section
If a
character
scalar, it is interpreted as theholder
and theyear
is set as thePOT-Creation-Date
's year.- ...
Additional (named) components to add to the metadata. For
print.po_metadata
, passed on toformat.po_metadata
- x
A
po_metadata
object.- template
Logical; format the metadata as in a
.pot
template?- use_plurals
Logical; should the
Plural-Forms
entry be included?
Value
For po_metadata
, an object of class po_metadata
that
has a format
method used to serialize the metadata.
Details
Three components are set automatically if not provided:
pot_timestamp
- APOSIXct
used to write thePOT-Creation-Date
entry. Defaults to theSys.time()
at run time.po_timestamp
- APOSIXct
used to write thePO-Revision-Date
entry. Defaults to be the same aspot_timestamp
.language_team
- A string used to write theLanguage-Team
entry. Defaults to be the same aslanguage
; if provided manually, the formatLANGUAGE <LL@li.org>
is recommended.
The charset
for output is always set to "UTF-8"
; this is
intentional to make it more cumbersome to create non-UTF-8 files.
Examples
message_data <- get_message_data(system.file('pkg', package='potools'))
#> Getting R-level messages...
#> Getting src-level messages...
desc_data <- read.dcf(system.file('pkg', 'DESCRIPTION', package='potools'), c('Package', 'Version'))
metadata <- po_metadata(
package = desc_data[, "Package"], version = desc_data[, "Version"],
language = 'ar_SY', author = 'R User', email = 'ruser@gmail.com',
bugs = 'https://github.com/ruser/potoolsExample/issues'
)
# add fake translations
message_data[type == "singular", msgstr := "<arabic translation>"]
#> Index: <type>
#> message_source type file
#> <char> <char> <char>
#> 1: R singular add.R
#> 2: R singular add.R
#> 3: R singular onLoad.R
#> 4: R singular onLoad.R
#> 5: R singular onLoad.R
#> 6: src singular reverse_int.c
#> msgid msgid_plural
#> <char> <list>
#> 1: add() only works on all-integer input, but found other types:
#> 2: integer
#> 3: Launching
#> 4: /
#> 5:
#> 6: reverse_int() only works on integer input, received %s
#> call
#> <char>
#> 1: stop( "add() only works on all-integer input, but found other types: ", toString(unique(setdiff(input_types, "integer"))) )
#> 2: stop( "add() only works on all-integer input, but found other types: ", toString(unique(setdiff(input_types, "integer"))) )
#> 3: cat("Launching", format(libname), "/", format(pkgname), "\\n")
#> 4: cat("Launching", format(libname), "/", format(pkgname), "\\n")
#> 5: cat("Launching", format(libname), "/", format(pkgname), "\\n")
#> 6: _("reverse_int() only works on integer input, received %s")
#> line_number is_repeat is_marked_for_translation is_templated
#> <int> <lgcl> <lgcl> <lgcl>
#> 1: 7 FALSE TRUE FALSE
#> 2: 8 FALSE TRUE FALSE
#> 3: 2 FALSE FALSE FALSE
#> 4: 2 FALSE FALSE FALSE
#> 5: 2 FALSE FALSE FALSE
#> 6: 9 FALSE TRUE TRUE
#> msgstr
#> <char>
#> 1: <arabic translation>
#> 2: <arabic translation>
#> 3: <arabic translation>
#> 4: <arabic translation>
#> 5: <arabic translation>
#> 6: <arabic translation>
# Arabic has 6 plural forms
message_data[type == "plural", msgstr_plural := .(as.list(sprintf("<%d translation>", 0:5)))]
#> Index: <type>
#> message_source type file
#> <char> <char> <char>
#> 1: R singular add.R
#> 2: R singular add.R
#> 3: R singular onLoad.R
#> 4: R singular onLoad.R
#> 5: R singular onLoad.R
#> 6: src singular reverse_int.c
#> msgid msgid_plural
#> <char> <list>
#> 1: add() only works on all-integer input, but found other types:
#> 2: integer
#> 3: Launching
#> 4: /
#> 5:
#> 6: reverse_int() only works on integer input, received %s
#> call
#> <char>
#> 1: stop( "add() only works on all-integer input, but found other types: ", toString(unique(setdiff(input_types, "integer"))) )
#> 2: stop( "add() only works on all-integer input, but found other types: ", toString(unique(setdiff(input_types, "integer"))) )
#> 3: cat("Launching", format(libname), "/", format(pkgname), "\\n")
#> 4: cat("Launching", format(libname), "/", format(pkgname), "\\n")
#> 5: cat("Launching", format(libname), "/", format(pkgname), "\\n")
#> 6: _("reverse_int() only works on integer input, received %s")
#> line_number is_repeat is_marked_for_translation is_templated
#> <int> <lgcl> <lgcl> <lgcl>
#> 1: 7 FALSE TRUE FALSE
#> 2: 8 FALSE TRUE FALSE
#> 3: 2 FALSE FALSE FALSE
#> 4: 2 FALSE FALSE FALSE
#> 5: 2 FALSE FALSE FALSE
#> 6: 9 FALSE TRUE TRUE
#> msgstr msgstr_plural
#> <char> <list>
#> 1: <arabic translation>
#> 2: <arabic translation>
#> 3: <arabic translation>
#> 4: <arabic translation>
#> 5: <arabic translation>
#> 6: <arabic translation>
# Preview metadata
print(metadata)
#> msgid ""
#> msgstr ""
#> "Project-Id-Version: potoolsExample 0.0.1\n"
#> "Report-Msgid-Bugs-To: https://github.com/ruser/potoolsExample/issues\n"
#> "POT-Creation-Date: 2024-06-21 13:00+0000\n"
#> "PO-Revision-Date: 2024-06-21 13:00+0000\n"
#> "Last-Translator: R User <ruser@gmail.com>\n"
#> "Language-Team: ar_SY\n"
#> "Language: ar_SY\n"
#> "MIME-Version: 1.0\n"
#> "Content-Type: text/plain; charset=UTF-8\n"
#> "Content-Transfer-Encoding: 8bit\n"
# write .po file
write_po_file(
message_data[message_source == "R"],
tmp_po <- tempfile(fileext = '.po'),
metadata
)
#> NULL
writeLines(readLines(tmp_po))
#> msgid ""
#> msgstr ""
#> "Project-Id-Version: potoolsExample 0.0.1\n"
#> "Report-Msgid-Bugs-To: https://github.com/ruser/potoolsExample/issues\n"
#> "POT-Creation-Date: 2024-06-21 13:00+0000\n"
#> "PO-Revision-Date: 2024-06-21 13:00+0000\n"
#> "Last-Translator: R User <ruser@gmail.com>\n"
#> "Language-Team: ar_SY\n"
#> "Language: ar_SY\n"
#> "MIME-Version: 1.0\n"
#> "Content-Type: text/plain; charset=UTF-8\n"
#> "Content-Transfer-Encoding: 8bit\n"
#>
#> #: add.R:7
#> msgid "add() only works on all-integer input, but found other types:"
#> msgstr "<arabic translation>"
#>
#> #: add.R:8
#> msgid "integer"
#> msgstr "<arabic translation>"
# write .pot template
write_po_file(
message_data[message_source == "R"],
tmp_pot <- tempfile(fileext = '.pot'),
metadata
)
#> NULL
writeLines(readLines(tmp_pot))
#> msgid ""
#> msgstr ""
#> "Project-Id-Version: potoolsExample 0.0.1\n"
#> "Report-Msgid-Bugs-To: https://github.com/ruser/potoolsExample/issues\n"
#> "POT-Creation-Date: 2024-06-21 13:00+0000\n"
#> "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
#> "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
#> "Language-Team: LANGUAGE <LL@li.org>\n"
#> "Language: \n"
#> "MIME-Version: 1.0\n"
#> "Content-Type: text/plain; charset=UTF-8\n"
#> "Content-Transfer-Encoding: 8bit\n"
#>
#> #: add.R:7
#> msgid "add() only works on all-integer input, but found other types:"
#> msgstr ""
#>
#> #: add.R:8
#> msgid "integer"
#> msgstr ""
# cleanup
file.remove(tmp_po, tmp_pot)
#> [1] TRUE TRUE
rm(message_data, desc_data, metadata, tmp_po, tmp_pot)