I'm having trouble logging the output of an internationalized django variable.
My application code used the 'message' vaiable OK and it displays
in English and German (the two languages I am working with)
My problem is when I try to make a log of the said 'message' variable output.
I want to log in English and/or German (depending on what the end user is seeing)
I'm using string_concat and it says:
the lazy translations in result will only be converted to strings when result
itself is used in a string (usually at template rendering time).
Here is a code sample:
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import string_concat
message = _('Profile Updated OK')
# Build a log message
fmt_msg = _(message)
log_message = 'Message Sent: '
log_message = string_concat(log_message, fmt_msg)
logger.info(log_message)
The log entry is not translated:
Message Sent: <django.utils.functional.__proxy__ object at 0x9c3c4ac>
Can anyone suggest how I can have the proxy object to be translated
when used with logging?
It's translating OK in my regular Django code just the logging.info() issue.
Cheers!
From the docs:
The result of a ugettext_lazy() call can be used wherever you would use a unicode string (an object with type unicode) in Python. If you try to use it where a bytestring (a str object) is expected, things will not work as expected, since a ugettext_lazy() object doesn't know how to convert itself to a bytestring.
Also, don't call _() twice.
logger.info(u'Message Sent: %s' % message)
You have to force Unicode strings, as documented in http://www.djangobook.com/en/2.0/chapter19/
u"Hello %s" % ugettext_lazy("people")
And do not call the function twice ;)
Related
We are using axios to pass GET request to our django instance, that splits it into search terms and runs the search. This has been working fine until we ran into an edge case. We use urlencode to ensure that strings do not have empty spaces or others
So generalize issue, we have TextField called "name" and we want to search for term "A & B Company". However, issue is that when the request reaches django.
What we expected was that name=A%20&%20B%20Company&field=value would be parsed as name='A & B Company' and field='value'.
Instead, it is parsed as name='A ' 'B Company' and field='value'. The & symbol is incorrectly treated as separator, despite being encoded.
Is there a way to indicate django GET parameter that certain & symbols are part of the value, instead of separators for fields?
You can use the lib urllib
class ModelExample(models.Model):
name = models.TextField()
# in view...
from urllib.parse import parse_qs
instance = ModelExample(name="name=A%20&%20B%20Company&field=value")
dict_qs = parse_qs(instance.name)
dict_qs contains a dict with decoded querystring
You can find more informations about urllib.parse here: https://docs.python.org/3/library/urllib.parse.html
I have a very simple flask graphql app and everything work as I aspect, I can call it from my browser and it returns the given data.
But if I send a string which contains '&' I always get the message "Syntax Error GraphQL (1:22) Unterminated string \n\n1: (...) \n ^\n"
The browser split the given string treated it as parameter.
Is there any workaround to handle this?
#!/usr/bin/env python3
import flask
import flask_graphql
import graphene
app = flask.Flask('graphql-test')
class Query(graphene.ObjectType):
helloz = graphene.String(text=graphene.String())
def resolve_helloz(self, info, text):
return text
#app.route('/')
def index():
# Create graphql view with the authentication passed as context
return flask_graphql.GraphQLView.as_view(
'index',
schema=graphene.Schema(query=Query),
graphiql=False
)()
if __name__ == '__main__':
# Run application
app.run(host='127.0.0.1', port='8001')
If you are sending the query as a query parameter, you need to escape any characters that have a special meaning, like & and ?. & is used to delimit individual parameters, so without escaping it, the query parameter ends up being interpreted as {helloz(text:"test -- which is not valid GraphQL syntax. You should instead send:
127.0.0.1:8001?query={helloz(text:"test%26test")}
This is a very basic question. I tried to google to find answers that I could understand in simple language. but that did not help. I came across the below snippet of code in Django's UserCreationForm and only then I know something ugettext_lazy _ exists. I have no idea, if it is a django specific module/function, what's its purpose and why it should be used.
There is this article in SO, which discuss more on this. but I want to grasp the fundamentals first. Please enlighten me!
from django.utils.translation import ugettext, ugettext_lazy as _
///// what is the _ means here and why is it used
class UserCreationForm(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given username and
password.
"""
error_messages = {
'duplicate_username': _("A user with that username already exists."),
'password_mismatch': _("The two password fields didn't match."),
}
ugettext is a unicode version of a translatable string.
ugettext_lazy is a "lazy" version of that. Lazy strings are a Django-ism; they are string-like objects that don't actually turn into the real string until the last possible minute. Often, you can't know how to translate a string until late in the process. I don't know what language a browser uses until I can look at their request, so I want the translation string to be "lazy" and not evaluate until it absolutely needs to be rendered in the template, for instance.
For your purpose, it means these will appear as strings--but it also means that they might be overridden by translations. So, for example, you could change the duplicate-username message to _("Sorry, but a user with that name exists. Please try again"). For English-speaking browsers, they'd see your new message. If this string has a translation already registered, though, you'd be breaking it--now the lookup for the Spanish-language version would fail, since it wouldn't find a matching string to yours for Spanish.
For 95% of sites, this doesn't matter, since you won't offer a translated version of your site. If it does, you should read https://docs.djangoproject.com/en/dev/topics/i18n/.
I have weird problem with django translations that i need help figuring out. Problem is that instead of getting translated string every time i seem to get randomly either translated string or default string.
I have created a class for putting "action" buttons on several pages. Many of those buttons are reusable so why should i put
blabla
into several templates when i can create simple toolbar and use
toolbar.add(tool)
in view and then just use templatetag for rendering all the tools.... anyway.
This is example of one tool:
class NewUserGroupButton(MyTool):
tool_id = 'new-user-group'
button_label = ugettext(u'Create new user group')
tool_href = 'new/'
js = ()
def render(self):
s = '<a id="%(tool_id)s" href="%(tool_href)s" class="button blue">%(button_label)s</a>'
return s % {'tool_id': self.tool_id, 'tool_href': self.tool_href, 'button_label':self.button_label}
The tools are rendered like this:
class ToolbarTools:
def __init__(self):
self.tools = []
def add(self, tool):
self.tools.append(tool)
def render(self):
# Organize tools by weight
self.tools.sort(key=lambda x: x.weight)
# Render tools
output = '<ul id="toolbar" class="clearfix">'
for tool in self.tools:
output += '<li id="%s">' % ('tool-'+ tool.tool_id)
output += tool.render() if tool.renderable else ''
output += '</li>'
output += '</ul>'
# Reset tools container
self.tools = []
return mark_safe(output)
im using ugettext to translate the string. using (u)gettext=lambda s:s or ugettext_lazy gives me either no translations or proxy object corresponding to function choices.
And like i said - while rest of the page is in correct language the toolbar buttons seem to be randomly either translated or not. The faulty behaviour remains consistent if i move between different pages with different "tools" or even refresh the same page several times.
Could someone please help me to figure out what is causing this problem and how to fix it?
Problem solved.
The issue itself (random translating) was perhaps caused by using ugettext. But at the same time i should have used ugettext_lazy instead.
And thus the problem really came from ugettext_lazy returning proxy object not translated string... and that is caused by this:
[Quote]
Working with lazy translation objects
The result of a ugettext_lazy() call can be used wherever you would use a unicode string (an object with type unicode) in Python. If you try to use it where a bytestring (a str object) is expected, things will not work as expected, since a ugettext_lazy() object doesn't know how to convert itself to a bytestring. You can't use a unicode string inside a bytestring, either, so this is consistent with normal Python behavior. For example:
This is fine: putting a unicode proxy into a unicode string.
u"Hello %s" % ugettext_lazy("people")
This will not work, since you cannot insert a unicode object
into a bytestring (nor can you insert our unicode proxy there)
"Hello %s" % ugettext_lazy("people")
[/Quote]
taken from here:
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#working-with-lazy-translation-objects
Alan
I had the same issue just now. The problem was caused by incorrect Middleware order - I set LocaleMiddleware after CommonMiddleware. After I placed it between SessionMiddleware and CommonMiddleware, it seems to work correctly.
See more here: https://lokalise.com/blog/advanced-django-internationalization/
I know, the problem was solved a long ago, but it can be helpful for someone.
I am using
rf['email'].errors
As said in docs, I can use it to have array of errors.
[str(e) for e in rf['email'].errors] #give me ["<django.utils.functional.__proxy__>"]
If repr or str - it gives ul's or string of array.
So it worked only when I used repr and eval together. But I think its stupid solution.
eval(`rf['email'].errors`)
You have a couple options depending on the output you'd like.
Option one, use the unicode constructor to convert the data:
list_of_error_texts = [unicode(e) for e in rf['email'].errors]
(Django's proxy object implements a method that responds to unicode.)
Option two, get the ErrorList as text. This produces a newline separated list of error text, with each line preceded by an asterisk:
print rf['email'].errors.as_text()
* My error one
* My error two
Option three, use django's force_unicode function. This is like unicode, but has some extra safety features:
from django.utils.encoding import force_unicode
list_of_error_texts = [force_unicode(e) for e in rf['email'].errors]