Skip to content
Browse files

refactorings and started docs

  • Loading branch information...
1 parent e46c331 commit c1b117674913198dbefcb7f4690054106cb976dd @mihneasim committed
View
14 docs/sphinx/Makefile
@@ -3,14 +3,14 @@
# You can set these variables from the command line.
SPHINXOPTS =
-SPHINXBUILD = sphinx-build
+SPHINXBUILD = /home/mihnea/envs/n12/bin/sphinx-build
PAPER =
-BUILDDIR = _build
+BUILDDIR = /home/mihnea/envs/n12/var/docs/naaya.i18n
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) /home/mihnea/envs/n12/src/naaya.i18n/docs/sphinx
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
@@ -72,17 +72,17 @@ qthelp:
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/naayai18n.qhcp"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/naaya-docs.qhcp"
@echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/naayai18n.qhc"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/naaya-docs.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/naayai18n"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/naayai18n"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/naaya-docs"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/naaya-docs"
@echo "# devhelp"
epub:
View
67 docs/sphinx/api/index.rst
@@ -0,0 +1,67 @@
+API Documentation
+=================
+
+Portal i18n
+-----------
+
+**Portal i18n** is the main object used for internationalization operations, used
+for querying the other submodules or getting their address. Most
+of the public API available for restricted access resides here.
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ portal_tool
+
+
+Message Catalog
+---------------
+
+The **Message Catalog** is the main storage for translations. Its API is defined
+by *interfaces.INyCatalog* interface.
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ message_catalog/*
+
+
+Negotiator
+---------------
+
+The **Negotiator** is responsible for selecting a display language for the
+browser. It has some configuration settings which can be tweaked by programmers.
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ negotiator/*
+
+
+Property Manager
+----------------
+
+The **Property Manager** takes care of properly setting and returning localized
+values for objects in database.
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ property_manager/*
+
+
+Import Export Tool
+------------------
+
+The **Import Export Tool** provides input-output action
+for **Message Catalog** data.
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ import_export/*
View
5 docs/sphinx/api/portal_tool.rst
@@ -0,0 +1,5 @@
+:mod:`naaya.i18n.portal_tool`
+==============================
+
+.. automodule:: naaya.i18n.portal_tool
+ :members:
View
19 docs/sphinx/conf.py
@@ -217,3 +217,22 @@
('index', 'naayai18n', u'naaya.i18n Documentation',
[u'Mihnea Simian'], 1)
]
+
+### Custom Naaya related handlers ###
+def skip_zope_related_members(app, what, name, obj, skip, options):
+ """
+ Currently skips security related methods added by ClassSecurityInfo.
+ See http://sphinx.pocoo.org/ext/autodoc.html#event-autodoc-skip-member
+
+ """
+ if skip:
+ # do not "redempt" previously skipped members by autodoc
+ return True
+ elif name.endswith('__roles__'):
+ return True
+ else:
+ return False
+
+def setup(app):
+ app.connect('autodoc-skip-member', skip_zope_related_members)
+
View
14 docs/sphinx/index.rst
@@ -1,17 +1,13 @@
-.. naaya.i18n documentation master file, created by
- sphinx-quickstart on Tue Jun 28 16:08:09 2011.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
naaya.i18n's documentation
======================================
-**naaya.i18n** is a required dependency module for **Naaya** content management system.
- It is responsible for management of localized data and portal i18n related issues.
- This document refers to version |release|.
+**naaya.i18n** is a required dependency module for **Naaya** content management
+system. It is responsible for management of localized data and portal i18n
+related issues. This document refers to version |release|.
Manager's Guide
---------------
-See what you need to know about internationalization if you are a Naaya portal manager.
+See what you need to know about internationalization if you are a Naaya
+portal manager.
.. toctree::
:maxdepth: 2
View
6 docs/sphinx/manager_guide/manage_languages.rst
@@ -17,9 +17,9 @@ Selecting the default language
The *default language* is the language the portal is first displayed in,
when the user either has no localization preferences set or the default
language is within his preferred languages. This is also the default fallback
- language.
+language.
This setting does not influence the default translation for new found strings.
- Each new found message without translation is still considered English,
- since most of the Naaya and Zope products are edited so.
+Each new found message without translation is still considered English,
+since most of the Naaya and Zope products are edited so.
View
15 naaya/i18n/ExternalService.py
@@ -8,7 +8,7 @@
from urllib import urlencode
import re
-DUMMY_TEXT = "'XXXXX'" # google tends to change other wildcards like ${}
+DUMMY_TEXT = "XXXXX" # google tends to change other wildcards like ${}
REQUEST_URI = 'http://translate.google.com/translate_a/t'
def external_translate(message, target_lang):
@@ -21,6 +21,12 @@ def external_translate(message, target_lang):
"""
try:
+ # Replace mappings, if any
+ mappings_pat = re.compile(r'\$\{(.*?)\}')
+ mappings = mappings_pat.findall(message)
+ if mappings is not []:
+ message = mappings_pat.sub(DUMMY_TEXT, message)
+
op = urllib2.build_opener()
op.addheaders = [('User-agent', 'Mozilla/5.0')]
handler = op.open(REQUEST_URI,
@@ -31,16 +37,11 @@ def external_translate(message, target_lang):
jsonize_pat = re.compile(',,')
while jsonize_pat.search(body) is not None:
body = jsonize_pat.sub(r',"",', body)
- # Replace mappings, if any
- mappings_pat = re.compile(r'\$\{(.*?)\}')
- mappings = mappings_pat.findall(body)
- if mappings is not []:
- mappings_pat.sub(DUMMY_TEXT, body)
json_data = json.loads(body)
try:
- translation = json_data[0][0][0]
+ translation = ''.join([ x[0] for x in json_data[0] ])
except KeyError:
# no translation or unexpected response
return ''
View
7 naaya/i18n/NyMessageCatalog.py
@@ -2,7 +2,12 @@
# Python imports
# Zope imports
-from Globals import PersistentMapping
+try:
+ # zope 2.12
+ from Persistence import PersistentMapping
+except ImportError:
+ # zope <= 2.11
+ from Globals import PersistentMapping
from Persistence import Persistent
from zope.interface import implements
View
3 naaya/i18n/TranslationsToolWrapper.py
@@ -15,7 +15,6 @@
from Acquisition import Implicit
# Product imports
-from portal_tool import message_encode, message_decode
from LanguageManagers import NyLanguages
class TranslationsToolWrapper(Implicit):
@@ -41,7 +40,7 @@ def msgEncode(self, message):
Encodes a message in order to be passed as parameter in
the query string.
"""
- return quote(message_encode(message))
+ return quote(self.portal_i18n.message_encode(message))
security.declarePublic('message_encode')
@deprecate(("Portal Translations/message_encode is deprecated, use "
View
2 naaya/i18n/patches.py
@@ -8,11 +8,11 @@
from zope.component import adapts
from zope.publisher.interfaces import IRequest
from ZPublisher.BaseRequest import DefaultPublishTraverse
-import zope.thread
# Naaya imports
from Products.Naaya.interfaces import INySite
+
class NySitePublishTraverse(DefaultPublishTraverse):
adapts(INySite, IRequest)
View
81 naaya/i18n/portal_tool.py
@@ -8,9 +8,17 @@
from OFS.Folder import Folder
from OFS.SimpleItem import SimpleItem
from AccessControl import ClassSecurityInfo
-from Globals import DTMLFile
from ZPublisher import HTTPRequest
-from zope.app.i18n import ZopeMessageFactory as _
+try:
+ # Zope 2.12
+ from zope.i18nmessageid import ZopeMessageFactory as _
+ from App.special_dtml import DTMLFile
+ from App.class_init import InitializeClass
+except ImportError:
+ # Zope <= 2.11
+ from zope.app.i18n import ZopeMessageFactory as _
+ from Globals import DTMLFile
+ from Globals import InitializeClass
from AccessControl.Permissions import view_management_screens
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
@@ -41,28 +49,6 @@ def to_unicode(x):
def filter_sort(x, y):
return cmp(to_unicode(x), to_unicode(y))
-def message_encode(message):
- """Encodes a message to an ASCII string.
-
- To be used in the user interface, to avoid problems with the
- encodings, HTML entities, etc..
- """
- if isinstance(message, unicode):
- encoding = HTTPRequest.default_encoding
- message = message.encode(encoding)
-
- return encodestring(message)
-
-def message_decode(message):
- """Decodes a message from an ASCII string.
-
- To be used in the user interface, to avoid problems with the
- encodings, HTML entities, etc..
- """
- message = decodestring(message)
- encoding = HTTPRequest.default_encoding
- return unicode(message, encoding)
-
def get_url(url, batch_start, batch_size, regex, lang, empty, **kw):
params = []
for key, value in kw.items():
@@ -96,6 +82,15 @@ def manage_addNaayaI18n(self, languages=[('en', 'English')],
class NaayaI18n(Folder):
+ """
+ Naaya instantiates a **NaayaI18n** object insides its root. This object
+ holds the whole internationalization data and operations:
+ - management of languages
+ - negotiation
+ - translating and translation data
+ - management of object property localization
+
+ """
meta_type = METATYPE_NAAYAI18N
icon = 'misc_/portal_i18n/icon.gif'
@@ -270,13 +265,31 @@ def get_translation(self, msg, **kwargs):
### Public general purpose methods
security.declarePublic('message_decode')
def message_decode(self, message):
- """ Decode the encoded message (for url passing) """
- return message_decode(message)
+ """
+ Decodes a message from an ASCII string.
+
+ To be used in the user interface, to avoid problems with the
+ encodings, HTML entities, etc..
+
+ """
+ message = decodestring(message)
+ encoding = HTTPRequest.default_encoding
+ return unicode(message, encoding)
security.declarePublic('message_decode')
def message_encode(self, message):
- """ Decode the encoded message (for url passing) """
- return message_encode(message)
+ """
+ Encodes a message to an ASCII string.
+
+ To be used in the user interface, to avoid problems with the
+ encodings, HTML entities, etc..
+
+ """
+ if isinstance(message, unicode):
+ encoding = HTTPRequest.default_encoding
+ message = message.encode(encoding)
+
+ return encodestring(message)
### Private methods for private views
@@ -379,10 +392,10 @@ def get_namespace(self, REQUEST):
translation = self.get_message_catalog()\
.gettext(message, lang, '')
message = to_unicode(message)
- message_encoded = message_encode(message)
+ message_encoded = self.message_encode(message)
else:
message_encoded = message
- message = message_decode(message_encoded)
+ message = self.message_decode(message_encoded)
#translations = self.get_translations(message)
translation = self.get_message_catalog().gettext(message, lang, '')
message = to_unicode(message)
@@ -395,7 +408,7 @@ def get_namespace(self, REQUEST):
namespace['messages'] = []
for x in messages:
x = to_unicode(x)
- x_encoded = message_encode(x)
+ x_encoded = self.message_encode(x)
url = get_url(
REQUEST.URL, batch_start, batch_size, regex, lang, empty,
msg=x_encoded)
@@ -424,7 +437,7 @@ def manage_editMessage(self, message, language, translation,
"""Modifies a message.
"""
message_encoded = message
- message_key = message_decode(message_encoded)
+ message_key = self.message_decode(message_encoded)
self.get_message_catalog()\
.edit_message(message_key, language, translation)
@@ -439,7 +452,7 @@ def manage_editMessage(self, message, language, translation,
security.declareProtected('Manage messages', 'manage_delMessage')
def manage_delMessage(self, message, REQUEST, RESPONSE):
""" """
- message_key = message_decode(message)
+ message_key = self.message_decode(message)
self.get_message_catalog().del_message(message_key)
url = get_url(REQUEST.URL1 + '/manage_messages',
@@ -546,3 +559,5 @@ def manage_import_tmx(self, file, language, REQUEST, RESPONSE):
security.declareProtected(view_management_screens, 'manage_import_xliff')
def manage_import_xliff(self, file, language, REQUEST, RESPONSE):
raise NotImplementedError("Xliff import is not yet implemented")
+
+InitializeClass(NaayaI18n)
View
40 naaya/i18n/tests/test_translations_tool_wrapper.py
@@ -21,12 +21,12 @@ class _PatchedTranslationsTool(TranslationsTool):
def utToUtf8(self, p_string):
if isinstance(p_string, unicode): return p_string.encode('utf-8')
else: return str(p_string)
-
+
def _wrapper_factory():
""" You can use this to create wrapper or the actual translations tool """
# you can use this bool as a manual switch
actual_tool = False
-
+
if actual_tool:
wrapper = _PatchedTranslationsTool('id', 'title')
wrapper.add_language('de')
@@ -41,13 +41,13 @@ def _wrapper_factory():
catalog.gettext('Unkown', 'en')
wrapper = TranslationsToolWrapper(catalog)
return wrapper
-
+
class TranslationsToolWrapperTest(unittest.TestCase):
-
+
def setUp(self):
self.wrapper = _wrapper_factory()
-
-
+
+
def test_get_msg_translations(self):
self.assertEqual(self.wrapper.get_msg_translations('Administration', ''),
'')
@@ -56,7 +56,7 @@ def test_get_msg_translations(self):
'Administration')
self.assertEqual(self.wrapper.get_msg_translations('Administration', 'de'),
'Verwaltung')
-
+
def test_msgEncodeDecode(self):
self.assertEqual(self.wrapper.message_encode(' 1+'), 'IDEr\n')
self.assertEqual(self.wrapper.msgEncode(' 1+'),
@@ -65,17 +65,17 @@ def test_msgEncodeDecode(self):
self.assertEqual(self.wrapper.message_decode(
self.wrapper.message_encode(' 1+')), ' 1+')
self.assertEqual(self.wrapper.message_decode('IDEr\n'), ' 1+')
-
+
def test_languages_mapping(self):
mapping = self.wrapper.tt_get_languages_mapping()
-
+
self.assertEqual(len(mapping), 1)
self.assertTrue(mapping[0].has_key('code'))
self.assertTrue(mapping[0].has_key('name'))
self.assertTrue(mapping[0].has_key('default'))
self.assertEqual(mapping[0]['code'], 'de')
self.assertEqual(mapping[0]['name'], 'German')
-
+
def test_get_messages(self):
messages = self.wrapper.tt_get_messages('', 'msg', True)
messages_order_de = self.wrapper.tt_get_messages('', 'de', True)
@@ -83,7 +83,7 @@ def test_get_messages(self):
[('Unkown', False), ('Administration', True)])
self.assertEqual(messages_order_de,
[('Administration', True), ('Unkown', False)])
-
+
def test_get_not_translated_messages_count(self):
count = self.wrapper.tt_get_not_translated_messages_count('')
self.assertEqual(count, {'de': 1})
@@ -91,9 +91,9 @@ def test_get_not_translated_messages_count(self):
self.assertEqual(count, {'de': 1})
count = self.wrapper.tt_get_not_translated_messages_count('x')
self.assertEqual(count, False)
-
+
class TranslationsToolWrapperNaayaTest(NaayaTestCase):
-
+
def setUp(self):
# step 1: fix request patch, for Localizer
try:
@@ -103,7 +103,7 @@ def setUp(self):
_requests[get_ident()] = self.portal.REQUEST
except:
pass
-
+
# step 2: add language in site and catalog
self.portal.gl_add_site_language('de')
try:
@@ -111,32 +111,30 @@ def setUp(self):
self.portal.getPortalTranslations().add_language('de')
except:
pass
-
+
# step 3: force negotiation to de, regardless of negotiator
self.portal.REQUEST['EDW_SelectedLanguage'] = {('en', 'de'): 'de'}
self.portal.REQUEST['TraversalRequestNameStack'] = ['de']
-
+
def test_translate(self):
-
-
# add message and translation
self.portal.getPortalTranslations().gettext('${count} dogs', 'en')
try:
self.portal.getPortalTranslations().message_edit('${count} dogs', 'de', '${count} Hunde', '')
except AttributeError:
self.portal.getPortalTranslations().edit_message('${count} dogs', 'de', '${count} Hunde')
-
+
# and test!
in_de = self.portal.getPortalTranslations().trans('${count} dogs',
count='3')
self.assertEqual(in_de, '3 Hunde')
-
+
def test_template_translation(self):
self.tmpl = PageTemplate(id='test_tmpl')
self.tmpl.pt_edit('<p i18n:translate="">Home for'
' <span i18n:name="hours">3</span> hours</p>',
'text/html')
-
+
self.assertEqual(self.tmpl.__of__(self.portal)(),
'<p>Home for <span>3</span> hours</p>')
self.portal.getLocalizer().edit_message('Home for ${hours} hours', 'en',

0 comments on commit c1b1176

Please sign in to comment.
Something went wrong with that request. Please try again.