9

I am looking at gettext and .po files for creating a multilingual application. My understanding is that in the .po file msgid is the source and msgstr is the translation. Accordingly I see 2 ways of defining msgid:

Using full text (e.g. "My name is %s.\n") with the following advantages:

  • when calling gettext you can clearly see what is about to be translated
  • it's easier to translate .po files because they contain the actual content to be translated

Using a key (e.g. my-name %s) with the following advantages:

  • when the source text is long (e.g. paragraph about company), gettext calls are more concise which makes your views cleaner
  • easier to maintain several .po files and views, because the key is less likely to change (e.g. key of company-description far less likely to change than the actual company description)

Hence my question:
Is there a way of working with gettext and .po files that allows combining the advantages of both methods, that is:
-usage of a keys for gettext calls
-ability for the translator to see the full text that needs to be translated?

Community
  • 1
  • 1
Max
  • 12,794
  • 30
  • 90
  • 142

2 Answers2

7

gettext was designed to translate English text to other languages, and this is the way you should use it. Do not use it with keys. If you want keys, use some other technique such as an associative array.

I have managed two large open-source projects (50 languages, 5000 translations), one using the key approach and one using the gettext approach - and I would never use the key approach again.

The cons include propagating changes in English text to the other langauges. If you change

msg_no_food = "We had no food left, so we had to eat the cats"

to

msg_no_food = "We had no food left, so we had to eat the cat's"

The new text has a completely different meaning - so how do you ensure that other translations are invalidated and updated?

You mentioned having long text that makes your scripts hard to read. The solution to this might be to put these in a separate script. For example, put this in the main code

print help_message('help_no_food')

and have a script that just provides help messages:

switch ($help_msg) {
...
case 'help_no_food': return gettext("We had no food left, so we had to eat the cat's");
...
}

Another problem for gettext is when you have a full page to translate. Perhaps a brochure page on a website that contains lots of embedded images. If you allow lots of space for languages with long text (e.g. German), you will have lots of whitespace on languages with short text (e.g. Chinese). As a result, you might have different images/layout for each language.

Since these tend to be few in number, it is often easier to implement these outside gettext completely. e.g.

brochure-view.en.php
brochure-view.de.php
brochure-view.zh.php
fisharebest
  • 1,300
  • 10
  • 16
  • Good point about invalidation. The alternative you're suggesting (with the `switch` example) adds an additional layer, which is basically what I would like from a translation format, that is to have a `1 - key/id` to keep views more concise and easily maintained, `2 - source` to make sure we have the exact source which is used for invalidation, and `3 - translation`. Do you know if any translation formats have that structure? – Max Apr 02 '13 at 19:05
  • As I said, I'd steer away from keys if at all possible. In my experience, it makes it harder to read/debug code - not easier. I only use them (indirectly via a switch) for help text, which tends to sit outside the rest of the code anyhow. PO format is great because it is widely used and understood by translators (as opposed to developers) and there are lots of tools to make their job easier. – fisharebest Apr 02 '13 at 20:57
  • 3
    I fully understand what you're saying but there is one thing I can't get my head around: when you need to render the translation for an entire paragraph (e.g. company history): do you use the entire English paragraph in the `gettext` call? Sounds horrible to me, IMO it would make much more sense to do `gettext('company-history')` – Max Apr 05 '13 at 08:23
  • @Max I don't like using strings as keys because there's no compile-time check that a key actually exists ("magic strings"). Is there a way to use `gettext` with PHP's `define` feature? That way there will be an error if the key doesn't exist (and decent IDE autocompletion too). – Dai Jul 08 '16 at 00:27
3

I just answered a similar (much older) question here.

Short version:

The PO file format is very simple, so it is possible to generate PO/MO files from another workflow that allows the flexibility you're asking for. (your devs want identifiers, your translators want words)

You could roll this solution yourself, or use a cloud-based app like Loco to manage your translations and export a Gettext file with identifiers when your devs need them.

Community
  • 1
  • 1
Tim
  • 8,036
  • 2
  • 36
  • 52
  • I'm on your side here so not too objective with accepting your answer but I'm really convinced that's the way to go: keep `PO` because it's widely used and easy to manipulate, build whatever intermediate steps to create them from and use them in your application: that way everybody is happy and you keep relying on what other people use too (except for your custom layer obviously). – Max Jun 05 '13 at 13:05