From 2439e54259ffe1445a548d36220971df68f3ff03 Mon Sep 17 00:00:00 2001 From: Richard Cotton Date: Sun, 18 Jun 2017 15:06:05 -0400 Subject: [PATCH 1/5] typo --- R/translations.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/translations.R b/R/translations.R index ab9de88..f81249a 100644 --- a/R/translations.R +++ b/R/translations.R @@ -16,7 +16,7 @@ #' #' \code{\link{edit_translation}} is a very simple interactive interface for editing a translation object in memory. #' -#' @return \code{make_translation} and \code{read_translation} reutrn an object of class \dQuote{po}. \code{write_translation} returns the path to the file, invisibly. +#' @return \code{make_translation} and \code{read_translation} return an object of class \dQuote{po}. \code{write_translation} returns the path to the file, invisibly. #' @note These functions require that gettext is installed on your system. #' @author Thomas J. Leeper #' @examples From b909791be759dcb7d4875acd5a5b7d16b8271807 Mon Sep 17 00:00:00 2001 From: Richard Cotton Date: Sun, 18 Jun 2017 15:42:58 -0400 Subject: [PATCH 2/5] added first draft of auto-translations --- DESCRIPTION | 10 +++- NAMESPACE | 2 + R/auto_translate.R | 134 ++++++++++++++++++++++++++++++++++++++++++ man/auto_translate.Rd | 43 ++++++++++++++ man/translations.Rd | 2 +- 5 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 R/auto_translate.R create mode 100644 man/auto_translate.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 4f1f97d..7fd0b3a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -5,14 +5,17 @@ Description: A number of utilities for developing and maintaining error, warning and other messages in R packages, including checking for consistency across messages, spell-checking messages, and building message translations into various languages for purposes of localization. -Date: 2017-02-28 +Date: 2017-06-18 Authors@R: c(person("Thomas J.", "Leeper", role = c("aut", "cre"), - email = "thosjleeper@gmail.com")) + email = "thosjleeper@gmail.com"), + person("Richard", "Cotton", + role = "cre", + email = "richierocks@gmail.com")) URL: https://github.com/RL10N/msgtools/ BugReports: https://github.com/RL10N/msgtools/issues License: MIT + file LICENSE -Version: 0.2.7 +Version: 0.2.8 Depends: R (>= 3.2.0) Imports: tools, @@ -20,6 +23,7 @@ Imports: poio (>= 0.0-3), digest, tibble, + translateR, hunspell, devtools Suggests: diff --git a/NAMESPACE b/NAMESPACE index 5811f57..b70c22e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -7,10 +7,12 @@ export(dummy_pkg) export(edit_translation) export(get_message_distances) export(get_messages) +export(google_translate) export(install_gettext) export(install_translations) export(make_template) export(make_translation) +export(microsoft_translate) export(read_template) export(read_translation) export(spell_check_msgs) diff --git a/R/auto_translate.R b/R/auto_translate.R new file mode 100644 index 0000000..6c61fc6 --- /dev/null +++ b/R/auto_translate.R @@ -0,0 +1,134 @@ +#' Auto translate messages +#' +#' Automaticlly translate messages using Google Translate or Microsoft +#' Translator. +#' @param translation An object of class \code{"po"} containing a message +#' translation. +#' @param overwrite Logical. If \code{TRUE}, translations will be found for all +#' messages. If \code{FALSE}, only the messages that do not have an existing +#' translation will be translated. +#' @param api_key A string describing an API key for Google Translate or Microsoft +#' Translator. +#' @return An object of class \code{"po"} containing a message translation. +#' @note To get a Google Translate API KEY, you must create a Google Cloud +#' account. See \url{https://cloud.google.com/translate/docs/getting-started} +#' to get started. +#' Likewise, to use Microsfot Translator, you need a Microsoft Azure account. +#' See \url{https://www.microsoft.com/en-us/translator/getstarted.aspx} to get +#' started. +auto_translate <- function(translation, overwrite = FALSE, api_key, + engine = c("google", "microsoft")) { + engine <- match.arg(engine) + + to_translate <- if(overwrite) { + rep.int(TRUE, nrow(translation$direct)) + } else { + translation$direct$msgstr == "" + } + direct_translations <- translate( + content.vec = translation$direct$msgid[to_translate], + google.api.key = api_key, + source.lang = "en", + target.lang = translation$lang + ) + translation$direct$msgstr[to_translate] <- direct_translations + + # There may be a more sophisticated way of getting countable translations + # for languages with multiple plural forms. For now if there is 1 plural form + # just pass the singular form, and return it for both values. + # In other cases, use the plural form multiple times. + to_translate <- if (overwrite) { + rep.int(TRUE, nrow(translation$countable)) + } else { + vapply( + translation$countable$msgstr, + function(msgstri) { + all(msgstri == "") + }, + logical(1L) + ) + } + singular_countable_translations <- translate( + content.vec = translation$countable$msgid[to_translate], + google.api.key = api_key, + source.lang = "en", + target.lang = translation$lang + ) + plural_countable_translations <- if (translation$n_plural_forms > 1L) { + translate( + content.vec = translation$countable$msgid_plural[to_translate], + google.api.key = api_key, + source.lang = "en", + target.lang = translation$lang + ) + } else { + character(sum(to_translate)) + } + m <- translation$n_plural_forms - 1L + translation$countable$msgstr[to_translate] <- Map( + function(singular, plural) { + c(singular, rep.int(plural, m)) + }, + singular_countable_translations, + plural_countable_translations + ) + translation +} + +#' @rdname auto_translate +#' @export +google_translate <- function(translation, overwrite = FALSE, + api_key = Sys.getenv("GOOGLE_TRANSLATE_API_KEY")) { + auto_translate(translation, overwrite = overwrite, api_key, engine = "google") +} + +#' @rdname auto_translate +#' @export +microsoft_translate <- function(translation, overwrite = FALSE, + api_key = Sys.getenv("MICROSOFT_TRANSLATER_API_KEY")) { + auto_translate(translation, overwrite = overwrite, api_key, engine = "microsoft") +} + +# translateR::translate() is currently broken. +# Maintainers contacted and awaiting a fix. +# In the meantime, this is the same function with lapply() instead of mclapply(). +translate <- function (dataset = NULL, content.field = NULL, content.vec = NULL, + google.api.key = NULL, microsoft.client.id = NULL, microsoft.client.secret = NULL, + source.lang = NULL, target.lang = NULL) { + translator <- translateR:::validateInput(dataset, content.field, content.vec, + google.api.key, microsoft.client.id, microsoft.client.secret, + source.lang, target.lang) + if (!(is.null(dataset))) { + to.translate <- dataset[[content.field]] + } + if (!(is.null(content.vec))) { + to.translate <- content.vec + } + translateR:::checkLang(to.translate, source.lang, translator) + if (translator == "Google") { + translated <- unname(unlist(lapply(to.translate, function(x) translateR:::googleTranslate(x, + google.api.key, source.lang, target.lang)))) + } + if (translator == "Microsoft") { + ptm <- proc.time() + access.token <- getAccessToken(microsoft.client.id, microsoft.client.secret) + translated <- c() + for (doc in to.translate) { + translated <- c(translated, microsoftTranslate(doc, + access.token, source.lang, target.lang)) + if ((proc.time() - ptm)[3] > 540) { + ptm <- proc.time() + access.token <- getAccessToken(microsoft.client.id, + microsoft.client.secret) + } + } + } + if (!(is.null(content.vec))) { + return(translated) + } + if (!(is.null(dataset) & is.null(content.field))) { + dataset$translatedContent <- translated + return(dataset) + } +} + diff --git a/man/auto_translate.Rd b/man/auto_translate.Rd new file mode 100644 index 0000000..57de8f2 --- /dev/null +++ b/man/auto_translate.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auto_translate.R +\name{auto_translate} +\alias{auto_translate} +\alias{google_translate} +\alias{microsoft_translate} +\title{Auto translate messages} +\usage{ +auto_translate(translation, overwrite = FALSE, api_key, engine = c("google", + "microsoft")) + +google_translate(translation, overwrite = FALSE, + api_key = Sys.getenv("GOOGLE_TRANSLATE_API_KEY")) + +microsoft_translate(translation, overwrite = FALSE, + api_key = Sys.getenv("MICROSOFT_TRANSLATER_API_KEY")) +} +\arguments{ +\item{translation}{An object of class \code{"po"} containing a message +translation.} + +\item{overwrite}{Logical. If \code{TRUE}, translations will be found for all +messages. If \code{FALSE}, only the messages that do not have an existing +translation will be translated.} + +\item{api_key}{A string describing an API key for Google Translate or Microsoft +Translator.} +} +\value{ +An object of class \code{"po"} containing a message translation. +} +\description{ +Automaticlly translate messages using Google Translate or Microsoft +Translator. +} +\note{ +To get a Google Translate API KEY, you must create a Google Cloud +account. See \url{https://cloud.google.com/translate/docs/getting-started} +to get started. +Likewise, to use Microsfot Translator, you need a Microsoft Azure account. +See \url{https://www.microsoft.com/en-us/translator/getstarted.aspx} to get +started. +} diff --git a/man/translations.Rd b/man/translations.Rd index 235e832..6e12e5e 100644 --- a/man/translations.Rd +++ b/man/translations.Rd @@ -32,7 +32,7 @@ sync_translations(pkg = ".", verbose = getOption("verbose")) \item{team}{Optionally, a character string specifying contact information for a \dQuote{translation team}.} } \value{ -\code{make_translation} and \code{read_translation} reutrn an object of class \dQuote{po}. \code{write_translation} returns the path to the file, invisibly. +\code{make_translation} and \code{read_translation} return an object of class \dQuote{po}. \code{write_translation} returns the path to the file, invisibly. } \description{ Read, write, and generate translations of diagnostic messages From 7a8893c02805f42de97b1daf2e3b8a18659d07b3 Mon Sep 17 00:00:00 2001 From: Richard Cotton Date: Sun, 18 Jun 2017 15:48:04 -0400 Subject: [PATCH 3/5] add auto_translate examples --- R/auto_translate.R | 16 +++++++++++++++- man/auto_translate.Rd | 16 +++++++++++++++- po/R-msgtools.pot | 8 ++++---- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/R/auto_translate.R b/R/auto_translate.R index 6c61fc6..6f450cb 100644 --- a/R/auto_translate.R +++ b/R/auto_translate.R @@ -15,7 +15,21 @@ #' to get started. #' Likewise, to use Microsfot Translator, you need a Microsoft Azure account. #' See \url{https://www.microsoft.com/en-us/translator/getstarted.aspx} to get -#' started. +#' started.#' @examples +#' \dontrun{ +#' # create example package +#' pkg <- dummy_pkg() +#' +#' # setup pkg for localization +#' use_localization(pkg) +#' +#' # generate Spanish translation in memory +#' (tran <- make_translation("es", translator = "Some Person ")) +#' +#' auto_tran <- google_translate(tran) +#' View(auto_tran$direct) +#' View(auto_tran$countable) +#' } auto_translate <- function(translation, overwrite = FALSE, api_key, engine = c("google", "microsoft")) { engine <- match.arg(engine) diff --git a/man/auto_translate.Rd b/man/auto_translate.Rd index 57de8f2..3274dd6 100644 --- a/man/auto_translate.Rd +++ b/man/auto_translate.Rd @@ -39,5 +39,19 @@ account. See \url{https://cloud.google.com/translate/docs/getting-started} to get started. Likewise, to use Microsfot Translator, you need a Microsoft Azure account. See \url{https://www.microsoft.com/en-us/translator/getstarted.aspx} to get -started. +started.#' @examples +\dontrun{ + # create example package + pkg <- dummy_pkg() + + # setup pkg for localization + use_localization(pkg) + + # generate Spanish translation in memory + (tran <- make_translation("es", translator = "Some Person ")) + + auto_tran <- google_translate(tran) + View(auto_tran$direct) + View(auto_tran$countable) +} } diff --git a/po/R-msgtools.pot b/po/R-msgtools.pot index 660cdd0..b8693d7 100644 --- a/po/R-msgtools.pot +++ b/po/R-msgtools.pot @@ -1,14 +1,14 @@ msgid "" msgstr "" -"Project-Id-Version: msgtools 0.2.7\n" +"Project-Id-Version: msgtools 0.2.8\n" "Report-Msgid-Bugs-To: https://github.com/RL10N/msgtools/issues\n" -"POT-Creation-Date: 2017-03-01 14:52\n" -"PO-Revision-Date: 2017-03-01 14:52\n" +"POT-Creation-Date: 2017-06-18 15:45\n" +"PO-Revision-Date: 2017-06-18 15:45\n" "Last-Translator: \n" "Language-Team: \n" "Language: LL\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=C:\Users\THOMAS\AppData\Local\Temp\RtmpySZ1eX/translateme\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "English message is:" From 686983471e3802f23c34389ecc527ef73de5d0ec Mon Sep 17 00:00:00 2001 From: Richard Cotton Date: Sun, 18 Jun 2017 18:44:40 -0400 Subject: [PATCH 4/5] fix description --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 7fd0b3a..39c2e4a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -10,7 +10,7 @@ Authors@R: c(person("Thomas J.", "Leeper", role = c("aut", "cre"), email = "thosjleeper@gmail.com"), person("Richard", "Cotton", - role = "cre", + role = "aut", email = "richierocks@gmail.com")) URL: https://github.com/RL10N/msgtools/ BugReports: https://github.com/RL10N/msgtools/issues From 1e24ad6569cf6e2edad2145b559544dbd399fead Mon Sep 17 00:00:00 2001 From: Richard Cotton Date: Sun, 25 Jun 2017 22:09:25 -0400 Subject: [PATCH 5/5] use autotranslate --- DESCRIPTION | 11 ++-- NAMESPACE | 1 + R/auto_translate.R | 118 ++++++++++++++++++------------------------ man/auto_translate.Rd | 27 +++++++--- 4 files changed, 77 insertions(+), 80 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 39c2e4a..7efdd8c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -5,7 +5,7 @@ Description: A number of utilities for developing and maintaining error, warning and other messages in R packages, including checking for consistency across messages, spell-checking messages, and building message translations into various languages for purposes of localization. -Date: 2017-06-18 +Date: 2017-06-25 Authors@R: c(person("Thomas J.", "Leeper", role = c("aut", "cre"), email = "thosjleeper@gmail.com"), @@ -20,12 +20,13 @@ Depends: R (>= 3.2.0) Imports: tools, utils, - poio (>= 0.0-3), + autotranslate, + devtools, digest, - tibble, - translateR, hunspell, - devtools + poio (>= 0.0-3), + tibble, + translateR Suggests: testthat, knitr, diff --git a/NAMESPACE b/NAMESPACE index b70c22e..e86dd84 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -24,6 +24,7 @@ export(use_localization) export(write_template) export(write_translation) import(poio) +importFrom(autotranslate,get_translations) importFrom(devtools,as.package) importFrom(devtools,create) importFrom(digest,digest) diff --git a/R/auto_translate.R b/R/auto_translate.R index 6f450cb..e7edbff 100644 --- a/R/auto_translate.R +++ b/R/auto_translate.R @@ -9,6 +9,8 @@ #' translation will be translated. #' @param api_key A string describing an API key for Google Translate or Microsoft #' Translator. +#' @param parallelization_strategy A string naming a parallelization strategy, +#' passed to \code{\link[future]{plan}}. #' @return An object of class \code{"po"} containing a message translation. #' @note To get a Google Translate API KEY, you must create a Google Cloud #' account. See \url{https://cloud.google.com/translate/docs/getting-started} @@ -26,12 +28,21 @@ #' # generate Spanish translation in memory #' (tran <- make_translation("es", translator = "Some Person ")) #' -#' auto_tran <- google_translate(tran) -#' View(auto_tran$direct) -#' View(auto_tran$countable) +#' # You need a Google Translate API key before running this +#' auto_tran_google <- google_translate(tran) +#' View(auto_tran_google$direct) +#' View(auto_tran_google$countable) +#' +#' # You need a Microsoft Cognitive Services Translator API +#' # key before running this +#' auto_tran_microsoft <- microsoft_translate(tran) +#' View(auto_tran_microsoft$direct) +#' View(auto_tran_microsoft$countable) #' } -auto_translate <- function(translation, overwrite = FALSE, api_key, - engine = c("google", "microsoft")) { +#' @importFrom autotranslate get_translations +auto_translate <- function(translation, overwrite = FALSE, api_key, + parallelization_strategy = c("sequential", "multicore", "cluster"), + engine = c("google", "microsoft")) { engine <- match.arg(engine) to_translate <- if(overwrite) { @@ -39,11 +50,12 @@ auto_translate <- function(translation, overwrite = FALSE, api_key, } else { translation$direct$msgstr == "" } - direct_translations <- translate( - content.vec = translation$direct$msgid[to_translate], - google.api.key = api_key, - source.lang = "en", - target.lang = translation$lang + direct_translations <- get_translations( + x = translation$direct$msgid[to_translate], + lang_to = translation$lang, + lang_from = "en", + api_key = api_key, + engine = engine ) translation$direct$msgstr[to_translate] <- direct_translations @@ -62,18 +74,20 @@ auto_translate <- function(translation, overwrite = FALSE, api_key, logical(1L) ) } - singular_countable_translations <- translate( - content.vec = translation$countable$msgid[to_translate], - google.api.key = api_key, - source.lang = "en", - target.lang = translation$lang + singular_countable_translations <- get_translations( + x = translation$countable$msgid[to_translate], + lang_to = translation$lang, + lang_from = "en", + api_key = api_key, + engine = engine ) plural_countable_translations <- if (translation$n_plural_forms > 1L) { - translate( - content.vec = translation$countable$msgid_plural[to_translate], - google.api.key = api_key, - source.lang = "en", - target.lang = translation$lang + get_translations( + x = translation$countable$msgid_plural[to_translate], + lang_to = translation$lang, + lang_from = "en", + api_key = api_key, + engine = engine ) } else { character(sum(to_translate)) @@ -92,57 +106,25 @@ auto_translate <- function(translation, overwrite = FALSE, api_key, #' @rdname auto_translate #' @export google_translate <- function(translation, overwrite = FALSE, - api_key = Sys.getenv("GOOGLE_TRANSLATE_API_KEY")) { - auto_translate(translation, overwrite = overwrite, api_key, engine = "google") + api_key = Sys.getenv("GOOGLE_TRANSLATE_API_KEY"), + parallelization_strategy = c("sequential", "multicore", "cluster")) { + auto_translate( + translation, + overwrite = overwrite, + api_key = api_key, + engine = "google" + ) } #' @rdname auto_translate #' @export microsoft_translate <- function(translation, overwrite = FALSE, - api_key = Sys.getenv("MICROSOFT_TRANSLATER_API_KEY")) { - auto_translate(translation, overwrite = overwrite, api_key, engine = "microsoft") -} - -# translateR::translate() is currently broken. -# Maintainers contacted and awaiting a fix. -# In the meantime, this is the same function with lapply() instead of mclapply(). -translate <- function (dataset = NULL, content.field = NULL, content.vec = NULL, - google.api.key = NULL, microsoft.client.id = NULL, microsoft.client.secret = NULL, - source.lang = NULL, target.lang = NULL) { - translator <- translateR:::validateInput(dataset, content.field, content.vec, - google.api.key, microsoft.client.id, microsoft.client.secret, - source.lang, target.lang) - if (!(is.null(dataset))) { - to.translate <- dataset[[content.field]] - } - if (!(is.null(content.vec))) { - to.translate <- content.vec - } - translateR:::checkLang(to.translate, source.lang, translator) - if (translator == "Google") { - translated <- unname(unlist(lapply(to.translate, function(x) translateR:::googleTranslate(x, - google.api.key, source.lang, target.lang)))) - } - if (translator == "Microsoft") { - ptm <- proc.time() - access.token <- getAccessToken(microsoft.client.id, microsoft.client.secret) - translated <- c() - for (doc in to.translate) { - translated <- c(translated, microsoftTranslate(doc, - access.token, source.lang, target.lang)) - if ((proc.time() - ptm)[3] > 540) { - ptm <- proc.time() - access.token <- getAccessToken(microsoft.client.id, - microsoft.client.secret) - } - } - } - if (!(is.null(content.vec))) { - return(translated) - } - if (!(is.null(dataset) & is.null(content.field))) { - dataset$translatedContent <- translated - return(dataset) - } + api_key = Sys.getenv("MICROSOFT_TRANSLATOR_API_KEY"), + parallelization_strategy = c("sequential", "multicore", "cluster")) { + auto_translate( + translation, + overwrite = overwrite, + api_key = api_key, + engine = "microsoft" + ) } - diff --git a/man/auto_translate.Rd b/man/auto_translate.Rd index 3274dd6..0e3f8ce 100644 --- a/man/auto_translate.Rd +++ b/man/auto_translate.Rd @@ -6,14 +6,17 @@ \alias{microsoft_translate} \title{Auto translate messages} \usage{ -auto_translate(translation, overwrite = FALSE, api_key, engine = c("google", - "microsoft")) +auto_translate(translation, overwrite = FALSE, api_key, + parallelization_strategy = c("sequential", "multicore", "cluster"), + engine = c("google", "microsoft")) google_translate(translation, overwrite = FALSE, - api_key = Sys.getenv("GOOGLE_TRANSLATE_API_KEY")) + api_key = Sys.getenv("GOOGLE_TRANSLATE_API_KEY"), + parallelization_strategy = c("sequential", "multicore", "cluster")) microsoft_translate(translation, overwrite = FALSE, - api_key = Sys.getenv("MICROSOFT_TRANSLATER_API_KEY")) + api_key = Sys.getenv("MICROSOFT_TRANSLATOR_API_KEY"), + parallelization_strategy = c("sequential", "multicore", "cluster")) } \arguments{ \item{translation}{An object of class \code{"po"} containing a message @@ -25,6 +28,9 @@ translation will be translated.} \item{api_key}{A string describing an API key for Google Translate or Microsoft Translator.} + +\item{parallelization_strategy}{A string naming a parallelization strategy, +passed to \code{\link[future]{plan}}.} } \value{ An object of class \code{"po"} containing a message translation. @@ -50,8 +56,15 @@ started.#' @examples # generate Spanish translation in memory (tran <- make_translation("es", translator = "Some Person ")) - auto_tran <- google_translate(tran) - View(auto_tran$direct) - View(auto_tran$countable) + # You need a Google Translate API key before running this + auto_tran_google <- google_translate(tran) + View(auto_tran_google$direct) + View(auto_tran_google$countable) + + # You need a Microsoft Cognitive Services Translator API + # key before running this + auto_tran_microsoft <- microsoft_translate(tran) + View(auto_tran_microsoft$direct) + View(auto_tran_microsoft$countable) } }