FAQ
Hello,
I've started to translate my website using Catalyst::Plugin::I18N. It
works fine for static text. Bu I can't make it work for variables. For
example, I need to a translation for [% foo %] where for can take a
set of values defined in a database.

I'm sot sure what is the best way to translate such variables, and
what is possible:
* add a msgid for each possible value in messages.po => those gets
removed every time I run xgettext.pl
* Make the translation in my Database layer => unfortunately I use the
old Class::DBI, and could not find a plugin for it
* any other option?

Also, writing [% c.loc(foo) %] does not create an entry in messages.po
when running xgettext.pl, like [% c.loc('foo') %] does.

Thanks
Julien

Search Discussions

  • Ton Voon at Aug 4, 2010 at 8:04 am

    On 2 Aug 2010, at 06:08, Julien Sobrier wrote:

    Hello,
    I've started to translate my website using Catalyst::Plugin::I18N. It
    works fine for static text. Bu I can't make it work for variables. For
    example, I need to a translation for [% foo %] where for can take a
    set of values defined in a database.

    I'm sot sure what is the best way to translate such variables, and
    what is possible:
    * add a msgid for each possible value in messages.po => those gets
    removed every time I run xgettext.pl
    * Make the translation in my Database layer => unfortunately I use the
    old Class::DBI, and could not find a plugin for it
    * any other option?
    What I do is use the variable to work out the dynamic name, and then
    in a dummy template file, have the possible options. Eg:

    [% menu_name="Configuration"; c.loc(menu_name) %]

    Then in a dummy template file, have:

    [% c.loc("Configuration") %]

    This way xgettext.pl will always find it to put into messages.po. It
    means having to write in the dummy template all the possibilities, but
    it would have to be captured somewhere, so it might as well be in
    something that xgettext.pl can process.

    Ton
  • Nicholas Wehr at Aug 4, 2010 at 3:30 pm
    Check out Catalyst::Plugin::Localize::Simple

    http://search.cpan.org/~wehr/Catalyst-Plugin-Localize-Simple-1.1/lib/Catalyst/Plugin/Localize/Simple.pm

    I made it to overcome the learning curve of i18n, and it works very well.
    Used it to translate English to Spanish, French, Japanese, Italian,
    Portuguese, and Chinese Simplified. I provided a CMS for the translation
    team to create and modify these translation files. Very simple and straight
    forward. Let me know if you have questions on usage.

    -nw

    On Wed, Aug 4, 2010 at 1:04 AM, Ton Voon wrote:


    On 2 Aug 2010, at 06:08, Julien Sobrier wrote:

    Hello,
    I've started to translate my website using Catalyst::Plugin::I18N. It
    works fine for static text. Bu I can't make it work for variables. For
    example, I need to a translation for [% foo %] where for can take a
    set of values defined in a database.

    I'm sot sure what is the best way to translate such variables, and
    what is possible:
    * add a msgid for each possible value in messages.po => those gets
    removed every time I run xgettext.pl
    * Make the translation in my Database layer => unfortunately I use the
    old Class::DBI, and could not find a plugin for it
    * any other option?
    What I do is use the variable to work out the dynamic name, and then in a
    dummy template file, have the possible options. Eg:

    [% menu_name="Configuration"; c.loc(menu_name) %]

    Then in a dummy template file, have:

    [% c.loc("Configuration") %]

    This way xgettext.pl will always find it to put into messages.po. It means
    having to write in the dummy template all the possibilities, but it would
    have to be captured somewhere, so it might as well be in something that
    xgettext.pl can process.

    Ton



    _______________________________________________
    List: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive:
    http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20100804/50866be2/attachment.htm
  • Cosimo Streppone at Aug 6, 2010 at 12:44 pm

    On Mon, 02 Aug 2010 07:08:04 +0200, Julien Sobrier wrote:

    Also, writing [% c.loc(foo) %] does not create an entry in messages.po
    when running xgettext.pl, like [% c.loc('foo') %] does.
    To make that work, I think you'd have to actually *run*
    your templates for all possible cases, and then collect all
    the strings that were passed as arguments to c.loc().

    In other words, I'm not saying it's impossible, but
    xgettext.pl will probably never be able to do that.

    A slightly different approach, that works for me,
    is to create your .PO files in different stages.

    First step parses the templates with xgettext.pl and generates
    the .PO files.

    A second step can, for example, parse the actual source
    code, for stuff like '$c->loc("foo")'.
    xgettext.pl can do that with a bit of trickery.

    The new messages will be merged together in the same .PO files.

    In your case, you could pull the messages you want to be translated
    directly from the database, and write some on-the-fly
    fake templates (or text files for that matter),
    and feed them to xgettext.pl.

    --
    Cosimo
  • Ben van Staveren at Aug 6, 2010 at 12:58 pm
    I've more or less given up on it, mostly because there are a few use
    cases where text needs translated that's not easily passed through
    c->loc, for example dynamically generated descriptions and such things.
    They *could* be put through c->loc but that ties some logic too tight to
    the whole web app for it to be worthwhile.

    One thing I tend to do is just separate things to a ridiculous degree;
    instead of going [% c.loc('hi there') %], I'll in fact name it [%
    c.loc('index_tt2_hi_there') %] - which means that I need to translate
    for en_us as well (or at least put the text in). Inside perl modules,
    text that needs translated (e.g. modules that aren't tied to Catalyst),
    they all use another module I wrote that makes you "register" all
    different text identifiers, and will cache them; if you don't register
    it, you can't use it (error shows up), and once it's registered, another
    script will yank the cached entries and will merge them into an existing
    .po file if they need to be there.

    There's also the issue that I'm dealing with now where I have a web shop
    that I need to build that needs to be fully bilingual. Including product
    descriptions and names - this makes things interesting because I18N is
    absolutely useless for it, so I'm building a set of modules that attempt
    to solve the whole problem gracefully; perhaps something to stick on
    CPAN at some point.

    Cosimo Streppone wrote:
    On Mon, 02 Aug 2010 07:08:04 +0200, Julien Sobrier
    wrote:
    Also, writing [% c.loc(foo) %] does not create an entry in messages.po
    when running xgettext.pl, like [% c.loc('foo') %] does.
    To make that work, I think you'd have to actually *run*
    your templates for all possible cases, and then collect all
    the strings that were passed as arguments to c.loc().

    In other words, I'm not saying it's impossible, but
    xgettext.pl will probably never be able to do that.

    A slightly different approach, that works for me,
    is to create your .PO files in different stages.

    First step parses the templates with xgettext.pl and generates
    the .PO files.

    A second step can, for example, parse the actual source
    code, for stuff like '$c->loc("foo")'.
    xgettext.pl can do that with a bit of trickery.

    The new messages will be merged together in the same .PO files.

    In your case, you could pull the messages you want to be translated
    directly from the database, and write some on-the-fly
    fake templates (or text files for that matter),
    and feed them to xgettext.pl.
    --
    Ben van Staveren
    phone: +62 81 70777529
    email: benvanstaveren@gmail.com
  • Matthias Dietrich at Aug 6, 2010 at 1:16 pm
    Hi,

    Am 06.08.2010 um 14:58 schrieb Ben van Staveren:
    There's also the issue that I'm dealing with now where I have a web shop that I need to build that needs to be fully bilingual. Including product descriptions and names - this makes things interesting because I18N is absolutely useless for it, so I'm building a set of modules that attempt to solve the whole problem gracefully; perhaps something to stick on CPAN at some point.
    I'm using short identifiers for my I18N texts, like "Home.Greeting" which is then translated to "Hi there" for en_us or "Hall?chen" for de_de. When I added a small CMS to a customer's application all texts should also be translated. So I saved any text to I18N key CMS.NavigationPoint.PageKey.* within the right language "file" (actually I'm using C::P::I18N::DBI), * for "Title" or "Content" or similar.

    I think it should be possible to handle product descriptions like this. In your Backend save every text to Product.$ArticleNumber.Description, Product.$ArticleNumber.Name, Product.$ArticleNumber.Variant and so on where $ArticleNumber is the actual article number. The possible languages should be somewhere in your Catalyst config.

    Matthias

    --
    rainboxx Software Engineering
    Matthias Dietrich

    rainboxx Matthias Dietrich | Phone: +49 7141 / 2 39 14 71
    K?nigsallee 43 | Fax : +49 3222 / 1 47 63 00
    71638 Ludwigsburg | Mobil: +49 151 / 50 60 78 64
    CPAN: http://search.cpan.org/~mdietrich/
    XING: https://www.xing.com/profile/Matthias_Dietrich18
    GULP: http://www.gulp.de/profil/rainboxx.html
  • Ben van Staveren at Aug 6, 2010 at 1:52 pm
    Hi Matthias,

    That's what I considered at some point, but what happens there is that
    you are more or less totally working around the I18N module at that
    point. I did some experimenting with a subclass of TT that was actually
    "translation" aware and would do it on a much lower level (given that I
    use TT for the web-facing end of the app, as well as for emails,
    generated files on disk, and even use it to an extend to generate
    shipping labels).

    Matthias Dietrich wrote:
    Hi,

    Am 06.08.2010 um 14:58 schrieb Ben van Staveren:

    There's also the issue that I'm dealing with now where I have a web shop that I need to build that needs to be fully bilingual. Including product descriptions and names - this makes things interesting because I18N is absolutely useless for it, so I'm building a set of modules that attempt to solve the whole problem gracefully; perhaps something to stick on CPAN at some point.
    I'm using short identifiers for my I18N texts, like "Home.Greeting" which is then translated to "Hi there" for en_us or "Hall?chen" for de_de. When I added a small CMS to a customer's application all texts should also be translated. So I saved any text to I18N key CMS.NavigationPoint.PageKey.* within the right language "file" (actually I'm using C::P::I18N::DBI), * for "Title" or "Content" or similar.

    I think it should be possible to handle product descriptions like this. In your Backend save every text to Product.$ArticleNumber.Description, Product.$ArticleNumber.Name, Product.$ArticleNumber.Variant and so on where $ArticleNumber is the actual article number. The possible languages should be somewhere in your Catalyst config.

    Matthias
    --
    Ben van Staveren
    phone: +62 81 70777529
    email: benvanstaveren@gmail.com
  • Bill Moseley at Aug 6, 2010 at 2:57 pm

    On Fri, Aug 6, 2010 at 6:16 AM, Matthias Dietrich wrote:

    I'm using short identifiers for my I18N texts, like "Home.Greeting" which
    is then translated to "Hi there" for en_us or "Hallöchen" for de_de. When I
    added a small CMS to a customer's application all texts should also be
    translated. So I saved any text to I18N key CMS.NavigationPoint.PageKey.*
    within the right language "file" (actually I'm using C::P::I18N::DBI), * for
    "Title" or "Content" or similar.
    I've been arguing with work about how to key our text. So far we continue
    to use the English in the loc() tags in the templates, and then the I18N
    team uses a script to pull out this text which gets sent to translation
    services.

    The risk is text gets into the templates that for some reason does not get
    pulled out. The developers like the English in the templates as it makes
    them easy to read, and it means they don't really have to stop when entering
    new text. Just seems like in the long run this will be unmaintainable and
    error prone. (Well, not in the long run as it already is error prone.)

    I've been arguing for a system where we use some kind of ID for the keys.
    I'm not so sure the key format matters -- could be just a primary key in
    the db, for example. This could be a stage done by the designers so the
    design spec just indicates a message id. Then code development and
    translation can happen at the same time.

    Is anyone using a system like that? And more specifically, what application
    are you using to manage the translation database? We have started to write
    one, but it's a bit more than trivial as we need it to work with different
    translation services, track history/changes, multiple applications, etc.
    So, it would make more sense to use an existing tool.

    So, I'd like to hear about your translation workflow and any tools you are
    using.

    Thanks,


    --
    Bill Moseley
    moseley@hank.org
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20100806/890c1518/attachment.htm
  • Cosimo Streppone at Aug 6, 2010 at 3:18 pm

    On Fri, 06 Aug 2010 16:57:42 +0200, Bill Moseley wrote:

    I've been arguing with work about how to key our text. So far we
    continue to use the English in the loc() tags in the templates, and then
    the I18N
    team uses a script to pull out this text which gets sent to translation
    services.
    We also chose to use english text as message keys.
    I wanted to avoid ids because:

    1) Retrofitting i18n in an existing app would make you
    spend weeks/months replacing all the text messages with ids.

    2) Designers or front-end developers work suddenly
    becomes much harder. You need to provide them a database of
    already used IDs and what they mean.

    3) With IDs it's difficult to identify when a message
    has arguments, and which ones, or even how many of them:

    "Hello, [_1], you have [_quant,_2,message,messages,no messages]"

    The main disadvantage I see is that when you change your text,
    all the .PO files need to be updated, so you actually kill some
    of the existing messages, and you have to manage that with
    your i18n tools.
    So, I'd like to hear about your translation workflow and any tools you
    are using.
    I found the latest Transifex (0.9.0+) very good for us:

    http://trac.transifex.org/

    We're managing our own instance. Pay attention if you
    plan to do that:

    http://my.opera.com/cstrep/blog/2010/06/22/dependencies-suck

    --
    Cosimo
  • Ben van Staveren at Aug 6, 2010 at 3:22 pm
    Hi Bill,

    Back in the day (heh) we faced the same problem for an app we were doing
    for a client, because the client insisted they wanted the ability to do
    their own translations, we ended up with text keyed on the location
    where it was called from, and the actual english string. So in a
    template we'd get

    index.tt2(hello there, customer) as the key, but inside the template it
    was generated by doing [% f.xlat("hello there, customer") %] - or if you
    wanted parameters it was more like [% f.xlat("hello there, %",
    array_of_data) %].

    We used one script that would just walk the template directory, and
    would set up the stash like this:

    $stash = {
    f => {
    xlat => sub {
    my $string = shift;
    my @params = (@_);
    ...
    },
    },
    };

    We'd run it, and based on filename and the actual string passed it'd
    generate the "master key file" - some more scripts would look at
    duplicates (e.g. if more than one template contained the same string)
    and would generate a yaml configuration file containing a string =>
    template mapping.

    Similarly, inside perl modules we used the same mechanism, also
    described this in an earlier reply; where all translation strings *had*
    to be "registered" during module initialisation and it would then dump
    these to it's own master key file.

    Rinse, repeat, merge. This then ended up going through the actual
    application's admin interface into the database, where it'd also flag
    everything that required translation into the available languages, so
    that the clients' translator team could go and take care of it.

    In the end probably not the most graceful of solutions, and error-wise
    there were a few where certain phrases could have different meanings
    based on context but the code couldn't determine that - but usually that
    got fixed with a little rephrasing in choice locations :)

    That's also the system I'm currently using in a slightly modified form
    for the webshop I'm building at the moment. I'll see if I can roll it
    all up into something distributable and put it online for download but
    that will have to happen some time later.


    Bill Moseley wrote:

    On Fri, Aug 6, 2010 at 6:16 AM, Matthias Dietrich wrote:

    I'm using short identifiers for my I18N texts, like
    "Home.Greeting" which is then translated to "Hi there" for en_us
    or "Hall?chen" for de_de. When I added a small CMS to a
    customer's application all texts should also be translated. So I
    saved any text to I18N key CMS.NavigationPoint.PageKey.* within
    the right language "file" (actually I'm using C::P::I18N::DBI), *
    for "Title" or "Content" or similar.


    I've been arguing with work about how to key our text. So far we
    continue to use the English in the loc() tags in the templates, and
    then the I18N team uses a script to pull out this text which gets sent
    to translation services.

    The risk is text gets into the templates that for some reason does not
    get pulled out. The developers like the English in the templates as
    it makes them easy to read, and it means they don't really have to
    stop when entering new text. Just seems like in the long run this
    will be unmaintainable and error prone. (Well, not in the long run as
    it already is error prone.)

    I've been arguing for a system where we use some kind of ID for the
    keys. I'm not so sure the key format matters -- could be just a
    primary key in the db, for example. This could be a stage done by the
    designers so the design spec just indicates a message id. Then code
    development and translation can happen at the same time.

    Is anyone using a system like that? And more specifically, what
    application are you using to manage the translation database? We have
    started to write one, but it's a bit more than trivial as we need it
    to work with different translation services, track history/changes,
    multiple applications, etc. So, it would make more sense to use an
    existing tool.

    So, I'd like to hear about your translation workflow and any tools you
    are using.

    Thanks,


    --
    Bill Moseley
    moseley@hank.org ------------------------------------------------------------------------

    _______________________________________________
    List: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/
    --
    Ben van Staveren
    phone: +62 81 70777529
    email: benvanstaveren@gmail.com
  • Matthias Dietrich at Aug 6, 2010 at 4:33 pm
    Hi Bill,

    Am 06.08.2010 um 16:57 schrieb Bill Moseley:
    I've been arguing with work about how to key our text. So far we continue to use the English in the loc() tags in the templates, and then the I18N team uses a script to pull out this text which gets sent to translation services.

    The risk is text gets into the templates that for some reason does not get pulled out.
    yes, that's an issue with my solution, too. You code and add texts and if you don't add them immediately to the database you may get lost. Especially when you have code with I18N text that only gets called in some special circumstances that you can hardly simulate, so your text stays as a key (or english text) until someone stumbles upon this special case and reports.
    I've been arguing for a system where we use some kind of ID for the keys. I'm not so sure the key format matters -- could be just a primary key in the db, for example. This could be a stage done by the designers so the design spec just indicates a message id. Then code development and translation can happen at the same time.
    Using an integer ID doesn't sound useful to me. An ID doesn't say anything about what it should be replaced with, a key does (should). My keys also have arguments like "Home.Greeting[_1]" which could be translated to "Hello [_1]".

    A disadvantage of using english as identifier is: when you change the text, say you have a typo in it, you need to change all you translations so they have the correct identifier again. If you have a key (or integer ID), changing the typo is easy because there is a additional translation and typos in your keys are irrelevant.
    So, I'd like to hear about your translation workflow and any tools you are using.
    My tools were pgAdmin3 and some AutoCRUD until now, because there has not been any "big" translation. In a project at my former employer we wrote a small Excel import script because the customer translated every text with Excel. There's no magic here that could help you, sorry.

    Thanks,
    Matthias

    --
    rainboxx Software Engineering
    Matthias Dietrich

    rainboxx Matthias Dietrich | Phone: +49 7141 / 2 39 14 71
    K?nigsallee 43 | Fax : +49 3222 / 1 47 63 00
    71638 Ludwigsburg | Mobil: +49 151 / 50 60 78 64
    CPAN: http://search.cpan.org/~mdietrich/
    XING: https://www.xing.com/profile/Matthias_Dietrich18
    GULP: http://www.gulp.de/profil/rainboxx.html
  • Ton Voon at Aug 6, 2010 at 11:03 pm

    On 6 Aug 2010, at 15:57, Bill Moseley wrote:

    I've been arguing with work about how to key our text. So far we
    continue to use the English in the loc() tags in the templates, and
    then the I18N team uses a script to pull out this text which gets
    sent to translation services.
    For Opsview (http://opsview.com), we decided early on to use message
    ids. I'm very glad of this decision (after pain in my work on the
    Nagios Plugins using English text as the key).

    After chatting to a Java guy who already implemented i18n in his app,
    we went with a dotted notation like:

    [% c.loc("ui.admin.host.edit.label.hostaddress") %]

    The dotted notation is good because it gives a pretty good idea where
    in the app this text will be found. The last part can be as complex as
    you like to describe the content. Variables work with:

    [% c.loc("ui.admin.host.edit.label.numberOfAddresses [_1]",
    num_addresses) %]

    Obviously, there needs to be an English translation. This is when I
    spent about 10 hours of my life trying to work out how
    Locale::Maketext::Simple was not doing a fallback as I expected. A
    patch was made and thankfully this works properly now if you set
    your .po file to be called i_default.po: http://cpansearch.perl.org/src/JESSE/Locale-Maketext-Simple-0.19/Changes

    I run a make gettext in my cat app that calls xgettext.pl and some
    other perl code to check for missing strings in i_default.po. It also
    updates all our language files with any new msgids but sets msgstr to
    "". This is good because: (1) Locale::Maketext::Simple will now
    fallback to i_default.po and (2) anyone translating the .po files can
    easily see which strings still need translating.

    So overall I think our workflow is pretty good. I can write a Cat
    advent calendar entry for this if interested.

    Ton
  • Tomas Doran at Aug 7, 2010 at 12:29 pm

    On 7 Aug 2010, at 01:03, Ton Voon wrote:

    I can write a Cat advent calendar entry for this if interested.
    YES!

    We were happy to take submissions for this years advent as of Jan 1st,
    so please do so! ;)

    (Any time before mid december)

    Cheers
    t0m

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedAug 2, '10 at 5:08a
activeAug 7, '10 at 12:29p
posts13
users9
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2021 Grokbase