Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to translate package content?

I want to have error messages, warnings and other user feedback from my package available in multiple languages. (R can translate the contents of message, warning, stop, gettext, and ngettext.)

There is advice on how to do this in these documents:

  1. The Internationalization section of Writing R Extensions.
  2. The Localization of messages section of R Installation and Administration.
  3. The Translations (R < 3.0.0) page of the R Developer guidance.

The mgcv and Rcmdr (po dir) packages have translations, providing examples of how to do things.

Nevertheless, I'm struggling to get things working. Here's a reproducible package example:

On Windows you need to download and extract gettext-tools, and add the location to your Windows PATH environment variable.

library(roxygen2)
library(devtools)
library(tools)

# Create the directories to hold the package content
Vectorize(dir.create)(c("test", "test/R", "test/man", "test/po"))

# Write the package DESCRIPTION file
cat(
  'Package: test
Title: Test pkg
Description: Investigate how to translate content
Version: 0.0-1
Date: 2015-03-17
Author: Richard Cotton
Maintainer: Richard Cotton <[email protected]>
License: Unlimited',
  file = "test/DESCRIPTION"
)

# Create a function go to into the package, plus its documentation
cat(
  "#' Translatable messages
#' Some strings to be translated.
#' @param n A natural number.
#' @export
translatable <- function(n)
{
  message('faucet')
  cat(gettext('napkin'), '\n')
  cat(ngettext(n, 'one', 'many', domain = 'R-test'), '\n')
}",
  file = "test/R/translatable.R"
)

# Create the master translation file (American English)
xgettext2pot("test", "test/po/R-test.pot")

# Alter the master file to make British English and French translations
en <- readLines("test/po/R-test.pot")
en_gb <- en
en_gb[which(en_gb == 'msgid "faucet"') + 1] <- 'msgid "tap"'
en_gb[which(en_gb == 'msgid "napkin"') + 1] <- 'msgid "serviette"'
writeLines(en_gb, "test/po/R-en_GB.po")

fr <- en
fr[which(fr == 'msgid "faucet"') + 1] <- 'msgid "robinet"'
fr[which(fr == 'msgid "napkin"') + 1] <- 'msgid "serviette"'
fr[which(fr == 'msgid        "one"') + 2] <- 'msgstr[0]    "un"'
fr[which(fr == 'msgid_plural "many"') + 2] <- 'msgstr[1]    "beaucoup"'
writeLines(fr, "test/po/R-fr.po")

# Build and install the package
pkg_file <- build("test")
install.packages(pkg_file, repos = NULL, type = "source")

Change your OS locale to English (United States) (under Windows 7, it's in Control Panel -> Region and Language -> Formats -> Format) and restart R.

You should see the default text:

library(test)
translatable(1)
## faucet
## napkin 
## one
translatable(2)
## faucet
## napkin 
## many

Now change your locale to English (United Kingdom) or to French (France), restart R, and rerun the example. I expected the text to change, but it doesn't.

Sys.getlocale() reports a change in my locale, so that is definitely working.

capabilities("NLS") returns TRUE, so natural language support is switched on.

With a French locale, this example adapted from the mgcv::bam help page gives me a French error message, so the problem is with how I've generated the package.

library(mgcv)
dat <- gamSim(1,n=25000,dist="normal",scale=20)
bs <- "cr";k <- 12
b <- bam(
  y ~ s(x0,bs=bs)+s(x1,bs=bs)+s(x2,bs=bs,k=k)+s(x3,bs=bs),
  data   = dat, 
  family = list(family = NULL)
)
## Erreur dans bam(y ~ s(x0, bs = bs) + s(x1, bs = bs) + s(x2, bs = bs, k = k) +  : 
##   famille non reconnue

What am I doing wrong?

like image 668
Richie Cotton Avatar asked Mar 17 '15 07:03

Richie Cotton


People also ask

How do I translate content?

In your browser, go to Google Translate. At the top, click Documents. Choose the languages to translate to and from. To automatically set the original language of a document, click Detect language.

How do I translate page contents?

Translating a webpage on any Android device is as simple as using Google Translate in the built-in Chrome browser. Open the Chrome app and when visiting a webpage in another language select “More” and then the target language at the bottom of the page.

What is a translation package?

A translation package is a ZIP file containing the service structure's XLIFFs and dynamic documents that are set to the proper preference value of Preparation State, one for each target language selected in Package Languages.


1 Answers

You haven't taken the step to compile and install your translations. And your .po files have problems.

Here's a working R-fr.po file for your example:

msgid ""
msgstr ""
"Project-Id-Version: R 3.1.2\n"
"Report-Msgid-Bugs-To: bugs.r-project.org\n"
"POT-Creation-Date: 2015-03-17 09:46\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"

msgid "faucet"
msgstr "robinet"

msgid "napkin"
msgstr "serviette"

msgid        "one"
msgid_plural "many"
msgstr[0]    "un"
msgstr[1]    "beaucoup"

Note that you had msgid where you should have msgstr. You also did not specify the language, or the plural forms, and the "charset" variable threw an error during compilation.

Once you have the correct file, follow the directions under "preparing and installing a translation". Specifically, from the command line do the following:

mkdir test/inst/po/fr/LC_MESSAGES
msgfmt -c --statistics -o test/inst/po/fr/LC_MESSAGES/R-test.mo R-test.po

This will throw some errors and warnings if there are problems. If not, it should give a confirmation message.

Then rebuild the package and install it, and then try everything again:

library("test")
translatable(1)
## faucet
## napkin
## one 
translatable(2)
## faucet
## napkin 
## many 
Sys.setenv(LANG = "fr")
translatable(1)
## robinet
## serviette
## un 
> translatable(2)
## robinet
## serviette
## beaucoup

Note, you don't need to change your OS language. You can just set the LANG environment variable to get the message translations.

On a related note, I find this process really annoying, so it's on my medium-term to-do list to create a package (this one, specifically) that I hope will simplify the process.

like image 66
Thomas Avatar answered Sep 28 '22 13:09

Thomas