Louis Go
Louis Go

Reputation: 2588

Babel - Using both `msgstr` and `msgid` without duplicate static strings

Take this as an example while I tried to minimize code duplication.

msg = 'User request is completed'
logging.info(msg) 
reply(_(msg))     # Babel would failed to extract the variable `msg`.

I know babel cannot extract variables but I'd like to find a way to keep both msgid and msgstr in my code while making babel extract without the problem.

To keep both msgid and msgstr, I have to write duplicate code

from flask_babel import _
# I'd like to find a way to just change one line instead of two.
logging.info('User request is completed') # 1. log msgid
reply(_('User request is completed'))     # 2. reply msgstr which is returned by `_()`

I wan to log with msgid and reply translated msgstr.
It's easier to lookup the log in a fixed language or it'd be hard for looking into the log in Klingon. (No offense to Klingon)

Eg: Log User request is completed while reply qaStaHvIS qemlI'.

I'm using flask_babel but I believe this question should be common for babel. I cannot find a solution for it. Probably my skill for search engine is not good enough. Please let me know if there is any related post.

My naive way to deal with it:


# `msg` is translated string 'qaStaHvIS qemlI'
# `msgid` is the id 'User request is completed'
msg, msgid = gettext_and_id('User request is completed') # No such function in babel
logging.info(msgid)
reply(msg)

However I did check the source code of flask-babel and there is no similar functions.
Indeed, I could make a helper function on my own, but I'd like to have a better solution.

def gettext_and_id(msgid):
    return gettext(msgid), msgid

However this solution doesn't fix everything. If I want to use Some {file} as a string for substitution, then it's still tedious...

filename = 'neverland'
# ... file doesn't exist
msg, msgid = gettext_and_id('{file} is not found')
msg = msg.format(file=filename)
msgid = msgid.format(file=filename)

Upvotes: 1

Views: 386

Answers (1)

AKX
AKX

Reputation: 169388

Babel won't be able to pick up the string t's contents into a catalog from the expression _(t), because that would involve either static analysis to try and figure out if t is statically assigned, or actually running the code and capturing all _() invocations, both of which are a bit tough to do.

You can configure a custom keyword, say, msgid, and define that function in your program to simply return the same string at runtime.

Then you can do

msg = msgid('User request is completed')
logging.info(msg) 
reply(_(msg))

and Babel would pick up the message, but it would only actually get translated by the _() call.

Alternately, if you don't want to pay the runtime price for that identity msgid function, you could write a custom Babel extractor and tag your messages with some special syntax, e.g. here a # msgid comment:

msg = 'User request is completed'  # msgid
logging.info(msg) 
reply(_(msg))

Upvotes: 1

Related Questions