5

I am using poedit to translate my gettext strings. I´m using ID´s to translate, so for example the following ID:

"msg_forgot_pw"

would be translated to:

"I have forgot my password"

The string will be printed with echo, so the string should be valid HTML. Currently I´m using <br> to make new lines within the translation in Poedit. We already found out that you can use \n in the translation and than use a translation-function like Álvaro G. Vicario made. The only problem here is, that you must enter \n manually in Pedit, because it doesn´t replace a enter to a \n. So is there a way to make new lines in the output of those translation strings without putting <br> or \n manually into it?

user3292653
  • 602
  • 1
  • 7
  • 25

2 Answers2

5

The PO catalogue format itself does not restrict translations to be one-liners but you need to use proper markup:

#: example.php:2
msgid "__multi_line_example__"
msgstr ""
"One line\n"
"Two lines\n"
"Three lines\n"

Unluckily, the popular Poedit program does not make it easy: you can type actual new lines with the Enter key but they are silently discarded on save! You can insert new lines even with Poedit but you need to type a \n escape sequence manually:

New lines in Poedit

(No idea about what other graphical tools do.)

The string will be printed with echo, so the string should be valid HTML.

IMHO, accepting HTML code from translators is kind of risky. You give them too much power to break the app badly. It's normally safer to only accept plain text and escape it properly when injecting it in HTML context, e.g.:

<p><?php echo htmlspecialchars(_('msg_forgot_pw')); ?></p>

This also makes the string usable in non-HTML context (e.g., a plain text e-mail message).

My advice is that:

  1. The translatable string contains plain text
  2. You add <br> tags yourself when printing

    <p><?php echo nl2br(htmlspecialchars(_('msg_forgot_pw'))); ?></p>
    

This is pretty lengthy so I suggest writing wrappers:

/**
 * Fetches translation as HTML (block with line feeds)
 * 
 * @param string $msg_id Message ID
 * @return string HTML
 */
function p($msg_id){
    return nl2br(htmlspecialchars(_($msg_id), ENT_COMPAT | ENT_HTML401, 'UTF-8'), false);
}

/**
 * Fetches translation as HTML (single line)
 * 
 * @param string $msg_id Message ID
 * @return string HTML
 */
function l($msg_id){
    return htmlspecialchars(_($msg_id), ENT_COMPAT | ENT_HTML401, 'UTF-8');
}

Edit: The answer to the updated question is "no, not with Poedit". You'll have to live with that or find another tool.

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
  • Hey :) Thank you for your answer. You are right the function works great if you add manually \n into the textarea in poedit, but poedit doesn´t insert those \n if you click enter to make a new line. So this is not a good solution because the translator should not enter the line breaks manually (even or \n) – user3292653 Feb 19 '14 at 07:23
  • @user3292653 I've just edited my answer to correct plain wrong information about line feeds in Poedit. Sorry for the inconvenience. – Álvaro González Feb 20 '14 at 10:55
  • Ok, thanks! Is there somebody else who can answer this question? – user3292653 Feb 21 '14 at 08:19
  • @user3292653 I think you should edit the question and explain what you miss in current answers. As it's now, it only wonders if you need to use HTML and it's clear you don't (and `br` is not HTML; `
    ` is).
    – Álvaro González Feb 21 '14 at 08:25
4

A possibility would be to use "normal" linebreaks \n, \r or \r\n (depends on your platform) and replace them in PHP with the <br /> tag - there is already a PHP function for that: nl2br. I am not aware of your code design, but generally you can do this in the method you translate the keys:

function translate($key){
   // do something to get the translation from the file and store it in some variable ($translation in this case)
    return nl2br($translation)
}

and call it via:

echo translation("msg_forgot_pw");

Your translation file have to look something like this:

array(
    // you can use a \n, \r, \r\n tag
    "msg_forgot_pw" => "I have forgot \nmy password",
     // or you can simply add a linebreak
    "msg_forgot_pw2" => "I have forgot 
my password",

    // ... more entries
)
Flixer
  • 938
  • 1
  • 7
  • 20
  • See the post below, unfortunately this is not a good solution because you have to enter \n manually – user3292653 Feb 21 '14 at 08:18
  • The answer should also work with linebreaks inside your translation file. I have edited my answer, first to show how it works and additionally to use the `nl2br` method in PHP which already handles the platform independent replacement of the linebreaks to HTML-tags. – Flixer Feb 21 '14 at 12:29