Get translatable text from an external source into catalog - python

Possibly i am overlooking an obvious solution or thinking the wrong way...
I have a limited amount of text, words in a database, that I want to display translated to users in a flask/jinja/babel webapp. eg. "running" is a possible value of an "activity" column and that should be "laufen" for my german users.
Words in templates and code are extracted and put into the catalog, but how do i get additional words into the catalog? Is there a simple text file extractor?
The only thing i could think of is, just create a .py file and put lots of _('...') lines in them, but that feels just wrong... is it?

I created a messages.txt with my "words" like gettext function calls:
_('cycling')
_('running')
and added it to my babel.cfg as python source:
[python: messages.txt]
plain, simple, stupid, but works.

First, start with http://flask.pocoo.org/snippets/4/.
Secondly, you need to store these 'limited' values as integers or enums in database and then create the lookup table for all these enums in code (so Babel knows about them):
i18n_val = {0: _('running'), ...}
# Or multi-level dict with different categories:
i18n_all = {
'activity': {
0: _('running'), ...
'foo': {
0: _('bar..'), ...
}
}
And accessing the translated string from template is now as simple as:
{{ i18n_val[obj.activity] }}
{{ i18n_all['activity'][obj.activity] }}
In order to make the i18n_val and i18n_all variables available for all the templates, just register them with context processors.

Related

Permanently replace value in Django

After extensive googling, I still havent come up with an effecient way to solve this.
Im creating a website using Django. I have a db which contains time data, more specifically dates. The value for "the present" is set to 3000-01-01 (YYYY-MM-DD) as is common practice for time-querying.
What I want to do is display a string like "Now" or "Present" or any other value instead of the date 3000-01-01. Is there some sort of global override anywhere that I can use? Seems like a waste to hard-code it in every view/template.
Cheers!
Since this is rendering, I would advice against "subclassing" the DateField such that it renders 'now' instead of the original date(..) object: it will make calculations in the model layer more cumbersome.
Probably a good way to deal with this is implementing a template filter [Django-doc], for example we can construct a file:
# app/templatetags/nowdate.py
from django import template
register = template.Library()
PRESENT = date(3000, 1, 1)
#register.filter
def nowdate(value):
if value == PRESENT:
return 'present'
return value
The templatetags directory of the app application, needs to contain an __init__.py file as well (an empty file), and the app of course needs to be part of the INSTALLED_APPS in the settings.py.
Then we can use it in the template like:
<!-- app/templates/app/some_template.html -->
{{ some_model.some_date_field|nowdate }}
Here we thus fetch the some_date_field of the some_model variable (this attribute is thus a date(..) object), and we pass it through the nowdate filter we have constructed such that, if it is 3000-01-01, it is replaced by the 'present' string.
The advantage here is that if we later change our mind about what date the "present" is, we can easily change it in the template filter, furthermore we can easily extend it, for example by adding a 'past', 'future', etc.

Replacing a variable name in text with the value of that variable

I have a template that uses placeholders for the varying content that will be filled in. Suppose the template has:
"This article was written by AUTHOR, who is solely responsible for its content."
The author's name is stored in the variable author.
So I of course do:
wholeThing = wholeThing.replace('AUTHOR', author)
The problem is I have 10 of these self-named variables, and it would just be more economical if I could something like this, using only 4 for brevity:
def(self-replace):
...
return
wholeThing = wholeThing.self-replace('AUTHOR', 'ADDR', 'PUBDATE', 'MF_LINK')
With Python 3.6+, you may find formatted string literals (PEP 498) efficient:
# data from #bohrax
d = {"publication": "article", "author": "Me"}
template = f"This {d['publication']} was written by {d['author']}, who is solely responsible for its content."
print(template)
This article was written by Me, who is solely responsible for its content.
Sounds like what you need is string formatting, something like this:
def get_sentence(author,pud_date):
return "This article was written by {}, who is solely responsible for its content. This article was published on {}.".format(author,pub_date)
Assuming you are parsing the variables that make up the string iteratively, you can call this function with the arguments needed and get the string returned.
That str.format() function can be placed anywhere and can take any number of arguments as long as there is a place for it in the string indicated by the {}. I suggest you play around with this function on the interpreter or ipython notebook to get familiar with it.
If you have control over the templates I would use str.format and a dict containing the variables:
>>> template = "This {publication} was written by {author}, who is solely responsible for its content."
>>> variables = {"publication": "article", "author": "Me"}
template.format(**variables)
'This article was written by Me, who is solely responsible for its content.'
It is easy to extend this to a list of strings:
templates = [
"String with {var1}",
"String with {var2}",
]
variables = {
"var1": "value for var1",
"var2": "value for var2",
}
replaced = [template.format(**variables) for template in templates]

Create a engine to replace template entries with json objects in python

I want to create an engine in python that can replace tags in a template file with objects from json? I've loooked at python based engines that use regex but they are overly complicated and I am a little confused as to how to start an go about it. Any code to start would help
Sample json file
{
"webbpage": {
"title": "Stackoverflow"
},
"Songs": {
"name": "Mr Crowley"
},
"CoverArtists": [
{ "name": "Ozzy", "nicknames": ["Ozzman","Ozzster"] },
{ "name": "Slipknot", "nicknames": ["Slip"] }
]
}
Sample template file
<html>
<head>
<title><%% webbpage.title %%></title>
</head>
<body>
<h1><%% Songs.name %%></h1>
<%% EACH CoverArtists artist %%>
<%% artist.name %%>
<%% EACH CoverArtists.nicknames nickname %%>
<p><%% nickname %%></p>
<%% END %%>
<%% END %%>
</body>
</html>
Basically variables are identified between <%% and %%> and loops are identifed between <%% EACH .. %%> AND <%% END %%> and basically output html
Check out Alex Mitchells blog on templating (python based), it's extremely helpful, and the related GIT here
Basically,
Take input files on command line
Parse template file - build Abstract Syntax tree to parse easily. Create a node base type, and then for each new type implement a concrete class
Build stack to keep track of loops, pop when loops close, look for errors of missing loop ends
Parse json file, build dictionary of objects, map AST entries and replace in html
Write output to file.
I have a version of this based on Alex mitchells engine here, where I've fixed some issues with the original one( and put it in some code of my own) and will be trying to get rid of the reg exp based matching and put in contextual matching, because regular expressions dont work too well on large complex HTML data.
So basically you need to identify tokens within <%% and %%>. This step can be done with a regular expression, e.g. :
>>> import re
>>> t='<h1><%% Songs.name %%></h1>'
>>> re.search(r'<%%(.+?)%%>', t).groups()
(' Songs.name ',)
Parsing the code that this gives is quite a complicated task, and you might find some help in shlex or tokenizer. Even if you need to use regular expressions for the entire project, I suggest you take a look at these, and examples from other languages, to understand how a syntax parser works.
Once you've parsed the language, the next step is to replace the tokens with values from json. The best way would be to first load the data into python dicts, and then write a renderer to insert the data into the html.
Even if you can't use them, you should still have a look at some templating engines such as jinja or chameleon and study their source code to get an idea of how such a project is put together.

Getting journal articles by category: Liferay Portlet written in Python

I am trying to write a simple Liferay portlet in Python. The portlet will show a list of categories and when clicked will show a list of Web Content articles (journal articles) of a certain structure.
I am able to get the list of categories but cannot find a way using the liferay api to get a list of articles by category?
I have searched allover but it seems to me the method should be on this page:
http://docs.liferay.com/portal/6.1/javadocs/com/liferay/portlet/journal/service/JournalArticleLocalServiceUtil.html
It is a Java implementation but really easy to convert into python.
<%
String languageId = LanguageUtil.getLanguageId( renderRequest );
List<JournalArticle> journalArticleList = new ArrayList<JournalArticle>();
AssetEntryQuery assetEntryQuery = new AssetEntryQuery();
assetEntryQuery.setAnyCategoryIds(new long[] { 12704 }); //category Id
assetEntryQuery.setOrderByCol1("modifiedDate");
assetEntryQuery.setEnd(5);
List<AssetEntry> assetEntryList = AssetEntryLocalServiceUtil.getEntries(assetEntryQuery);
for (AssetEntry ae : assetEntryList) {
JournalArticleResource journalArticleResource = JournalArticleResourceLocalServiceUtil.getJournalArticleResource(ae.getClassPK());
JournalArticle journalArticle = JournalArticleLocalServiceUtil.getLatestArticle(journalArticleResource.getResourcePrimKey());
JournalContentUtil.clearCache();
String content = JournalContentUtil.getContent(journalArticleResource.getGroupId(), journalArticle.getArticleId(), "view", languageId, themeDisplay);
out.println("<br>"+journalArticle.getTitle(languageId)+"<br>");
out.println(content);
}
%>
The proposed solution is good yet needs one extra piece. It will return all Assets - web-content-articles are a subset of assets. For example, you will get documents (which have been categorized the same way) as well. To refine your search, add a className, classNameid, or classTypeId to the AssetEntryQuery (in addition to the category id). Alternatively, within the for-loop you could pick out the web-content, ignore the others.
Thanks, AssetEntryQuery was the solution:
from com.liferay.portlet.asset.service.persistence import AssetEntryQuery
from com.liferay.portlet.asset.service import AssetEntryServiceUtil
aq = AssetEntryQuery()
aq.setAllCategoryIds([442492])
articles = AssetEntryServiceUtil.getEntries(aq)
for a in articles:
out.write(str(a.title))
out.write(str(a))

Creating views in django (string indentation problems)

I am new to both Python (and django) - but not to programming.
I am having no end of problems with identation in my view. I am trying to generate my html dynamically, so that means a lot of string manipulation. Obviously - I cant have my entire HTML page in one line - so what is required in order to be able to dynamically build an html string, i.e. mixing strings and other variables?
For example, using PHP, the following trivial example demonstrates generating an HTML doc containing a table
<?php
$output = '<html><head><title>Getting worked up over Python indentations</title></head><body>';
output .= '<table><tbody>'
for($i=0; $i< 10; $i++){
output .= '<tr class="'.(($i%2) ? 'even' : 'odd').'"><td>Row: '.$i;
}
$output .= '</tbody></table></body></html>'
echo $output;
I am trying to do something similar in Python (in my views.py), and I get errors like:
EOL while scanning string literal (views.py, line 21)
When I put everything in a single line, it gets rid of the error.
Could someone show how the little php script above will be written in python?, so I can use that as a template to fix my view.
[Edit]
My python code looks something like this:
def just_frigging_doit(request):
html = '<html>
<head><title>What the funk<title></head>
<body>'
# try to start builing dynamic HTML from this point onward...
# but server barfs even further up, on the html var declaration line.
[Edit2]
I have added triple quotes like suggested by Ned and S.Lott, and that works fine if I want to print out static text. If I want to create dynamic html (for example a row number), I get an exception - cannot concatenate 'str' and 'int' objects.
I am trying to generate my html dynamically, so that means a lot of string manipulation.
Don't do this.
Use Django's templates. They work really, really well. If you can't figure out how to apply them, do this. Ask a question showing what you want to do. Don't ask how to make dynamic HTML. Ask about how to create whatever page feature you're trying to create. 80% of the time, a simple {%if%} or {%for%} does everything you need. The rest of the time you need to know how filters and the built-in tags work.
Use string.Template if you must fall back to "dynamic" HTML. http://docs.python.org/library/string.html#template-strings Once you try this, you'll find Django's is better.
Do not do string manipulation to create HTML.
cannot concatenate 'str' and 'int' objects.
Correct. You cannot.
You have three choices.
Convert the int to a string. Use the str() function. This doesn't scale well. You have lots of ad-hoc conversions and stuff. Unpleasant.
Use the format() method of a string to insert values into the string. This is slightly better than complex string manipulation. After doing this for a while, you figure out why templates are a good idea.
Use a template. You can try string.Template. After a while, you figure out why Django's are a good idea.
my_template.html
<html><head><title>Getting worked up over Python indentations</title></head><body>
<table><tbody>
{%for object in objects%}
<tr class="{%cycle 'even' 'odd'%}"><td>Row: {{object}}</td></tr>
{%endfor%}
</tbody></table></body></html>
views.py
def myview( request ):
render_to_response( 'my_template.html',
{ 'objects':range(10) }
)
I think that's all you'd need for a mockup.
In Python, a string can span lines if you use triple-quoting:
"""
This is a
multiline
string
"""
You probably want to use Django templates to create your HTML. Read a Django tutorial to see how it's done.
Python is strongly typed, meaning it won't automatically convert types for you to make your expressions work out, the way PHP will. So you can't concatenate strings and numbers like this: "hello" + num.

Categories

Resources