From 3affcc07e036e77b49bf0aae71c3fdd1ebd24293 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Mon, 12 Jul 2021 00:48:19 -0700 Subject: [PATCH 01/31] Implement tr_add() for adding new translations --- DESCRIPTION | 1 + NAMESPACE | 2 ++ R/msgmerge.R | 37 +++++++++++++++++++++++++++++++++++++ man/tr_add.Rd | 21 +++++++++++++++++++++ potools.Rproj | 1 + 5 files changed, 62 insertions(+) create mode 100644 man/tr_add.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 46b1747b..09002ca7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -14,3 +14,4 @@ URL: https://github.com/MichaelChirico/potools BugReports: https://github.com/MichaelChirico/potools/issues Encoding: UTF-8 VignetteBuilder: knitr +RoxygenNote: 7.1.2 diff --git a/NAMESPACE b/NAMESPACE index cfcc50ca..9f16835b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -11,6 +11,8 @@ export(translate_package) export(get_message_data) export(write_po_file, po_metadata) +export(tr_add) + export(check_cracked_messages, check_untranslated_cat, check_untranslated_src) export(check_potools_sys_reqs) diff --git a/R/msgmerge.R b/R/msgmerge.R index 1b703618..6d77386b 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -70,3 +70,40 @@ update_en_quot_mo_files <- function(dir, verbose) { } return(invisible()) } + + + +#' Add a new translation +#' +#' This creates `po/{lang}.po` containing the messages to be translated. +#' +#' @param lang Language identifiers. These are typically two letters (e.g. +#' "en" = English, "fr" = French, "es" = Spanish, "zh" = Chinese), but +#' can include an additional suffix for languages that have regional +#' variations (e.g. "fr_CN" = French Canadian, "zh_CN" = simplified +#' characters as used in mainland China, "zh_TW" = traditional characters +#' as used in Taiwan.) +#' @param dir Path to package root. +tr_add <- function(lang, dir = ".") { + package <- get_desc_data(dir)[["Package"]] + + pot_path <- file.path(dir, "po", paste0("R-", package, ".pot")) + po_path <- file.path(dir, "po", paste0("R-", lang, ".po")) + run_msginit(pot_path, po_path, lang) +} + +# https://www.gnu.org/software/gettext/manual/html_node/msginit-Invocation.html +run_msginit <- function(pot_path, po_path, locale, width = 80) { + cmd <- paste("msginit", + "-i", shQuote(path.expand(pot_path)), + "-o", shQuote(path.expand(po_path)), + "-l", shQuote(locale), + "-w", width, + "--no-translator" # don't consult user-email etc + ) + if (system(cmd) != 0L) { + stop(sprintf("running msginit on '%s' failed", pot_path)) + } + return(invisible()) +} + diff --git a/man/tr_add.Rd b/man/tr_add.Rd new file mode 100644 index 00000000..503b76bf --- /dev/null +++ b/man/tr_add.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/msgmerge.R +\name{tr_add} +\alias{tr_add} +\title{Add a new translation} +\usage{ +tr_add(lang, dir = ".") +} +\arguments{ +\item{lang}{Language identifiers. These are typically two letters (e.g. +"en" = English, "fr" = French, "es" = Spanish, "zh" = Chinese), but +can include an additional suffix for languages that have regional +variations (e.g. "fr_CN" = French Canadian, "zh_CN" = simplified +characters as used in mainland China, "zh_TW" = traditional characters +as used in Taiwan.)} + +\item{dir}{Path to package root.} +} +\description{ +This creates `po/{lang}.po` containing the messages to be translated. +} diff --git a/potools.Rproj b/potools.Rproj index 497f8bfc..9ecfdfcb 100644 --- a/potools.Rproj +++ b/potools.Rproj @@ -18,3 +18,4 @@ StripTrailingWhitespace: Yes BuildType: Package PackageUseDevtools: Yes PackageInstallArgs: --no-multiarch --with-keep.source +PackageRoxygenize: rd From 63dcbc50495d9dc32f1e1a8ab2f146fb29d956af Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Mon, 1 Nov 2021 10:11:47 -0500 Subject: [PATCH 02/31] Add or update as necessary --- R/msgmerge.R | 23 ++++++++++++++++++++--- man/tr_add.Rd | 4 +++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/R/msgmerge.R b/R/msgmerge.R index 6d77386b..4dc22ee1 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -1,6 +1,15 @@ # split off from tools::update_pkg_po() to only run the msgmerge & checkPoFile steps + +# https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html run_msgmerge = function(po_file, pot_file) { - if (system(sprintf("msgmerge --update %s %s", po_file, shQuote(pot_file))) != 0L) { + cmd <- paste("msgmerge", + "--update", + "--previous", # show previous match for fuzzy matches + shQuote(path.expand(po_file)), + shQuote(path.expand(pot_file)) + ) + + if (system(cmd) != 0L) { # nocov these warnings? i don't know how to trigger them as of this writing. warningf("Running msgmerge on '%s' failed.", po_file) } @@ -84,12 +93,20 @@ update_en_quot_mo_files <- function(dir, verbose) { #' characters as used in mainland China, "zh_TW" = traditional characters #' as used in Taiwan.) #' @param dir Path to package root. -tr_add <- function(lang, dir = ".") { +#' @param Verbose If `TRUE`, explain what's happening. +tr_add <- function(lang, dir = ".", verbose = TRUE) { package <- get_desc_data(dir)[["Package"]] pot_path <- file.path(dir, "po", paste0("R-", package, ".pot")) po_path <- file.path(dir, "po", paste0("R-", lang, ".po")) - run_msginit(pot_path, po_path, lang) + + if (!file.exists(po_path)) { + if (verbose) message(sprintf("Adding new %s translation", lang)) + run_msginit(pot_path, po_path, lang) + } else { + if (verbose) message(sprintf("Updating existing %s translation", lang)) + run_msgmerge(po_path, pot_path) + } } # https://www.gnu.org/software/gettext/manual/html_node/msginit-Invocation.html diff --git a/man/tr_add.Rd b/man/tr_add.Rd index 503b76bf..3798b682 100644 --- a/man/tr_add.Rd +++ b/man/tr_add.Rd @@ -4,7 +4,7 @@ \alias{tr_add} \title{Add a new translation} \usage{ -tr_add(lang, dir = ".") +tr_add(lang, dir = ".", verbose = TRUE) } \arguments{ \item{lang}{Language identifiers. These are typically two letters (e.g. @@ -15,6 +15,8 @@ characters as used in mainland China, "zh_TW" = traditional characters as used in Taiwan.)} \item{dir}{Path to package root.} + +\item{Verbose}{If `TRUE`, explain what's happening.} } \description{ This creates `po/{lang}.po` containing the messages to be translated. From cfe1eff93b753ddf7ec372870859804b0a5b530c Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Mon, 1 Nov 2021 10:14:26 -0500 Subject: [PATCH 03/31] Only add previous for tr_add() --- R/msgmerge.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/R/msgmerge.R b/R/msgmerge.R index 4dc22ee1..b14b36ca 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -1,10 +1,10 @@ # split off from tools::update_pkg_po() to only run the msgmerge & checkPoFile steps # https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html -run_msgmerge = function(po_file, pot_file) { +run_msgmerge = function(po_file, pot_file, previous = FALSE) { cmd <- paste("msgmerge", "--update", - "--previous", # show previous match for fuzzy matches + if (previous) "--previous", # show previous match for fuzzy matches shQuote(path.expand(po_file)), shQuote(path.expand(pot_file)) ) @@ -105,7 +105,7 @@ tr_add <- function(lang, dir = ".", verbose = TRUE) { run_msginit(pot_path, po_path, lang) } else { if (verbose) message(sprintf("Updating existing %s translation", lang)) - run_msgmerge(po_path, pot_path) + run_msgmerge(po_path, pot_path, previous = TRUE) } } From b205c342a63b8f60b807afb9e40cb8553c6859b1 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Mon, 1 Nov 2021 10:15:25 -0500 Subject: [PATCH 04/31] Fix typo --- R/msgmerge.R | 2 +- man/tr_add.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/msgmerge.R b/R/msgmerge.R index b14b36ca..5560f16b 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -93,7 +93,7 @@ update_en_quot_mo_files <- function(dir, verbose) { #' characters as used in mainland China, "zh_TW" = traditional characters #' as used in Taiwan.) #' @param dir Path to package root. -#' @param Verbose If `TRUE`, explain what's happening. +#' @param verbose If `TRUE`, explain what's happening. tr_add <- function(lang, dir = ".", verbose = TRUE) { package <- get_desc_data(dir)[["Package"]] diff --git a/man/tr_add.Rd b/man/tr_add.Rd index 3798b682..b9950b78 100644 --- a/man/tr_add.Rd +++ b/man/tr_add.Rd @@ -16,7 +16,7 @@ as used in Taiwan.)} \item{dir}{Path to package root.} -\item{Verbose}{If `TRUE`, explain what's happening.} +\item{verbose}{If `TRUE`, explain what's happening.} } \description{ This creates `po/{lang}.po` containing the messages to be translated. From 6124465caa7b555ba7e2aecdcae240ecacdcb507 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Thu, 4 Nov 2021 08:17:47 -0500 Subject: [PATCH 05/31] Split tr_add() into po_create() and po_update() --- NAMESPACE | 3 ++- R/msgmerge.R | 44 +++++++++++++++++++++++---------- man/{tr_add.Rd => po_create.Rd} | 18 ++++++++++---- 3 files changed, 46 insertions(+), 19 deletions(-) rename man/{tr_add.Rd => po_create.Rd} (50%) diff --git a/NAMESPACE b/NAMESPACE index 9f16835b..dd8e6cc9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -11,7 +11,8 @@ export(translate_package) export(get_message_data) export(write_po_file, po_metadata) -export(tr_add) +export(po_create) +export(po_update) export(check_cracked_messages, check_untranslated_cat, check_untranslated_src) diff --git a/R/msgmerge.R b/R/msgmerge.R index 5560f16b..d5679ad9 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -82,9 +82,15 @@ update_en_quot_mo_files <- function(dir, verbose) { -#' Add a new translation +#' Create or update a `.po` file containing translations #' -#' This creates `po/{lang}.po` containing the messages to be translated. +#' @description +#' * `po_create()` creates a new `po/{lang}.po` containing the messages to be +#' translated. +#' * `po_update()` updates an existing `.po` file after the messages in a +#' package have changed. The translations for existing messages are preserved; +#' new messages are added; and translations for deleted message are marked +#' as deprecated and moved to the bottom of the file. #' #' @param lang Language identifiers. These are typically two letters (e.g. #' "en" = English, "fr" = French, "es" = Spanish, "zh" = Chinese), but @@ -94,19 +100,31 @@ update_en_quot_mo_files <- function(dir, verbose) { #' as used in Taiwan.) #' @param dir Path to package root. #' @param verbose If `TRUE`, explain what's happening. -tr_add <- function(lang, dir = ".", verbose = TRUE) { +po_create <- function(lang, dir = ".", verbose = TRUE) { package <- get_desc_data(dir)[["Package"]] + po_path <- po_path(dir, lang) + if (file.exists(po_path)) { + po_update(lang, dir = dir, verbose = verbose) + return(invisible()) + } - pot_path <- file.path(dir, "po", paste0("R-", package, ".pot")) - po_path <- file.path(dir, "po", paste0("R-", lang, ".po")) + if (verbose) messagef("Adding new %s translation", lang) + run_msginit(pot_path(dir, package), po_path, lang) +} - if (!file.exists(po_path)) { - if (verbose) message(sprintf("Adding new %s translation", lang)) - run_msginit(pot_path, po_path, lang) - } else { - if (verbose) message(sprintf("Updating existing %s translation", lang)) - run_msgmerge(po_path, pot_path, previous = TRUE) - } +#' @rdname po_create +po_update <- function(lang, dir = ".", verbose = TRUE) { + package <- get_desc_data(dir)[["Package"]] + + if (verbose) messagef("Updating existing %s translation", lang) + run_msgmerge(po_path(dir, lang), pot_path(dir, package), previous = TRUE) +} + +po_path <- function(dir, lang) { + file.path(dir, "po", paste0("R-", lang, ".po")) +} +pot_path <- function(dir, package) { + file.path(dir, "po", paste0("R-", package, ".pot")) } # https://www.gnu.org/software/gettext/manual/html_node/msginit-Invocation.html @@ -119,7 +137,7 @@ run_msginit <- function(pot_path, po_path, locale, width = 80) { "--no-translator" # don't consult user-email etc ) if (system(cmd) != 0L) { - stop(sprintf("running msginit on '%s' failed", pot_path)) + stopf("running msginit on '%s' failed", pot_path) } return(invisible()) } diff --git a/man/tr_add.Rd b/man/po_create.Rd similarity index 50% rename from man/tr_add.Rd rename to man/po_create.Rd index b9950b78..c2aa9ef5 100644 --- a/man/tr_add.Rd +++ b/man/po_create.Rd @@ -1,10 +1,13 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/msgmerge.R -\name{tr_add} -\alias{tr_add} -\title{Add a new translation} +\name{po_create} +\alias{po_create} +\alias{po_update} +\title{Create or update a `.po` file containing translations} \usage{ -tr_add(lang, dir = ".", verbose = TRUE) +po_create(lang, dir = ".", verbose = TRUE) + +po_update(lang, dir = ".", verbose = TRUE) } \arguments{ \item{lang}{Language identifiers. These are typically two letters (e.g. @@ -19,5 +22,10 @@ as used in Taiwan.)} \item{verbose}{If `TRUE`, explain what's happening.} } \description{ -This creates `po/{lang}.po` containing the messages to be translated. +* `po_create()` creates a new `po/{lang}.po` containing the messages to be + translated. +* `po_update()` updates an existing `.po` file after the messages in a + package have changed. The translations for existing messages are preserved; + new messages are added; and translations for deleted message are marked + as deprecated and moved to the bottom of the file. } From c644cb789bb007b4303dace1b64c7ae5c4336a4a Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sat, 6 Nov 2021 15:19:21 -0700 Subject: [PATCH 06/31] lang->languages --- R/msgmerge.R | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/R/msgmerge.R b/R/msgmerge.R index d5679ad9..4d16b30d 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -85,14 +85,14 @@ update_en_quot_mo_files <- function(dir, verbose) { #' Create or update a `.po` file containing translations #' #' @description -#' * `po_create()` creates a new `po/{lang}.po` containing the messages to be +#' * `po_create()` creates a new `po/{languages}.po` containing the messages to be #' translated. #' * `po_update()` updates an existing `.po` file after the messages in a #' package have changed. The translations for existing messages are preserved; #' new messages are added; and translations for deleted message are marked #' as deprecated and moved to the bottom of the file. #' -#' @param lang Language identifiers. These are typically two letters (e.g. +#' @param languages Language identifiers. These are typically two letters (e.g. #' "en" = English, "fr" = French, "es" = Spanish, "zh" = Chinese), but #' can include an additional suffix for languages that have regional #' variations (e.g. "fr_CN" = French Canadian, "zh_CN" = simplified @@ -100,24 +100,24 @@ update_en_quot_mo_files <- function(dir, verbose) { #' as used in Taiwan.) #' @param dir Path to package root. #' @param verbose If `TRUE`, explain what's happening. -po_create <- function(lang, dir = ".", verbose = TRUE) { +po_create <- function(languages, dir = ".", verbose = TRUE) { package <- get_desc_data(dir)[["Package"]] - po_path <- po_path(dir, lang) + po_path <- po_path(dir, languages) if (file.exists(po_path)) { - po_update(lang, dir = dir, verbose = verbose) + po_update(languages, dir = dir, verbose = verbose) return(invisible()) } - if (verbose) messagef("Adding new %s translation", lang) - run_msginit(pot_path(dir, package), po_path, lang) + if (verbose) messagef("Adding new %s translation", languages) + run_msginit(pot_path(dir, package), po_path, languages) } #' @rdname po_create -po_update <- function(lang, dir = ".", verbose = TRUE) { +po_update <- function(languages, dir = ".", verbose = TRUE) { package <- get_desc_data(dir)[["Package"]] - if (verbose) messagef("Updating existing %s translation", lang) - run_msgmerge(po_path(dir, lang), pot_path(dir, package), previous = TRUE) + if (verbose) messagef("Updating existing %s translation", languages) + run_msgmerge(po_path(dir, languages), pot_path(dir, package), previous = TRUE) } po_path <- function(dir, lang) { From a088663ca77b1d3e794a15ba4321116e51fbb474 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sat, 6 Nov 2021 15:19:52 -0700 Subject: [PATCH 07/31] lang->languages --- man/po_create.Rd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/man/po_create.Rd b/man/po_create.Rd index c2aa9ef5..e94f2c7b 100644 --- a/man/po_create.Rd +++ b/man/po_create.Rd @@ -5,12 +5,12 @@ \alias{po_update} \title{Create or update a `.po` file containing translations} \usage{ -po_create(lang, dir = ".", verbose = TRUE) +po_create(languages, dir = ".", verbose = TRUE) -po_update(lang, dir = ".", verbose = TRUE) +po_update(languages, dir = ".", verbose = TRUE) } \arguments{ -\item{lang}{Language identifiers. These are typically two letters (e.g. +\item{languages}{Language identifiers. These are typically two letters (e.g. "en" = English, "fr" = French, "es" = Spanish, "zh" = Chinese), but can include an additional suffix for languages that have regional variations (e.g. "fr_CN" = French Canadian, "zh_CN" = simplified @@ -22,7 +22,7 @@ as used in Taiwan.)} \item{verbose}{If `TRUE`, explain what's happening.} } \description{ -* `po_create()` creates a new `po/{lang}.po` containing the messages to be +* `po_create()` creates a new `po/{languages}.po` containing the messages to be translated. * `po_update()` updates an existing `.po` file after the messages in a package have changed. The translations for existing messages are preserved; From 10e16fdeb858cff9998600da9b63ff22ec820e1a Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Nov 2021 08:46:59 -0600 Subject: [PATCH 08/31] Mark .pot file as UTF-8 --- R/write_po_file.R | 2 +- po/R-potools.pot | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/write_po_file.R b/R/write_po_file.R index f1cdb8f1..01be6041 100644 --- a/R/write_po_file.R +++ b/R/write_po_file.R @@ -300,7 +300,7 @@ format.po_metadata = function(x, template = FALSE, use_plurals = FALSE, ...) { x$email = "EMAIL@ADDRESS" x$language = '' x$language_team = "LANGUAGE " - x$charset = 'CHARSET' + x$charset = 'UTF-8' } if (is.character(x$copyright)) { x$copyright = list(years = format(x$pot_timestamp, "%Y"), holder = x$copyright) diff --git a/po/R-potools.pot b/po/R-potools.pot index f892fa53..1f8a03eb 100644 --- a/po/R-potools.pot +++ b/po/R-potools.pot @@ -8,7 +8,7 @@ msgstr "" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: find_fuzzy_messages.R:6 From 42885b110f92b61fe278dca29c0faa533a383ec7 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Nov 2021 08:58:39 -0600 Subject: [PATCH 09/31] Split po_create() and po_update() into pieces And fundamentally change approach --- R/msgmerge.R | 2 +- R/po_compile.R | 5 +++-- R/po_create.R | 47 ++++++++++++++++++++++++++++++++++++++++++++ R/po_create_update.R | 38 ----------------------------------- R/po_extract.R | 4 ++++ R/po_update.R | 25 +++++++++++++++++++++++ man/po_compile.Rd | 4 ++-- man/po_create.Rd | 35 +++++++++++++++++++++------------ man/po_extract.Rd | 3 +++ 9 files changed, 107 insertions(+), 56 deletions(-) create mode 100644 R/po_create.R delete mode 100644 R/po_create_update.R create mode 100644 R/po_update.R diff --git a/R/msgmerge.R b/R/msgmerge.R index 03689f31..77e7a505 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -1,7 +1,7 @@ # split off from tools::update_pkg_po() to only run the msgmerge & checkPoFile steps # https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html -run_msgmerge = function(po_file, pot_file, previous = FALSE) { +run_msgmerge = function(pot_file, po_file, previous = FALSE) { cmd <- paste("msgmerge", "--update", if (previous) "--previous", # show previous match for fuzzy matches diff --git a/R/po_compile.R b/R/po_compile.R index 82394021..000ae627 100644 --- a/R/po_compile.R +++ b/R/po_compile.R @@ -6,8 +6,8 @@ #' #' @param dir Path to package root directory. #' @param package Name of package. If not supplied, read from `DESCRIPTION`. -#' @param lazy If `TRUE`, only `.mo` functions that are older than `.po` -#' files be updated +#' @param lazy If `TRUE`, only `.mo` files that are older than their +#' corresponding`.po` file will be updated. #' @param verbose If `TRUE`, print information as it goes. po_compile = function(dir = ".", package = NULL, lazy = TRUE, verbose = TRUE) { po_metadata <- get_po_metadata(dir = dir, package = package) @@ -57,6 +57,7 @@ get_po_metadata <- function(dir = ".", package = NULL) { language = languages, type = type, po = po_paths, + pot = pot_paths(dir, type), mo = mo_paths ) } diff --git a/R/po_create.R b/R/po_create.R new file mode 100644 index 00000000..814fc149 --- /dev/null +++ b/R/po_create.R @@ -0,0 +1,47 @@ +#' Create a new `.po` file +#' +#' `po_create()` creates a new `po/{languages}.po` containing the messages to be +#' translated. If a translation already exists, it'll be updated with any +#' changes to the `.pot` since it was last touched. +#' +#' @param languages Language identifiers. These are typically two letters (e.g. +#' "en" = English, "fr" = French, "es" = Spanish, "zh" = Chinese), but +#' can include an additional suffix for languages that have regional +#' variations (e.g. "fr_CN" = French Canadian, "zh_CN" = simplified +#' characters as used in mainland China, "zh_TW" = traditional characters +#' as used in Taiwan.) +#' @inheritParams po_extract +#' @seealso [po_update()] to update all `.po` files with changes from the +#' `.pot`. +po_create <- function(languages, dir = ".", verbose = !is_testing()) { + package <- get_desc_data(dir, "Package") + + po_files <- data.table::CJ(type = pot_types(dir), language = languages) + po_files[, "po_path" := file.path(dir, "po", paste0(po_prefix(po_files$type), po_files$language, ".po"))] + po_files[, "pot_path" := pot_paths(dir, po_files$type)] + + for (ii in seq_along(nrow(po_files))) { + row <- po_files[ii] + if (file.exists(row$po_path)) { + if (verbose) messagef("Updating '%s' %s translation", row$language, row$type) + run_msgmerge(row$pot_path, row$po_path, previous = TRUE) + } else { + if (verbose) messagef("Creating '%s' %s translation", row$language, row$type) + run_msginit(row$pot_path, row$po_path, locale = row$language) + } + } + + invisible(po_files) +} + +pot_paths <- function(dir, type) { + package <- get_desc_data(dir, "Package") + file.path(dir, "po", paste0(po_prefix(type), package, ".pot")) +} +po_prefix <- function(type = c("R", "src")) { + ifelse(type == "R", "R-", "") +} +pot_types <- function(dir = ".") { + types <- c("R", "src") + types[file.exists(pot_paths(dir, types))] +} diff --git a/R/po_create_update.R b/R/po_create_update.R deleted file mode 100644 index 92830436..00000000 --- a/R/po_create_update.R +++ /dev/null @@ -1,38 +0,0 @@ - -#' Create or update a `.po` file containing translations -#' -#' @description -#' * `po_create()` creates a new `po/{languages}.po` containing the messages to be -#' translated. -#' * `po_update()` updates an existing `.po` file after the messages in a -#' package have changed. The translations for existing messages are preserved; -#' new messages are added; and translations for deleted message are marked -#' as deprecated and moved to the bottom of the file. -#' -#' @param languages Language identifiers. These are typically two letters (e.g. -#' "en" = English, "fr" = French, "es" = Spanish, "zh" = Chinese), but -#' can include an additional suffix for languages that have regional -#' variations (e.g. "fr_CN" = French Canadian, "zh_CN" = simplified -#' characters as used in mainland China, "zh_TW" = traditional characters -#' as used in Taiwan.) -#' @param dir Path to package root. -#' @param verbose If `TRUE`, explain what's happening. -po_create <- function(languages, dir = ".", verbose = TRUE) { - package <- get_desc_data(dir)[["Package"]] - po_path <- po_path(dir, languages) - if (file.exists(po_path)) { - po_update(languages, dir = dir, verbose = verbose) - return(invisible()) - } - - if (verbose) messagef("Adding new %s translation", languages) - run_msginit(pot_path(dir, package), po_path, languages) -} - -#' @rdname po_create -po_update <- function(languages, dir = ".", verbose = TRUE) { - package <- get_desc_data(dir)[["Package"]] - - if (verbose) messagef("Updating existing %s translation", languages) - run_msgmerge(po_path(dir, languages), pot_path(dir, package), previous = TRUE) -} diff --git a/R/po_extract.R b/R/po_extract.R index a59ee84f..f0389fb9 100644 --- a/R/po_extract.R +++ b/R/po_extract.R @@ -1,10 +1,14 @@ #' Extract messages for translation into a `.pot` file #' +#' @description #' `po_extract()` scans your package for strings to be translated and #' saves them into a `.pot` template file (in the package's `po` directory). #' You should never modify this file by hand; instead modify the underlying #' source code and re-run `po_extract()`. #' +#' If you have existing translations, call [po_update()] after [po_extract()] +#' to update them with the changes. +#' #' @returns The extracted messages as computed by [get_message_data()], #' invisibly. #' @inheritParams get_message_data diff --git a/R/po_update.R b/R/po_update.R new file mode 100644 index 00000000..6537713e --- /dev/null +++ b/R/po_update.R @@ -0,0 +1,25 @@ +#' Update all `.po` files with changes in `.pot` +#' +#' `po_update()` updates existing `.po` file after the `.pot` file has changed. +#' The translations for existing messages are preserved; new messages are added; +#' and translations for deleted message are marked as deprecated and moved to +#' the bottom of the file. +#' +#' @inheritParams po_extract +#' @param lazy If `TRUE`, only `.po` files that are older than their +#' corresponding `.pot` file will be updated +#' @rdname po_create +po_update <- function(dir = ".", lazy = TRUE, verbose = !is_testing()) { + meta <- get_po_metadata(dir) + if (lazy) { + meta <- meta[is_outdated(meta$po, meta$pot)] + } + + for (ii in seq_len(nrow(meta))) { + row <- meta[ii] + if (verbose) messagef("Updating '%s' %s translation", row$language, row$type) + run_msgmerge(row$po, row$pot, previous = TRUE) + } + + invisible(meta) +} diff --git a/man/po_compile.Rd b/man/po_compile.Rd index 7c09d32d..8b0766b6 100644 --- a/man/po_compile.Rd +++ b/man/po_compile.Rd @@ -11,8 +11,8 @@ po_compile(dir = ".", package = NULL, lazy = TRUE, verbose = TRUE) \item{package}{Name of package. If not supplied, read from \code{DESCRIPTION}.} -\item{lazy}{If \code{TRUE}, only \code{.mo} functions that are older than \code{.po} -files be updated} +\item{lazy}{If \code{TRUE}, only \code{.mo} files that are older than their +corresponding\code{.po} file will be updated.} \item{verbose}{If \code{TRUE}, print information as it goes.} } diff --git a/man/po_create.Rd b/man/po_create.Rd index 1c8cb104..ad4f5394 100644 --- a/man/po_create.Rd +++ b/man/po_create.Rd @@ -1,13 +1,13 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/po_create_update.R +% Please edit documentation in R/po_create.R, R/po_update.R \name{po_create} \alias{po_create} \alias{po_update} -\title{Create or update a \code{.po} file containing translations} +\title{Create a new \code{.po} file} \usage{ -po_create(languages, dir = ".", verbose = TRUE) +po_create(languages, dir = ".", verbose = !is_testing()) -po_update(languages, dir = ".", verbose = TRUE) +po_update(dir = ".", lazy = TRUE, verbose = !is_testing()) } \arguments{ \item{languages}{Language identifiers. These are typically two letters (e.g. @@ -17,17 +17,26 @@ variations (e.g. "fr_CN" = French Canadian, "zh_CN" = simplified characters as used in mainland China, "zh_TW" = traditional characters as used in Taiwan.)} -\item{dir}{Path to package root.} +\item{dir}{Character, default the present directory; a directory in which +an R package is stored.} -\item{verbose}{If \code{TRUE}, explain what's happening.} +\item{verbose}{Logical, default \code{TRUE} (except during testing). Should +extra information about progress, etc. be reported?} + +\item{lazy}{If \code{TRUE}, only \code{.po} files that are older than their +corresponding \code{.pot} file will be updated} } \description{ -\itemize{ -\item \code{po_create()} creates a new \verb{po/\{languages\}.po} containing the messages to be -translated. -\item \code{po_update()} updates an existing \code{.po} file after the messages in a -package have changed. The translations for existing messages are preserved; -new messages are added; and translations for deleted message are marked -as deprecated and moved to the bottom of the file. +\code{po_create()} creates a new \verb{po/\{languages\}.po} containing the messages to be +translated. If a translation already exists, it'll be updated with any +changes to the \code{.pot} since it was last touched. + +\code{po_update()} updates existing \code{.po} file after the \code{.pot} file has changed. +The translations for existing messages are preserved; new messages are added; +and translations for deleted message are marked as deprecated and moved to +the bottom of the file. } +\seealso{ +\code{\link[=po_update]{po_update()}} to update all \code{.po} files with changes from the +\code{.pot}. } diff --git a/man/po_extract.Rd b/man/po_extract.Rd index c9f1193b..6a0fc0dd 100644 --- a/man/po_extract.Rd +++ b/man/po_extract.Rd @@ -46,4 +46,7 @@ invisibly. saves them into a \code{.pot} template file (in the package's \code{po} directory). You should never modify this file by hand; instead modify the underlying source code and re-run \code{po_extract()}. + +If you have existing translations, call \code{\link[=po_update]{po_update()}} after \code{\link[=po_extract]{po_extract()}} +to update them with the changes. } From 205ee8fb2eb6e8aa534a97fc06504a586cdbf965 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Nov 2021 09:02:30 -0600 Subject: [PATCH 10/31] Fix broken tests --- R/msgmerge.R | 4 ++-- R/po_compile.R | 3 ++- R/po_create.R | 10 ++++++---- tests/testthat/test-write-po-file.R | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/R/msgmerge.R b/R/msgmerge.R index 77e7a505..e0dafe80 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -1,7 +1,7 @@ # split off from tools::update_pkg_po() to only run the msgmerge & checkPoFile steps # https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html -run_msgmerge = function(pot_file, po_file, previous = FALSE) { +run_msgmerge = function(po_file, pot_file, previous = FALSE) { cmd <- paste("msgmerge", "--update", if (previous) "--previous", # show previous match for fuzzy matches @@ -65,7 +65,7 @@ update_en_quot_mo_files <- function(dir, verbose) { } # https://www.gnu.org/software/gettext/manual/html_node/msginit-Invocation.html -run_msginit <- function(pot_path, po_path, locale, width = 80) { +run_msginit <- function(po_path, pot_path, locale, width = 80) { cmd <- paste("msginit", "-i", shQuote(path.expand(pot_path)), "-o", shQuote(path.expand(po_path)), diff --git a/R/po_compile.R b/R/po_compile.R index 000ae627..1b85dfa3 100644 --- a/R/po_compile.R +++ b/R/po_compile.R @@ -52,12 +52,13 @@ get_po_metadata <- function(dir = ".", package = NULL) { mo_names <- gsub(lang_regex, sprintf("\\1%s.mo", package), basename(po_paths)) mo_paths <- file.path(dir, "inst", "po", languages, "LC_MESSAGES", mo_names) + pot_paths <- pot_paths(dir, type, package = package) data.table( language = languages, type = type, po = po_paths, - pot = pot_paths(dir, type), + pot = pot_paths, mo = mo_paths ) } diff --git a/R/po_create.R b/R/po_create.R index 814fc149..cf8fb47f 100644 --- a/R/po_create.R +++ b/R/po_create.R @@ -24,18 +24,20 @@ po_create <- function(languages, dir = ".", verbose = !is_testing()) { row <- po_files[ii] if (file.exists(row$po_path)) { if (verbose) messagef("Updating '%s' %s translation", row$language, row$type) - run_msgmerge(row$pot_path, row$po_path, previous = TRUE) + run_msgmerge(row$po_path, row$pot_path, previous = TRUE) } else { if (verbose) messagef("Creating '%s' %s translation", row$language, row$type) - run_msginit(row$pot_path, row$po_path, locale = row$language) + run_msginit(row$po_path, row$pot_path, locale = row$language) } } invisible(po_files) } -pot_paths <- function(dir, type) { - package <- get_desc_data(dir, "Package") +pot_paths <- function(dir, type, package = NULL) { + if (is.null(package)) { + package <- get_desc_data(dir, "Package") + } file.path(dir, "po", paste0(po_prefix(type), package, ".pot")) } po_prefix <- function(type = c("R", "src")) { diff --git a/tests/testthat/test-write-po-file.R b/tests/testthat/test-write-po-file.R index cbf4b26e..0af385a1 100644 --- a/tests/testthat/test-write-po-file.R +++ b/tests/testthat/test-write-po-file.R @@ -12,7 +12,7 @@ test_that("po_metadata constructor & methods work", { format(metadata, template = TRUE), c( '"Language-Team: LANGUAGE \\n"', - '"Content-Type: text/plain; charset=CHARSET\\n"', + '"Content-Type: text/plain; charset=UTF-8\\n"', '# SOME DESCRIPTIVE TITLE.', '# This file is distributed under the same license as the R package.', '# FIRST AUTHOR , YEAR.' From 0d3391d891196717bcec75d1ebfdfc929a286b6f Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Nov 2021 12:58:20 -0600 Subject: [PATCH 11/31] Add test for po_create() Bringing in system2() code from #257 --- R/msgmerge.R | 35 +++++++++++++++--------------- R/po_create.R | 4 ++-- tests/testthat/_snaps/po_create.md | 18 +++++++++++++++ tests/testthat/test-po_create.R | 10 +++++++++ 4 files changed, 48 insertions(+), 19 deletions(-) create mode 100644 tests/testthat/_snaps/po_create.md create mode 100644 tests/testthat/test-po_create.R diff --git a/R/msgmerge.R b/R/msgmerge.R index e0dafe80..2186f83b 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -1,25 +1,23 @@ # split off from tools::update_pkg_po() to only run the msgmerge & checkPoFile steps # https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html -run_msgmerge = function(po_file, pot_file, previous = FALSE) { - cmd <- paste("msgmerge", - "--update", - if (previous) "--previous", # show previous match for fuzzy matches - shQuote(path.expand(po_file)), +run_msgmerge <- function(po_file, pot_file, previous = FALSE, verbose = TRUE) { + args <- c( + "--update", shQuote(path.expand(po_file)), + if (previous) "--previous", #show previous match for fuzzy matches shQuote(path.expand(pot_file)) ) - if (system(cmd) != 0L) { + val <- system2("msgmerge", args, stdout = TRUE, stderr = TRUE) + if (!identical(attr(val, "status", exact = TRUE), NULL)) { # nocov these warnings? i don't know how to trigger them as of this writing. - warningf("Running msgmerge on '%s' failed.", po_file) + warningf("Running msgmerge on './po/%s' failed:\n %s", basename(po_file), paste(val, collapse = "\n")) + } else if (verbose) { + messagef("Running msgmerge on './po/%s' succeeded:\n %s", basename(po_file), paste(val, collapse = "\n")) } - res <- tools::checkPoFile(po_file, strictPlural = TRUE) - if (nrow(res)) { - warningf("tools::checkPoFile() found some issues in %s", po_file) - print(res) - } - return(invisible()) + tools::checkPoFile(po_file, strictPlural = TRUE) + invisible() } run_msgfmt = function(po_file, mo_file, verbose) { @@ -65,16 +63,19 @@ update_en_quot_mo_files <- function(dir, verbose) { } # https://www.gnu.org/software/gettext/manual/html_node/msginit-Invocation.html -run_msginit <- function(po_path, pot_path, locale, width = 80) { - cmd <- paste("msginit", +run_msginit <- function(po_path, pot_path, locale, width = 80, verbose = TRUE) { + args <- c( "-i", shQuote(path.expand(pot_path)), "-o", shQuote(path.expand(po_path)), "-l", shQuote(locale), "-w", width, "--no-translator" # don't consult user-email etc ) - if (system(cmd) != 0L) { - stopf("running msginit on '%s' failed", pot_path) + val <- system2("msginit", args, stdout = TRUE, stderr = TRUE) + if (!identical(attr(val, "status", exact = TRUE), NULL)) { + stopf("Running msginit on '%s' failed", pot_path) + } else if (verbose) { + messagef("Running msgint on './po/%s' succeeded:\n %s", basename(po_path), paste(val, collapse = "\n")) } return(invisible()) } diff --git a/R/po_create.R b/R/po_create.R index cf8fb47f..eca2a603 100644 --- a/R/po_create.R +++ b/R/po_create.R @@ -24,10 +24,10 @@ po_create <- function(languages, dir = ".", verbose = !is_testing()) { row <- po_files[ii] if (file.exists(row$po_path)) { if (verbose) messagef("Updating '%s' %s translation", row$language, row$type) - run_msgmerge(row$po_path, row$pot_path, previous = TRUE) + run_msgmerge(row$po_path, row$pot_path, previous = TRUE, verbose = verbose) } else { if (verbose) messagef("Creating '%s' %s translation", row$language, row$type) - run_msginit(row$po_path, row$pot_path, locale = row$language) + run_msginit(row$po_path, row$pot_path, locale = row$language, verbose = verbose) } } diff --git a/tests/testthat/_snaps/po_create.md b/tests/testthat/_snaps/po_create.md new file mode 100644 index 00000000..bae2d20f --- /dev/null +++ b/tests/testthat/_snaps/po_create.md @@ -0,0 +1,18 @@ +# multiplication works + + Code + po_create("jp", verbose = TRUE) + Message + Creating 'jp' R translation + Running msgint on './po/R-jp.po' succeeded: + Created ./po/R-jp.po. + +--- + + Code + po_create("jp", verbose = TRUE) + Message + Updating 'jp' R translation + Running msgmerge on './po/R-jp.po' succeeded: + . done. + diff --git a/tests/testthat/test-po_create.R b/tests/testthat/test-po_create.R new file mode 100644 index 00000000..cf827118 --- /dev/null +++ b/tests/testthat/test-po_create.R @@ -0,0 +1,10 @@ +test_that("multiplication works", { + temp <- withr::local_tempdir() + dir.create(file.path(temp, "po")) + file.create(file.path(temp, "po", "R-test.pot")) + writeLines("Package: test", file.path(temp, "DESCRIPTION")) + + withr::local_dir(temp) + expect_snapshot(po_create("jp", verbose = TRUE)) + expect_snapshot(po_create("jp", verbose = TRUE)) +}) From d8880e099a7e8c6cdee8badb6446fd608845ee55 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Nov 2021 13:00:59 -0600 Subject: [PATCH 12/31] WS --- R/po_compile.R | 2 +- man/po_compile.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/po_compile.R b/R/po_compile.R index 1b85dfa3..4259a2da 100644 --- a/R/po_compile.R +++ b/R/po_compile.R @@ -7,7 +7,7 @@ #' @param dir Path to package root directory. #' @param package Name of package. If not supplied, read from `DESCRIPTION`. #' @param lazy If `TRUE`, only `.mo` files that are older than their -#' corresponding`.po` file will be updated. +#' corresponding `.po` file will be updated. #' @param verbose If `TRUE`, print information as it goes. po_compile = function(dir = ".", package = NULL, lazy = TRUE, verbose = TRUE) { po_metadata <- get_po_metadata(dir = dir, package = package) diff --git a/man/po_compile.Rd b/man/po_compile.Rd index 8b0766b6..ba3bf51f 100644 --- a/man/po_compile.Rd +++ b/man/po_compile.Rd @@ -12,7 +12,7 @@ po_compile(dir = ".", package = NULL, lazy = TRUE, verbose = TRUE) \item{package}{Name of package. If not supplied, read from \code{DESCRIPTION}.} \item{lazy}{If \code{TRUE}, only \code{.mo} files that are older than their -corresponding\code{.po} file will be updated.} +corresponding \code{.po} file will be updated.} \item{verbose}{If \code{TRUE}, print information as it goes.} } From efa92b6af7b5b2d34eaab54d6797af3ce3605ef8 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Nov 2021 13:52:03 -0600 Subject: [PATCH 13/31] Extract out local_test_package() helper --- R/utils.R | 8 ++++++++ tests/testthat/test-po_compile.R | 5 ++--- tests/testthat/test-po_create.R | 4 +--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/R/utils.R b/R/utils.R index 80f8183f..2d397e8d 100644 --- a/R/utils.R +++ b/R/utils.R @@ -167,3 +167,11 @@ is_outdated <- function(src, dst) { } is_testing = function() identical(Sys.getenv("TESTTHAT"), "true") + +local_test_package <- function(.envir = parent.frame()) { + temp <- withr::local_tempdir(.local_envir = .envir) + dir.create(file.path(temp, "po")) + writeLines("Package: test", file.path(temp, "DESCRIPTION")) + + temp +} diff --git a/tests/testthat/test-po_compile.R b/tests/testthat/test-po_compile.R index 6ef6ced0..f7197ac9 100644 --- a/tests/testthat/test-po_compile.R +++ b/tests/testthat/test-po_compile.R @@ -1,11 +1,10 @@ # metadata ---------------------------------------------------------------- test_that("can find R and src translations", { - temp <- withr::local_tempdir() - dir.create(file.path(temp, "po")) + temp <- local_test_package() file.create(file.path(temp, "po", c("R-en.po", "en.po"))) - meta <- withr::with_dir(temp, get_po_metadata(package = "test")) + meta <- withr::with_dir(temp, get_po_metadata()) expect_equal(meta$language, c("en", "en")) expect_setequal(meta$type, c("R", "src")) }) diff --git a/tests/testthat/test-po_create.R b/tests/testthat/test-po_create.R index cf827118..723d6389 100644 --- a/tests/testthat/test-po_create.R +++ b/tests/testthat/test-po_create.R @@ -1,8 +1,6 @@ test_that("multiplication works", { - temp <- withr::local_tempdir() - dir.create(file.path(temp, "po")) + temp <- local_test_package() file.create(file.path(temp, "po", "R-test.pot")) - writeLines("Package: test", file.path(temp, "DESCRIPTION")) withr::local_dir(temp) expect_snapshot(po_create("jp", verbose = TRUE)) From 511fad199ab59b58778bf8a169c569a7b1a20ae4 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Nov 2021 13:53:54 -0600 Subject: [PATCH 14/31] Extract & test po_language_files() --- R/po_create.R | 12 ++++++++---- R/utils.R | 14 +++++++++++--- tests/testthat/_snaps/po_create.md | 2 +- tests/testthat/test-po_create.R | 22 +++++++++++++++++++++- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/R/po_create.R b/R/po_create.R index eca2a603..16799d30 100644 --- a/R/po_create.R +++ b/R/po_create.R @@ -15,10 +15,7 @@ #' `.pot`. po_create <- function(languages, dir = ".", verbose = !is_testing()) { package <- get_desc_data(dir, "Package") - - po_files <- data.table::CJ(type = pot_types(dir), language = languages) - po_files[, "po_path" := file.path(dir, "po", paste0(po_prefix(po_files$type), po_files$language, ".po"))] - po_files[, "pot_path" := pot_paths(dir, po_files$type)] + po_files <- po_language_files(languages, dir) for (ii in seq_along(nrow(po_files))) { row <- po_files[ii] @@ -34,6 +31,13 @@ po_create <- function(languages, dir = ".", verbose = !is_testing()) { invisible(po_files) } +po_language_files <- function(languages, dir = ".") { + po_files <- data.table::CJ(type = pot_types(dir), language = languages) + po_files[, "po_path" := file.path(dir, "po", paste0(po_prefix(po_files$type), po_files$language, ".po"))] + po_files[, "pot_path" := pot_paths(dir, po_files$type)] + po_files[] +} + pot_paths <- function(dir, type, package = NULL) { if (is.null(package)) { package <- get_desc_data(dir, "Package") diff --git a/R/utils.R b/R/utils.R index 2d397e8d..2d75db45 100644 --- a/R/utils.R +++ b/R/utils.R @@ -168,10 +168,18 @@ is_outdated <- function(src, dst) { is_testing = function() identical(Sys.getenv("TESTTHAT"), "true") -local_test_package <- function(.envir = parent.frame()) { +local_test_package <- function(..., .envir = parent.frame()) { temp <- withr::local_tempdir(.local_envir = .envir) - dir.create(file.path(temp, "po")) - writeLines("Package: test", file.path(temp, "DESCRIPTION")) + writeLines(con = file.path(temp, "DESCRIPTION"), c( + "Package: test", + "Version: 1.0.0" + )) + dir_create(file.path(temp, c("po", "R"))) + + files <- list(...) + for (i in seq_along(files)) { + writeLines(files[[i]], file.path(temp, names(files)[[i]])) + } temp } diff --git a/tests/testthat/_snaps/po_create.md b/tests/testthat/_snaps/po_create.md index bae2d20f..adabf6a5 100644 --- a/tests/testthat/_snaps/po_create.md +++ b/tests/testthat/_snaps/po_create.md @@ -1,4 +1,4 @@ -# multiplication works +# the user is told what's happening Code po_create("jp", verbose = TRUE) diff --git a/tests/testthat/test-po_create.R b/tests/testthat/test-po_create.R index 723d6389..447d4498 100644 --- a/tests/testthat/test-po_create.R +++ b/tests/testthat/test-po_create.R @@ -1,4 +1,4 @@ -test_that("multiplication works", { +test_that("the user is told what's happening", { temp <- local_test_package() file.create(file.path(temp, "po", "R-test.pot")) @@ -6,3 +6,23 @@ test_that("multiplication works", { expect_snapshot(po_create("jp", verbose = TRUE)) expect_snapshot(po_create("jp", verbose = TRUE)) }) + +test_that("can generate both R and src pot files", { + temp <- local_test_package() + file.create(file.path(temp, "po", c("R-test.pot", "test.pot"))) + + expect_equal(pot_types(temp), c("R", "src")) + + files <- withr::with_dir(temp, po_language_files("en")) + expect_equal(files$type, c("R", "src")) + expect_equal(files$po_path, file.path(".", "po", c("R-en.po", "en.po"))) + expect_equal(files$pot_path, file.path(".", "po", c("R-test.pot", "test.pot"))) +}) + +test_that("can create multiple languages", { + temp <- local_test_package() + file.create(file.path(temp, "po", c("R-test.pot", "test.pot"))) + + files <- withr::with_dir(temp, po_language_files(c("en", "jp", "ar"))) + expect_equal(nrow(files), 6) +}) From d7c388225c4bc0eea3608b31abfb9d464bdc1ff3 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Nov 2021 14:08:28 -0600 Subject: [PATCH 15/31] Add tests for create and update And fix the bugs thus revealed --- R/po_create.R | 9 +++++++-- tests/testthat/_snaps/po_update.md | 12 ++++++++++++ tests/testthat/test-po_compile.R | 5 +++++ tests/testthat/test-po_update.R | 9 +++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 tests/testthat/_snaps/po_update.md create mode 100644 tests/testthat/test-po_update.R diff --git a/R/po_create.R b/R/po_create.R index 16799d30..ff9ff3f0 100644 --- a/R/po_create.R +++ b/R/po_create.R @@ -17,7 +17,7 @@ po_create <- function(languages, dir = ".", verbose = !is_testing()) { package <- get_desc_data(dir, "Package") po_files <- po_language_files(languages, dir) - for (ii in seq_along(nrow(po_files))) { + for (ii in seq_len(nrow(po_files))) { row <- po_files[ii] if (file.exists(row$po_path)) { if (verbose) messagef("Updating '%s' %s translation", row$language, row$type) @@ -42,7 +42,12 @@ pot_paths <- function(dir, type, package = NULL) { if (is.null(package)) { package <- get_desc_data(dir, "Package") } - file.path(dir, "po", paste0(po_prefix(type), package, ".pot")) + if (length(type) == 0) { + character() + } else { + file.path(dir, "po", paste0(po_prefix(type), package, ".pot")) + } + } po_prefix <- function(type = c("R", "src")) { ifelse(type == "R", "R-", "") diff --git a/tests/testthat/_snaps/po_update.md b/tests/testthat/_snaps/po_update.md new file mode 100644 index 00000000..3f949272 --- /dev/null +++ b/tests/testthat/_snaps/po_update.md @@ -0,0 +1,12 @@ +# user is told what's happening + + Code + po_update(verbose = TRUE, lazy = FALSE) + Message + Updating 'fr' R translation + Running msgmerge on './po/R-fr.po' succeeded: + . done. + Updating 'ja' R translation + Running msgmerge on './po/R-ja.po' succeeded: + . done. + diff --git a/tests/testthat/test-po_compile.R b/tests/testthat/test-po_compile.R index f7197ac9..34f3b53e 100644 --- a/tests/testthat/test-po_compile.R +++ b/tests/testthat/test-po_compile.R @@ -8,3 +8,8 @@ test_that("can find R and src translations", { expect_equal(meta$language, c("en", "en")) expect_setequal(meta$type, c("R", "src")) }) + +test_that("get_po_metadata() returns 0 rows if no .po fles", { + meta <- get_po_metadata(temp) + expect_equal(nrow(meta), 0) +}) diff --git a/tests/testthat/test-po_update.R b/tests/testthat/test-po_update.R new file mode 100644 index 00000000..30a1c476 --- /dev/null +++ b/tests/testthat/test-po_update.R @@ -0,0 +1,9 @@ +test_that("user is told what's happening", { + temp <- local_test_package("R/test.r" = "message('Hello')") + withr::local_dir(temp) + + po_extract() + po_create(c("ja", "fr")) + + expect_snapshot(po_update(verbose = TRUE, lazy = FALSE)) +}) From 0daabcdc37ca465d954a2b0a6a8e41f5c366b0ef Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 9 Nov 2021 14:14:39 -0600 Subject: [PATCH 16/31] Add missing line --- tests/testthat/test-po_compile.R | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/testthat/test-po_compile.R b/tests/testthat/test-po_compile.R index 34f3b53e..589b144b 100644 --- a/tests/testthat/test-po_compile.R +++ b/tests/testthat/test-po_compile.R @@ -10,6 +10,7 @@ test_that("can find R and src translations", { }) test_that("get_po_metadata() returns 0 rows if no .po fles", { + temp <- local_test_package() meta <- get_po_metadata(temp) expect_equal(nrow(meta), 0) }) From b60428122bb533eb955bff7100da026a2edb88d1 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Tue, 9 Nov 2021 17:52:22 -0800 Subject: [PATCH 17/31] might as well use fifelse --- R/po_create.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/po_create.R b/R/po_create.R index ff9ff3f0..6dd8926d 100644 --- a/R/po_create.R +++ b/R/po_create.R @@ -50,7 +50,7 @@ pot_paths <- function(dir, type, package = NULL) { } po_prefix <- function(type = c("R", "src")) { - ifelse(type == "R", "R-", "") + data.table::fifelse(type == "R", "R-", "") } pot_types <- function(dir = ".") { types <- c("R", "src") From ef5449f8b3e495982b9852114b9c8bd6942606a6 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 10 Nov 2021 06:05:56 -0600 Subject: [PATCH 18/31] Add links to solaris docs --- R/msgmerge.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/msgmerge.R b/R/msgmerge.R index 2186f83b..77659d80 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -1,6 +1,7 @@ # split off from tools::update_pkg_po() to only run the msgmerge & checkPoFile steps # https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html +# https://docs.oracle.com/cd/E36784_01/html/E36870/msgmerge-1.html#scrolltoc run_msgmerge <- function(po_file, pot_file, previous = FALSE, verbose = TRUE) { args <- c( "--update", shQuote(path.expand(po_file)), @@ -63,6 +64,7 @@ update_en_quot_mo_files <- function(dir, verbose) { } # https://www.gnu.org/software/gettext/manual/html_node/msginit-Invocation.html +# https://docs.oracle.com/cd/E36784_01/html/E36870/msginit-1.html#scrolltoc run_msginit <- function(po_path, pot_path, locale, width = 80, verbose = TRUE) { args <- c( "-i", shQuote(path.expand(pot_path)), From 7322e5561b5cc2312371297f4efa69543554e2c5 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 10 Nov 2021 06:07:57 -0600 Subject: [PATCH 19/31] Revert unintentional change --- R/msgmerge.R | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/R/msgmerge.R b/R/msgmerge.R index 77659d80..424cd7af 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -17,8 +17,12 @@ run_msgmerge <- function(po_file, pot_file, previous = FALSE, verbose = TRUE) { messagef("Running msgmerge on './po/%s' succeeded:\n %s", basename(po_file), paste(val, collapse = "\n")) } - tools::checkPoFile(po_file, strictPlural = TRUE) - invisible() + res <- tools::checkPoFile(po_file, strictPlural = TRUE) + if (nrow(res)) { + warningf("tools::checkPoFile() found some issues in %s", po_file) + print(res) + } + return(invisible()) } run_msgfmt = function(po_file, mo_file, verbose) { From 78afb31c36a53d0be1fd50408a2dae4504536d6e Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 10 Nov 2021 06:08:42 -0600 Subject: [PATCH 20/31] Move local_test_package() to better home --- R/utils.R | 16 ---------------- tests/testthat/helpers.R | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/R/utils.R b/R/utils.R index 2d75db45..80f8183f 100644 --- a/R/utils.R +++ b/R/utils.R @@ -167,19 +167,3 @@ is_outdated <- function(src, dst) { } is_testing = function() identical(Sys.getenv("TESTTHAT"), "true") - -local_test_package <- function(..., .envir = parent.frame()) { - temp <- withr::local_tempdir(.local_envir = .envir) - writeLines(con = file.path(temp, "DESCRIPTION"), c( - "Package: test", - "Version: 1.0.0" - )) - dir_create(file.path(temp, c("po", "R"))) - - files <- list(...) - for (i in seq_along(files)) { - writeLines(files[[i]], file.path(temp, names(files)[[i]])) - } - - temp -} diff --git a/tests/testthat/helpers.R b/tests/testthat/helpers.R index acd9ed1b..95c439a4 100644 --- a/tests/testthat/helpers.R +++ b/tests/testthat/helpers.R @@ -48,3 +48,19 @@ expect_messages = function(expr, msgs, ..., invert=FALSE) { test_package = function(pkg) test_path(file.path("test_packages", pkg)) mock_translation = function(mocks) test_path(file.path("mock_translations", mocks)) + +local_test_package <- function(..., .envir = parent.frame()) { + temp <- withr::local_tempdir(.local_envir = .envir) + writeLines(con = file.path(temp, "DESCRIPTION"), c( + "Package: test", + "Version: 1.0.0" + )) + dir_create(file.path(temp, c("po", "R"))) + + files <- list(...) + for (i in seq_along(files)) { + writeLines(files[[i]], file.path(temp, names(files)[[i]])) + } + + temp +} From 7133453ca6706f07654877840fe83b89be6fd381 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 10 Nov 2021 06:21:12 -0600 Subject: [PATCH 21/31] Revert CHARSET -> UTF-8 change --- R/write_po_file.R | 2 +- po/R-potools.pot | 2 +- tests/testthat/test-write-po-file.R | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/R/write_po_file.R b/R/write_po_file.R index 01be6041..f1cdb8f1 100644 --- a/R/write_po_file.R +++ b/R/write_po_file.R @@ -300,7 +300,7 @@ format.po_metadata = function(x, template = FALSE, use_plurals = FALSE, ...) { x$email = "EMAIL@ADDRESS" x$language = '' x$language_team = "LANGUAGE " - x$charset = 'UTF-8' + x$charset = 'CHARSET' } if (is.character(x$copyright)) { x$copyright = list(years = format(x$pot_timestamp, "%Y"), holder = x$copyright) diff --git a/po/R-potools.pot b/po/R-potools.pot index 1f8a03eb..f892fa53 100644 --- a/po/R-potools.pot +++ b/po/R-potools.pot @@ -8,7 +8,7 @@ msgstr "" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: find_fuzzy_messages.R:6 diff --git a/tests/testthat/test-write-po-file.R b/tests/testthat/test-write-po-file.R index 0af385a1..cbf4b26e 100644 --- a/tests/testthat/test-write-po-file.R +++ b/tests/testthat/test-write-po-file.R @@ -12,7 +12,7 @@ test_that("po_metadata constructor & methods work", { format(metadata, template = TRUE), c( '"Language-Team: LANGUAGE \\n"', - '"Content-Type: text/plain; charset=UTF-8\\n"', + '"Content-Type: text/plain; charset=CHARSET\\n"', '# SOME DESCRIPTIVE TITLE.', '# This file is distributed under the same license as the R package.', '# FIRST AUTHOR , YEAR.' From 6fd0c3026944b9edc53bdba1109aecbda5a8af3f Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 10 Nov 2021 08:00:01 -0600 Subject: [PATCH 22/31] More docs about updating --- R/po_update.R | 26 +++++++++++++++++++++++--- man/po_create.Rd | 20 +++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/R/po_update.R b/R/po_update.R index 16c86332..8e751c6b 100644 --- a/R/po_update.R +++ b/R/po_update.R @@ -1,9 +1,29 @@ #' Update all `.po` files with changes in `.pot` #' +#' @description #' `po_update()` updates existing `.po` file after the `.pot` file has changed. -#' The translations for existing messages are preserved; new messages are added; -#' and translations for deleted message are marked as deprecated and moved to -#' the bottom of the file. +#' There are four cases: +#' +#' * New messages are added with blank `msgstr`. +#' +#' * Delete messages are marked as deprecated and moved to the bottom +#' of the file. +#' +#' * Major changes to existing messages will appear as a addition and a +#' deletion. +#' +#' * Minor changes will be preserved and flagged as fuzzy: +#' +#' ``` +#' #, fuzzy, c-format +#' #| msgid "Generating en@quot translations" +#' msgid "Updating '%s' %s translation" +#' msgstr "en@quot翻訳生成中。。。" +#' ``` +#' +#' The old message is given after the `#|`. Translators need to update the +#' message as necessary, then delete the old translation and the `fuzzy` +#' comment. #' #' @inheritParams po_extract #' @param lazy If `TRUE`, only `.po` files that are older than their diff --git a/man/po_create.Rd b/man/po_create.Rd index b910d82f..cba5da4f 100644 --- a/man/po_create.Rd +++ b/man/po_create.Rd @@ -32,9 +32,23 @@ translated. If a translation already exists, it'll be updated with any changes to the \code{.pot} since it was last touched. \code{po_update()} updates existing \code{.po} file after the \code{.pot} file has changed. -The translations for existing messages are preserved; new messages are added; -and translations for deleted message are marked as deprecated and moved to -the bottom of the file. +There are four cases: +\itemize{ +\item New messages are added with blank \code{msgstr}. +\item Delete messages are marked as deprecated and moved to the bottom +of the file. +\item Major changes to existing messages will appear as a addition and a +deletion. +\item Minor changes will be preserved and flagged as fuzzy:\preformatted{#, fuzzy, c-format +#| msgid "Generating en@quot translations" +msgid "Updating '\%s' \%s translation" +msgstr "en@quot翻訳生成中。。。" +} + +The old message is given after the \verb{#|}. Translators need to update the +message as necessary, then delete the old translation and the \code{fuzzy} +comment. +} } \seealso{ \code{\link[=po_update]{po_update()}} to update all \code{.po} files with changes from the From 0e4371c8314091294a87517a5574a8947ec6c4b3 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 10 Nov 2021 08:04:31 -0600 Subject: [PATCH 23/31] Standardise number of dots --- tests/testthat/helpers.R | 4 ++++ tests/testthat/test-po_update.R | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/testthat/helpers.R b/tests/testthat/helpers.R index 95c439a4..07262040 100644 --- a/tests/testthat/helpers.R +++ b/tests/testthat/helpers.R @@ -64,3 +64,7 @@ local_test_package <- function(..., .envir = parent.frame()) { temp } + +standardise_dots <- function(x) { + gsub("\\.+", ".", x) +} diff --git a/tests/testthat/test-po_update.R b/tests/testthat/test-po_update.R index 30a1c476..9f11b4f8 100644 --- a/tests/testthat/test-po_update.R +++ b/tests/testthat/test-po_update.R @@ -5,5 +5,8 @@ test_that("user is told what's happening", { po_extract() po_create(c("ja", "fr")) - expect_snapshot(po_update(verbose = TRUE, lazy = FALSE)) + expect_snapshot( + po_update(verbose = TRUE, lazy = FALSE), + transform = standardise_dots + ) }) From 4b3353fa13168c5c2d62ee57c014debfa4a60d7f Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 10 Nov 2021 08:14:05 -0600 Subject: [PATCH 24/31] Improve docs --- R/po_create.R | 10 ++++++---- R/po_update.R | 19 ++++++++----------- man/po_create.Rd | 36 +++++------------------------------- man/po_update.Rd | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 46 deletions(-) create mode 100644 man/po_update.Rd diff --git a/R/po_create.R b/R/po_create.R index c82a77e8..88f58677 100644 --- a/R/po_create.R +++ b/R/po_create.R @@ -1,8 +1,12 @@ #' Create a new `.po` file #' +#' @description #' `po_create()` creates a new `po/{languages}.po` containing the messages to be -#' translated. If a translation already exists, it'll be updated with any -#' changes to the `.pot` since it was last touched. +#' translated. +#' +#' Generally, we expect you to use `po_create()` to create new `.po` files +#' but if you call it with an existing translation, it will update it with any +#' changes from the `.pot`. See [po_update()] for details. #' #' @param languages Language identifiers. These are typically two letters (e.g. #' "en" = English, "fr" = French, "es" = Spanish, "zh" = Chinese), but @@ -11,8 +15,6 @@ #' characters as used in mainland China, "zh_TW" = traditional characters #' as used in Taiwan.) #' @inheritParams po_extract -#' @seealso [po_update()] to update all `.po` files with changes from the -#' `.pot`. #' @export po_create <- function(languages, dir = ".", verbose = !is_testing()) { package <- get_desc_data(dir, "Package") diff --git a/R/po_update.R b/R/po_update.R index 8e751c6b..effc319b 100644 --- a/R/po_update.R +++ b/R/po_update.R @@ -4,15 +4,13 @@ #' `po_update()` updates existing `.po` file after the `.pot` file has changed. #' There are four cases: #' -#' * New messages are added with blank `msgstr`. +#' * New messages: added with blank `msgstr`. #' -#' * Delete messages are marked as deprecated and moved to the bottom -#' of the file. +#' * Deleted messages: marked as deprecated and moved to the bottom of the file. #' -#' * Major changes to existing messages will appear as a addition and a -#' deletion. +#' * Major changes to existing messages: appear as a addition and a deletion. #' -#' * Minor changes will be preserved and flagged as fuzzy: +#' * Minor changes to existing messages: will be flagged as fuzzy. #' #' ``` #' #, fuzzy, c-format @@ -21,14 +19,13 @@ #' msgstr "en@quot翻訳生成中。。。" #' ``` #' -#' The old message is given after the `#|`. Translators need to update the -#' message as necessary, then delete the old translation and the `fuzzy` -#' comment. +#' The previous message is given after the `#|`. Translators need to update +#' `msgstr` based changed from the old message and the new `msgid`, then +#' delete the old translation and the `fuzzy` comment. #' #' @inheritParams po_extract #' @param lazy If `TRUE`, only `.po` files that are older than their -#' corresponding `.pot` file will be updated -#' @rdname po_create +#' corresponding `.pot` file will be updated. #' @export po_update <- function(dir = ".", lazy = TRUE, verbose = !is_testing()) { meta <- get_po_metadata(dir) diff --git a/man/po_create.Rd b/man/po_create.Rd index cba5da4f..c31f23d1 100644 --- a/man/po_create.Rd +++ b/man/po_create.Rd @@ -1,13 +1,10 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/po_create.R, R/po_update.R +% Please edit documentation in R/po_create.R \name{po_create} \alias{po_create} -\alias{po_update} \title{Create a new \code{.po} file} \usage{ po_create(languages, dir = ".", verbose = !is_testing()) - -po_update(dir = ".", lazy = TRUE, verbose = !is_testing()) } \arguments{ \item{languages}{Language identifiers. These are typically two letters (e.g. @@ -22,35 +19,12 @@ R package is stored.} \item{verbose}{Logical, default \code{TRUE} (except during testing). Should extra information about progress, etc. be reported?} - -\item{lazy}{If \code{TRUE}, only \code{.po} files that are older than their -corresponding \code{.pot} file will be updated} } \description{ \code{po_create()} creates a new \verb{po/\{languages\}.po} containing the messages to be -translated. If a translation already exists, it'll be updated with any -changes to the \code{.pot} since it was last touched. - -\code{po_update()} updates existing \code{.po} file after the \code{.pot} file has changed. -There are four cases: -\itemize{ -\item New messages are added with blank \code{msgstr}. -\item Delete messages are marked as deprecated and moved to the bottom -of the file. -\item Major changes to existing messages will appear as a addition and a -deletion. -\item Minor changes will be preserved and flagged as fuzzy:\preformatted{#, fuzzy, c-format -#| msgid "Generating en@quot translations" -msgid "Updating '\%s' \%s translation" -msgstr "en@quot翻訳生成中。。。" -} +translated. -The old message is given after the \verb{#|}. Translators need to update the -message as necessary, then delete the old translation and the \code{fuzzy} -comment. -} -} -\seealso{ -\code{\link[=po_update]{po_update()}} to update all \code{.po} files with changes from the -\code{.pot}. +Generally, we expect you to use \code{po_create()} to create new \code{.po} files +but if you call it with an existing translation, it will update it with any +changes from the \code{.pot}. See \code{\link[=po_update]{po_update()}} for details. } diff --git a/man/po_update.Rd b/man/po_update.Rd new file mode 100644 index 00000000..3a144c0b --- /dev/null +++ b/man/po_update.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/po_update.R +\name{po_update} +\alias{po_update} +\title{Update all \code{.po} files with changes in \code{.pot}} +\usage{ +po_update(dir = ".", lazy = TRUE, verbose = !is_testing()) +} +\arguments{ +\item{dir}{Character, default the present directory; a directory in which an +R package is stored.} + +\item{lazy}{If \code{TRUE}, only \code{.po} files that are older than their +corresponding \code{.pot} file will be updated} + +\item{verbose}{Logical, default \code{TRUE} (except during testing). Should +extra information about progress, etc. be reported?} +} +\description{ +\code{po_update()} updates existing \code{.po} file after the \code{.pot} file has changed. +There are four cases: +\itemize{ +\item New messages: added with blank \code{msgstr}. +\item Deleted messages: marked as deprecated and moved to the bottom of the file. +\item Major changes to existing messages: appear as a addition and a deletion. +\item Minor changes to existing messages: will be flagged as fuzzy.\preformatted{#, fuzzy, c-format +#| msgid "Generating en@quot translations" +msgid "Updating '\%s' \%s translation" +msgstr "en@quot翻訳生成中。。。" +} + +The previous message is given after the \verb{#|}. Translators need to update +\code{msgstr} based changed from the old message and the new \code{msgid}, then +delete the old translation and the \code{fuzzy} comment. +} +} From ae5c5b781cb271615928231301a80d4817b95339 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 10 Nov 2021 08:19:18 -0600 Subject: [PATCH 25/31] Tweak messaging --- R/msgmerge.R | 4 ++-- R/po_update.R | 2 +- tests/testthat/_snaps/po_create.md | 6 ++---- tests/testthat/_snaps/po_update.md | 6 ++---- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/R/msgmerge.R b/R/msgmerge.R index 424cd7af..f4510c04 100644 --- a/R/msgmerge.R +++ b/R/msgmerge.R @@ -14,7 +14,7 @@ run_msgmerge <- function(po_file, pot_file, previous = FALSE, verbose = TRUE) { # nocov these warnings? i don't know how to trigger them as of this writing. warningf("Running msgmerge on './po/%s' failed:\n %s", basename(po_file), paste(val, collapse = "\n")) } else if (verbose) { - messagef("Running msgmerge on './po/%s' succeeded:\n %s", basename(po_file), paste(val, collapse = "\n")) + messagef(paste(val, collapse = "\n")) } res <- tools::checkPoFile(po_file, strictPlural = TRUE) @@ -81,7 +81,7 @@ run_msginit <- function(po_path, pot_path, locale, width = 80, verbose = TRUE) { if (!identical(attr(val, "status", exact = TRUE), NULL)) { stopf("Running msginit on '%s' failed", pot_path) } else if (verbose) { - messagef("Running msgint on './po/%s' succeeded:\n %s", basename(po_path), paste(val, collapse = "\n")) + messagef(paste(val, collapse = "\n")) } return(invisible()) } diff --git a/R/po_update.R b/R/po_update.R index effc319b..912ebc63 100644 --- a/R/po_update.R +++ b/R/po_update.R @@ -36,7 +36,7 @@ po_update <- function(dir = ".", lazy = TRUE, verbose = !is_testing()) { for (ii in seq_len(nrow(meta))) { row <- meta[ii] if (verbose) messagef("Updating '%s' %s translation", row$language, row$type) - run_msgmerge(row$po, row$pot, previous = TRUE) + run_msgmerge(row$po, row$pot, previous = TRUE, verbose = verbose) } invisible(meta) diff --git a/tests/testthat/_snaps/po_create.md b/tests/testthat/_snaps/po_create.md index adabf6a5..75df6c2a 100644 --- a/tests/testthat/_snaps/po_create.md +++ b/tests/testthat/_snaps/po_create.md @@ -4,8 +4,7 @@ po_create("jp", verbose = TRUE) Message Creating 'jp' R translation - Running msgint on './po/R-jp.po' succeeded: - Created ./po/R-jp.po. + Created ./po/R-jp.po. --- @@ -13,6 +12,5 @@ po_create("jp", verbose = TRUE) Message Updating 'jp' R translation - Running msgmerge on './po/R-jp.po' succeeded: - . done. + . done. diff --git a/tests/testthat/_snaps/po_update.md b/tests/testthat/_snaps/po_update.md index 3f949272..943e50c0 100644 --- a/tests/testthat/_snaps/po_update.md +++ b/tests/testthat/_snaps/po_update.md @@ -4,9 +4,7 @@ po_update(verbose = TRUE, lazy = FALSE) Message Updating 'fr' R translation - Running msgmerge on './po/R-fr.po' succeeded: - . done. + . done. Updating 'ja' R translation - Running msgmerge on './po/R-ja.po' succeeded: - . done. + . done. From b8e17e9c129aec7c515e9e42daecbb892787afcb Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Wed, 10 Nov 2021 08:25:37 -0600 Subject: [PATCH 26/31] Revert accidental doc changes --- R/po_compile.R | 8 +++++--- man/po_compile.Rd | 7 ++++--- man/po_update.Rd | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/R/po_compile.R b/R/po_compile.R index 1b1029f0..c546d314 100644 --- a/R/po_compile.R +++ b/R/po_compile.R @@ -4,10 +4,12 @@ #' with into the binary `.mo` files that are installed with packages and #' used for live translations. #' +#' #' @param dir Path to package root directory. -#' @param package Name of package. If not supplied, read from `DESCRIPTION`. -#' @param lazy If `TRUE`, only `.mo` files that are older than their -#' corresponding `.po` file will be updated. +#' @param package Name of package. If not supplied, read from +#' `DESCRIPTION`. +#' @param lazy If `TRUE`, only `.mo` functions that are older than +#' `.po` files be updated #' @param verbose If `TRUE`, print information as it goes. #' @export po_compile = function(dir = ".", package = NULL, lazy = TRUE, verbose = TRUE) { diff --git a/man/po_compile.Rd b/man/po_compile.Rd index aeb97314..0e8b9d56 100644 --- a/man/po_compile.Rd +++ b/man/po_compile.Rd @@ -9,10 +9,11 @@ po_compile(dir = ".", package = NULL, lazy = TRUE, verbose = TRUE) \arguments{ \item{dir}{Path to package root directory.} -\item{package}{Name of package. If not supplied, read from \code{DESCRIPTION}.} +\item{package}{Name of package. If not supplied, read from +\code{DESCRIPTION}.} -\item{lazy}{If \code{TRUE}, only \code{.mo} files that are older than their -corresponding \code{.po} file will be updated.} +\item{lazy}{If \code{TRUE}, only \code{.mo} functions that are older than +\code{.po} files be updated} \item{verbose}{If \code{TRUE}, print information as it goes.} } diff --git a/man/po_update.Rd b/man/po_update.Rd index 3a144c0b..cd7a7867 100644 --- a/man/po_update.Rd +++ b/man/po_update.Rd @@ -11,7 +11,7 @@ po_update(dir = ".", lazy = TRUE, verbose = !is_testing()) R package is stored.} \item{lazy}{If \code{TRUE}, only \code{.po} files that are older than their -corresponding \code{.pot} file will be updated} +corresponding \code{.pot} file will be updated.} \item{verbose}{Logical, default \code{TRUE} (except during testing). Should extra information about progress, etc. be reported?} From 0f930687c39f69d6d5b9e279febdfb2ac1ac77b9 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Wed, 10 Nov 2021 18:49:43 -0800 Subject: [PATCH 27/31] add TODO --- R/po_create.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/po_create.R b/R/po_create.R index 88f58677..5d1de6d2 100644 --- a/R/po_create.R +++ b/R/po_create.R @@ -34,6 +34,8 @@ po_create <- function(languages, dir = ".", verbose = !is_testing()) { invisible(po_files) } +# TODO: make sure this works with translating/updating base, which +# has the anti-pattern that src translations are in R.pot, not base.pot. po_language_files <- function(languages, dir = ".") { po_files <- data.table::CJ(type = pot_types(dir), language = languages) po_files[, "po_path" := file.path(dir, "po", paste0(po_prefix(po_files$type), po_files$language, ".po"))] From 3ff40d53dad5acbfd6cc274169d4c615a2aa9c9f Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Wed, 10 Nov 2021 18:50:49 -0800 Subject: [PATCH 28/31] another TODO --- R/po_create.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/po_create.R b/R/po_create.R index 5d1de6d2..a6f0644a 100644 --- a/R/po_create.R +++ b/R/po_create.R @@ -43,6 +43,7 @@ po_language_files <- function(languages, dir = ".") { po_files[] } +# TODO: should this be po_paths, with a template=TRUE/FALSE argument? pot_paths <- function(dir, type, package = NULL) { if (is.null(package)) { package <- get_desc_data(dir, "Package") From 5efd88f4c64fe46057aaad8c8edce23ffb1bb58a Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Wed, 10 Nov 2021 18:58:41 -0800 Subject: [PATCH 29/31] typo --- R/po_update.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/po_update.R b/R/po_update.R index 912ebc63..14df14e9 100644 --- a/R/po_update.R +++ b/R/po_update.R @@ -8,7 +8,7 @@ #' #' * Deleted messages: marked as deprecated and moved to the bottom of the file. #' -#' * Major changes to existing messages: appear as a addition and a deletion. +#' * Major changes to existing messages: appear as an addition and a deletion. #' #' * Minor changes to existing messages: will be flagged as fuzzy. #' From e6788bd757755a3cec4d0f8688f0fcf2861eaf9f Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Wed, 10 Nov 2021 19:01:20 -0800 Subject: [PATCH 30/31] clarify fuzzy description --- R/po_update.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/R/po_update.R b/R/po_update.R index 14df14e9..4c3e43ef 100644 --- a/R/po_update.R +++ b/R/po_update.R @@ -19,9 +19,11 @@ #' msgstr "en@quot翻訳生成中。。。" #' ``` #' -#' The previous message is given after the `#|`. Translators need to update -#' `msgstr` based changed from the old message and the new `msgid`, then -#' delete the old translation and the `fuzzy` comment. +#' The previous message is given in comments starting with `#|`. +#' Translators need to update the actual (uncommented) `msgstr` manually, +#' using the old `msgid` as a potential reference, then +#' delete the old translation and the `fuzzy` comment (c-format should +#' remain, if present). #' #' @inheritParams po_extract #' @param lazy If `TRUE`, only `.po` files that are older than their From a36031a36849cd80f4fd10b9bea2d73702f6c40f Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Wed, 10 Nov 2021 19:05:51 -0800 Subject: [PATCH 31/31] =?UTF-8?q?comment=20need=20for=20standardise=5Fdots?= =?UTF-8?q?=20&=20americanize=20=F0=9F=87=BA=F0=9F=87=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/testthat/helpers.R | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/testthat/helpers.R b/tests/testthat/helpers.R index 07262040..ad61f367 100644 --- a/tests/testthat/helpers.R +++ b/tests/testthat/helpers.R @@ -65,6 +65,8 @@ local_test_package <- function(..., .envir = parent.frame()) { temp } -standardise_dots <- function(x) { - gsub("\\.+", ".", x) +# different platforms/installations of gettext apparently +# produce a different number of "." in "progress" output; normalize +standardize_dots <- standardise_dots <- function(x) { + gsub("\\.{2,}", ".", x) }