Commits

Sergey Astanin committed 2f15cca

Accept-Language based i18n. Using plain python dicts instead of gettext for translations.

Comments (0)

Files changed (8)

 import os
 import cgi
 import urllib
+import re
 
 from google.appengine.ext import webapp
 from google.appengine.ext.webapp.util import run_wsgi_app
 
 import markdown
 
-def set_defaults(lang=None):
+import translate
+
+def get_messages(languages=[]):
+	msgs=translate.en
+	for lang in languages:
+		if hasattr(translate,lang):
+			msgs=getattr(translate,lang)
+			logging.debug('languages='+str(languages)+', using '+str(lang))
+			break
+	return msgs
+
+def set_defaults(languages=[]):
 	global default_site_title,default_page_title,default_page_text
-	try:
-		import gettext
-		t=gettext.translation('helloweb','./po',languages=[lang,])
-		_=t.lgettext
-	except:
-		_=lambda x:x
-	default_site_title=unicode(_('Hello Web! | A simple CMS for AppEngine'),"utf8")
-	default_page_title=unicode(_('Hello world!'),"utf8")
-	default_page_text=unicode(_("""**Hello Web!** — A simple minimalistic CMS for flat sites designed for Google AppEngine. Use Markdown to edit pages easily, have menu auto-generated, use the power of Django-compatible templates, host free of charge on AppEngine. And the code is less than 20 kB. 
+	msgs=get_messages(languages)
+	default_site_title=unicode(msgs['default_site_title'],"utf8")
+	default_page_title=unicode(msgs['default_index_title'],"utf8")
+	default_page_text=unicode(msgs['default_index_text'],"utf8")
 
-**Hello Web!** is distributed under the terms of [GNU Affero GPL](http://www.fsf.org/licensing/licenses/agpl-3.0.html)
-
-![Google App Engine](http://code.google.com/appengine/images/appengine-noborder-120x30.gif)"""),"utf8")
-
-def get_messages(lang=None):
-	try:
-		import gettext
-		t=gettext.translation('helloweb','./po',languages=[lang,])
-		_=t.lgettext
-	except:
-		_=lambda x:x
-	m={}
-	m['login']=_('Log in')
-	m['logout']=_('Log out')
-	m['logged_user_status_message']=_('Thank you for logging in')
-	m['logged_editor_status_message']=_('You can edit site pages')
-	m['menu_up']=_('Up')
-	m['menu_down']=_('Down')
-	m['add_page']=_('Add page')
-	m['options']=_('Options')
-	m['submit_page']=_('Submit')
-	m['delete_page']=_('Delete page')
-	m['page_title']=_('Title')
-	m['page_textarea_help']=_('You can use Markdown here')
-	m['page_textarea']=_('Page text')
-	m['newpage_header']=_('Add new page')
-	m['newpage_page_title']=_('Page title')
-	m['newpage_page_url']=_('Page URL (cannot be changed later)')
-	m['newpage_url']=_('URL')
-	m['options_header']=_('Options')
-	m['options_site_title']=_('Site title')
-	m['options_max_pages']=_('Maximum number of pages')
-	m['options_save']=_('Save')
-	m['page_not_found']=_('Page not found.')
-	return m
+def parse_accept_language(accept_language):
+	"Parse Accept-Language header. See RFC2616, sec. 14."
+	ll=[ v.strip().split(';') for v in accept_language.split(',') ]
+	ll=[ len(l)==1 and l.append(1.0) or l for l in ll]
+	ll=[ [l[0],float(re.sub('q\s*=\s*','',str(l[1])))] for l in ll]
+	ll=[ l[0] for l in sorted(ll,lambda l1,l2: l1[1] > l2[1]) ]
+	ll=[ re.sub('-','_',l).lower() for l in ll ]
+	return ll 
 
 default_max_pages=12
 template_dir=os.path.join('themes','simple')
-lang='ru'
 
 TMPL=__import__(template_dir)
 service_pages=['newpage','save','options','save_options',]
 
 class MainPage(webapp.RequestHandler):
 	@staticmethod
-	def create_default_site():
+	def languages(request):
+		al=request.headers.get('Accept-Language')
+		return parse_accept_language(al)
+
+	def create_default_site(self):
 		"""creates a new defaut site, returns SiteData"""
-		set_defaults(lang)
+		set_defaults(MainPage.languages(self.request))
 		p=PageData(url='index',\
 				title=default_page_title,\
 				content=default_page_text)
 		logging.debug('created default site with title: '+s.title)
 		return s
 
-	@staticmethod
-	def create_site_if_not_exists():
+	def create_site_if_not_exists(self):
 		"""creates a new site if not exists, returns SiteData"""
 		if SiteData.all().count() == 0:
-			site=MainPage.create_default_site()
+			site=self.create_default_site()
 			logging.debug('created site with title: '+site.title)
 		else:
 			site=SiteData.get_the_first()
 		return menu
 
 	@staticmethod
-	def get_site_data():
+	def get_site_data(languages):
 		"""returns a dictionary with site data except for the page text"""
 		data={}
 		site=SiteData.get_the_first()
 			data['is_editor']=True
 		if PageData.all().count(site.max_pages) < site.max_pages:
 			data['max_pages_not_reached']=True
-		data['msg']=get_messages(lang)
+		data['msg']=get_messages(languages)
 		return data
 
 	@require_admin
 			self.error(404)
 			t=os.path.join(template_dir, '404.html')
 			self.response.out.write(template.render(t,
-				{'msg':get_messages(lang)}))
+				{'msg':get_messages(MainPage.languages(self.request))}))
 			return
 		p.delete()
 		logging.debug('delete_page: page '+path+' deleted')
 			self.error(404)
 			path=os.path.join(template_dir, '404.html')
 			self.response.out.write(template.render(path,
-				{'msg':get_messages(lang)}))
+				{'msg':get_messages(MainPage.languages(self.request))}))
 			return
 		if 'delete' in self.request.arguments():
 			self.delete_page(path)
 			self.redirect('/')
 			return
 
-		data=self.get_site_data()
+		data=self.get_site_data(MainPage.languages(self.request))
 		data['page']=page
 
 		if path != 'index':
 		if PageData.all().count(s.max_pages) >= s.max_pages:
 			self.redirect('/')
 			return
-		data=MainPage.get_site_data()
+		data=MainPage.get_site_data(MainPage.languages(self.request))
 		data=self.recover_saved(self.request,data)
 		data['max_pages_not_reached']=False # do not show /newpage on /newpage
 		path = os.path.join(os.getcwd(), TMPL.newpage_html)
 	def get(self):
 		data={}
 		s=SiteData.get_the_first()
-		data=MainPage.get_site_data()
+		data=MainPage.get_site_data(MainPage.languages(self.request))
 		data['max_pages']=s.max_pages
 		path = os.path.join(os.getcwd(), TMPL.options_html)
 		self.response.out.write(template.render(path,data))

po/helloweb.po

-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: helloweb 0.2\n"
-"Report-Msgid-Bugs-To: helloweb-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2008-10-01 13:33+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: index.py:41
-msgid "Hello Web! | A simple CMS for AppEngine"
-msgstr ""
-
-#: index.py:42
-msgid "Hello world!"
-msgstr ""
-
-#: index.py:43
-msgid ""
-"**Hello Web!** — A simple minimalistic CMS for flat sites designed for "
-"Google AppEngine. Use Markdown to edit pages easily, have menu auto-"
-"generated, use the power of Django-compatible templates, host free of charge "
-"on AppEngine. And the code is less than 20 kB. \n"
-"\n"
-"**Hello Web!** is distributed under the terms of [GNU Affero GPL](http://www."
-"fsf.org/licensing/licenses/agpl-3.0.html)\n"
-"\n"
-"![Google App Engine](http://code.google.com/appengine/images/appengine-"
-"noborder-120x30.gif)"
-msgstr ""
-
-#: index.py:57
-msgid "Log&nbsp;in"
-msgstr ""
-
-#: index.py:58
-msgid "Log&nbsp;out"
-msgstr ""
-
-#: index.py:59
-msgid "Thank you for logging in"
-msgstr ""
-
-#: index.py:60
-msgid "You can edit site pages"
-msgstr ""
-
-#: index.py:61
-msgid "Up"
-msgstr ""
-
-#: index.py:62
-msgid "Down"
-msgstr ""
-
-#: index.py:63
-msgid "Add page"
-msgstr ""
-
-#: index.py:64 index.py:74
-msgid "Options"
-msgstr ""
-
-#: index.py:65
-msgid "Submit"
-msgstr ""
-
-#: index.py:66
-msgid "Delete page"
-msgstr ""
-
-#: index.py:67
-msgid "Title"
-msgstr ""
-
-#: index.py:68
-msgid "You can use Markdown here"
-msgstr ""
-
-#: index.py:69
-msgid "Page text"
-msgstr ""
-
-#: index.py:70
-msgid "Add new page"
-msgstr ""
-
-#: index.py:71
-msgid "Page title"
-msgstr ""
-
-#: index.py:72
-msgid "Page URL (cannot be changed later)"
-msgstr ""
-
-#: index.py:73
-msgid "URL"
-msgstr ""
-
-#: index.py:75
-msgid "Site title"
-msgstr ""
-
-#: index.py:76
-msgid "Maximum number of pages"
-msgstr ""
-
-#: index.py:77
-msgid "Save"
-msgstr ""
-
-#: index.py:78
-msgid "Page not found."
-msgstr ""

po/ru.po

-# Russian translations for PACKAGE package.
-# Copyright (C) 2008 THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# Сергей <s.astanin@gmail.com>, 2008.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: helloweb 0.2\n"
-"Report-Msgid-Bugs-To: helloweb-devel@lists.sourceforge.net\n"
-"POT-Creation-Date: 2008-10-01 13:33+0200\n"
-"PO-Revision-Date: 2008-10-01 13:40+0100\n"
-"Last-Translator: Sergey Astanin <s.astanin@gmail.com>\n"
-"Language-Team: Russian\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#: index.py:41
-msgid "Hello Web! | A simple CMS for AppEngine"
-msgstr "Hello Web! | Простая CMS для AppEngine"
-
-#: index.py:42
-msgid "Hello world!"
-msgstr "Привет, мир!"
-
-#: index.py:43
-msgid ""
-"**Hello Web!** — A simple minimalistic CMS for flat sites designed for Google AppEngine. Use Markdown to edit pages easily, have menu auto-generated, use the power of Django-compatible templates, host free of charge on AppEngine. And the code is less than 20 kB. \n"
-"\n"
-"**Hello Web!** is distributed under the terms of [GNU Affero GPL](http://www.fsf.org/licensing/licenses/agpl-3.0.html)\n"
-"\n"
-"![Google App Engine](http://code.google.com/appengine/images/appengine-noborder-120x30.gif)"
-msgstr ""
-"**Hello Web!** — очень простая система управления сайтом (CMS). Предназначена для создания «плоских» сайтов на Google AppEngine. Можно использовать Markdown при редактировании страниц, меню сайта обновляется автоматически, шаблоны совместимы с Django, есть бесплатный хостинг на AppEngine. И исходный код менее 20 кБ.\n"
-"\"\"\n"
-"\"\"**Hello Web!** распространяется на условиях [GNU Affero GPL](http://www.fsf.org/licensing/licenses/agpl-3.0.html) (то есть даром).\n"
-"\"\"\n"
-"\"\"![Google App Engine](http://code.google.com/appengine/images/appengine-noborder-120x30.gif)"
-
-#: index.py:57
-msgid "Log&nbsp;in"
-msgstr "войти"
-
-#: index.py:58
-msgid "Log&nbsp;out"
-msgstr "выйти"
-
-#: index.py:59
-msgid "Thank you for logging in"
-msgstr "Спасибо, что представились"
-
-#: index.py:60
-msgid "You can edit site pages"
-msgstr "Вы можете изменять страницы сайта"
-
-#: index.py:61
-msgid "Up"
-msgstr "вверх"
-
-#: index.py:62
-msgid "Down"
-msgstr "вниз"
-
-#: index.py:63
-msgid "Add page"
-msgstr "добавить страницу"
-
-#: index.py:64
-#: index.py:74
-msgid "Options"
-msgstr "настройки"
-
-#: index.py:65
-msgid "Submit"
-msgstr "Изменить"
-
-#: index.py:66
-msgid "Delete page"
-msgstr "удалить&nbsp;страницу"
-
-#: index.py:67
-msgid "Title"
-msgstr "Заголовок страницы"
-
-#: index.py:68
-msgid "You can use Markdown here"
-msgstr "здесь можно использовать разметку Markdown"
-
-#: index.py:69
-msgid "Page text"
-msgstr "Текст страницы"
-
-#: index.py:70
-msgid "Add new page"
-msgstr "Добавить новую страницу"
-
-#: index.py:71
-msgid "Page title"
-msgstr "Заголовок страницы"
-
-#: index.py:72
-msgid "Page URL (cannot be changed later)"
-msgstr "Адрес страницы (потом изменить нельзя)"
-
-#: index.py:73
-msgid "URL"
-msgstr "адрес"
-
-#: index.py:75
-msgid "Site title"
-msgstr "Заголовок сайта"
-
-#: index.py:76
-msgid "Maximum number of pages"
-msgstr "Максимальное количество страниц"
-
-#: index.py:77
-msgid "Save"
-msgstr "Сохранить"
-
-#: index.py:78
-msgid "Page not found."
-msgstr "Страница не найдена"
-

po/ru/LC_MESSAGES/helloweb.mo

Binary file removed.

themes/simple/menu.html

 	<a href="{{i.url}}?up" title="{{msg.menu_up}}" class="editor"
 		>↑</a><a
 		href="{{i.url}}?down" title="{{msg.menu_down}}" class="editor"
-		>↓</a>&nbsp;
+		>↓</a>
 	{% endif %}
 	<a href="{{i.url}}" title="{{i.title}}">{{i.title}}</a>
 	{% endspaceless %}
 	{% endif %}
 	{% if is_editor %}
 	{% if max_pages_not_reached %}
-	<p><a href="newpage" class="editor">[+] {{msg.add_page}}</a></p>
+	<p><a href="newpage" class="editor">[+] {{msg.menu_add_page}}</a></p>
 	{% endif %}
-	<p><a href="options" class="editor">[⚙] {{msg.options}}</a></p>
+	<p><a href="options" class="editor">[⚙] {{msg.menu_options}}</a></p>
 	{% endif %}
 	</div>

themes/simple/newpage.html

 			<input name="title" type="text"
 			label="{{msg.newpage_page_title}}"
 			size="50" value="{{page.title}}"/></div>
-		<div>{{msg.newpage_page_url}}: 
+		<div>{{msg.newpage_url_help}}: 
 			<input name="url" type="text"
 			label="{{msg.newpage_url}}"
 			size="31" value="{{page.url}}"/></div>
 		<div>{{msg.page_textarea}} ({{msg.page_textarea_help}}):<br />
 			<textarea name="content" label="{{msg.page_textarea}}"
 			rows="12" cols="70">{{ page.content }}</textarea></div>
-		<div><input type="submit" value="{{msg.add_page}}"></div>
+		<div><input type="submit" value="{{msg.page_add_page}}"></div>
 		</form>
 		{% endif %}
 		</div>

themes/simple/page.html

 			<textarea name="content"
 				label="{{msg.page_textarea}}" rows="12"
 				cols="70">{{ page.content }}</textarea></div>
-			<div><input type="submit" value="{{msg.submit_page}}">
+			<div><input type="submit" value="{{msg.page_submit}}">
 			{% if delete_url %}
 			<a href="{{delete_url}}" class="delete-url"
-				>[–]&nbsp;{{msg.delete_page}}</a>
+				>[–]&nbsp;{{msg.page_delete}}</a>
 			{% endif %}
 			</div>
 		</form>
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 ts=4 sw=4 :
+
+# gettext is not working on Google AppEngine, hence... :-(
+
+en={}
+ru={}
+
+en['default_site_title']="Hello Web! | A simple CMS for AppEngine"
+ru['default_site_title']="Hello Web! | Простая CMS для AppEngine"
+en['default_index_title']="We are ready"
+ru['default_index_title']="Всё готово"
+en['default_index_text']="Log in and start creating your own site."
+ru['default_index_text']="Войдите и создайте свой новый сайт."
+en['login']="Log&nbsp;in"
+ru['login']="войти"
+en['logout']="Log&nbsp;out"
+ru['logout']="выйти"
+en['logged_user_status_message']="Thank you for logging in"
+ru['logged_user_status_message']="Спасибо, что представились"
+en['logged_editor_status_message']="You can edit site pages"
+ru['logged_editor_status_message']="Вы можете изменять страницы сайта"
+en['menu_up']="Up"
+ru['menu_up']="вверх"
+en['menu_down']="Down"
+ru['menu_down']="вниз"
+en['menu_add_page']="Add page"
+ru['menu_add_page']="добавить страницу"
+en['menu_options']="Options"
+ru['menu_options']="настройки"
+en['page_submit']="Submit"
+ru['page_submit']="Изменить"
+en['page_delete']="Delete page"
+ru['page_delete']="удалить&nbsp;страницу"
+en['page_title']="Title"
+ru['page_title']="Заголовок страницы"
+en['page_textarea_help']="You can use Markdown here"
+ru['page_textarea_help']="здесь можно использовать разметку Markdown"
+en['page_textarea']="Page text"
+ru['page_textarea']="Текст страницы"
+en['page_add_page']="Add new page"
+ru['page_add_page']="Добавить новую страницу"
+en['newpage_page_title']="Page title"
+ru['newpage_page_title']="Заголовок страницы"
+en['newpage_url']="URL"
+ru['newpage_url']="адрес"
+en['newpage_url_help']="Page URL (cannot be changed later)"
+ru['newpage_url_help']="Адрес страницы (потом изменить нельзя)"
+en['options_site_title']="Site title"
+ru['options_site_title']="Заголовок сайта"
+en['options_max_pages']="Maximum number of pages"
+ru['options_max_pages']="Максимальное количество страниц"
+en['options_save']="Save"
+ru['options_save']="Сохранить"
+en['page_not_found']="Page not found."
+ru['page_not_found']="Страница не найдена"
+
+# synonyms
+
+en_gb=en
+en_us=en
+ru_ru=ru