Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix translation issues. #60

Merged
merged 1 commit into from Oct 8, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/HISTORY.txt
Expand Up @@ -5,7 +5,9 @@ Changelog
1.6.1 (unreleased)
------------------

- Nothing changed yet.
- Fix translation issues by translationg label instead of ids of
states and transitions.
[jone]


1.6.0 (2015-05-21)
Expand Down
4 changes: 2 additions & 2 deletions ftw/lawgiver/generator.py
Expand Up @@ -70,10 +70,10 @@ def get_translations(self, workflow_id, specification):
result = {}

for status in specification.states.values():
result[self._status_id(status)] = status.title
result[status.title] = status.title

for transition in specification.transitions:
result[self._transition_id(transition)] = transition.title
result[transition.title] = transition.title

for customerrole, plonerole in specification.role_mapping.items():
result[self._role_id(plonerole)] = getattr(
Expand Down
61 changes: 55 additions & 6 deletions ftw/lawgiver/i18nbuilder.py
@@ -1,7 +1,10 @@
from ftw.lawgiver.interfaces import IWorkflowGenerator
from ftw.lawgiver.utils import find_egginfo
from ftw.lawgiver.wdl.interfaces import IWorkflowSpecificationParser
from i18ndude.catalog import MessageCatalog
from i18ndude.catalog import POWriter
from operator import attrgetter
from path import Path
from zope.component import getUtility
import os.path

Expand Down Expand Up @@ -83,6 +86,16 @@ def generate_po(self, language_code):

self._update_message_catalog(po_path)

@property
def relative_specification_path(self):
if getattr(self, '_relative_specification_path', None):
return self._relative_specification_path

path = Path(self.specification_path)
project_root = find_egginfo(path.parent).parent
self._relative_specification_path = path.relpath(project_root)
return self._relative_specification_path

def _update_message_catalog(self, catalog_path, is_pot=False):
if not os.path.exists(os.path.dirname(catalog_path)):
os.makedirs(os.path.dirname(catalog_path))
Expand All @@ -95,9 +108,32 @@ def _update_message_catalog(self, catalog_path, is_pot=False):
self.workflow_id, self.specification)

catalog = MessageCatalog(filename=catalog_path)
delete_candidates = filter(
lambda msgid: msgid.startswith('{0}--'.format(self.workflow_id)),
catalog.keys())

def is_delete_candidate(msg):
# Lawgiver used to translate the states and transitions
# by state- / transition-id instead of by label,
# but Plone uses the label.
# We therefore remove all old entries.
if msg.msgid.startswith('{0}--STATUS--'.format(self.workflow_id)):
return True

if msg.msgid.startswith('{0}--TRANSITION--'.format(
self.workflow_id)):
return True

# When our spec-path is in the references of the message,
# we treat the message as delete candiate.
if self.relative_specification_path in msg.references:
# Remove the reference. It will be added again if we
# still need the message.
msg.references.remove(self.relative_specification_path)
return True

return False

delete_candidates = map(attrgetter('msgid'),
filter(is_delete_candidate,
catalog.values()))

for msgid, msgstr in translations.items():
msgid = msgid.decode('utf-8').replace('"', '\\"')
Expand All @@ -107,15 +143,28 @@ def _update_message_catalog(self, catalog_path, is_pot=False):
delete_candidates.remove(msgid)

if msgid in catalog:
catalog[msgid].msgstr = msgstr
msg = catalog[msgid]
msg.msgstr = msgstr
if self.relative_specification_path not in msg.references:
msg.references.append(self.relative_specification_path)

msg.automatic_comments = filter(
lambda text: not text.startswith('Default: '),
msg.automatic_comments)
msg.automatic_comments.append('Default: "{0}"'.format(msgstr))

else:
catalog.add(msgid, msgstr=msgstr)
catalog.add(msgid, msgstr=msgstr,
references=[self.relative_specification_path],
automatic_comments=[
'Default: "{0}"'.format(msgstr)])

if is_pot:
catalog[msgid].msgstr = u''

for msgid in delete_candidates:
del catalog[msgid]
if not catalog[msgid].references:
del catalog[msgid]

with open(catalog_path, 'w+') as catalog_file:
writer = POWriter(catalog_file, catalog)
Expand Down
Expand Up @@ -7,5 +7,11 @@ Role mapping:
Editor role description:
An "Editor" writes articles.

Transitions:
publish (Private => Published)

Status Private:
An editor can view this content.

Status Published:
An editor can view this content.
12 changes: 9 additions & 3 deletions ftw/lawgiver/tests/locales/en/LC_MESSAGES/plone.po
Expand Up @@ -11,6 +11,11 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0\n"
"Preferred-Encodings: utf-8 latin1\n"

#. Default: "Published"
#: ftw/lawgiver/tests/profiles/bar/workflows/wf-bar/specification.txt
msgid "Published"
msgstr "Published"

msgid "local-roles--ROLE--Editor"
msgstr ""

Expand Down Expand Up @@ -77,11 +82,12 @@ msgstr "editor-in-chief"
msgid "submit for publication"
msgstr "submit for publication"

#. Default: "editor"
#: ftw/lawgiver/tests/profiles/bar/workflows/wf-bar/specification.txt
msgid "wf-bar--ROLE--Editor"
msgstr "editor"

#. Default: "System Administrator"
#: ftw/lawgiver/tests/profiles/bar/workflows/wf-bar/specification.txt
msgid "wf-bar--ROLE--Manager"
msgstr "System Administrator"

msgid "wf-bar--STATUS--published"
msgstr "Published"
12 changes: 9 additions & 3 deletions ftw/lawgiver/tests/locales/plone.pot
Expand Up @@ -14,6 +14,11 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0\n"
"Preferred-Encodings: utf-8 latin1\n"

#. Default: "Published"
#: ftw/lawgiver/tests/profiles/bar/workflows/wf-bar/specification.txt
msgid "Published"
msgstr ""

msgid "local-roles--ROLE--Editor"
msgstr ""

Expand Down Expand Up @@ -80,11 +85,12 @@ msgstr ""
msgid "submit for publication"
msgstr ""

#. Default: "editor"
#: ftw/lawgiver/tests/profiles/bar/workflows/wf-bar/specification.txt
msgid "wf-bar--ROLE--Editor"
msgstr ""

#. Default: "System Administrator"
#: ftw/lawgiver/tests/profiles/bar/workflows/wf-bar/specification.txt
msgid "wf-bar--ROLE--Manager"
msgstr ""

msgid "wf-bar--STATUS--published"
msgstr ""
8 changes: 4 additions & 4 deletions ftw/lawgiver/tests/test_generator_unit.py
Expand Up @@ -371,10 +371,10 @@ def test_get_translations(self):

self.maxDiff = None
self.assertEquals(
{'wf--STATUS--private': 'Private',
'wf--STATUS--published': 'Published',
'wf--TRANSITION--publish--private_published': 'publish',
'wf--TRANSITION--retract--published_private': 'retract',
{'Private': 'Private',
'Published': 'Published',
'publish': 'publish',
'retract': 'retract',
'wf--ROLE--Editor': 'employee',
'wf--ROLE--Reviewer': 'boss',
'wf--ROLE-DESCRIPTION--Editor': 'A regular company employee.',
Expand Down
27 changes: 23 additions & 4 deletions ftw/lawgiver/tests/test_i18nbuilder.py
Expand Up @@ -17,18 +17,36 @@


SIMPLE_WORKFLOW_MESSAGES = r'''
#. Default: "Private"
#: ftw/lawgiver/tests/assets/i18nbuilder/profiles/default/workflows/simple_workflow/specification.txt
msgid "Private"
msgstr "Private"

#. Default: "Published"
#: ftw/lawgiver/tests/assets/i18nbuilder/profiles/default/workflows/simple_workflow/specification.txt
msgid "Published"
msgstr "Published"

#. Default: "publish"
#: ftw/lawgiver/tests/assets/i18nbuilder/profiles/default/workflows/simple_workflow/specification.txt
msgid "publish"
msgstr "publish"

#. Default: "editor"
#: ftw/lawgiver/tests/assets/i18nbuilder/profiles/default/workflows/simple_workflow/specification.txt
msgid "simple_workflow--ROLE--Editor"
msgstr "editor"

#. Default: "An \"Editor\" writes articles."
#: ftw/lawgiver/tests/assets/i18nbuilder/profiles/default/workflows/simple_workflow/specification.txt
msgid "simple_workflow--ROLE-DESCRIPTION--Editor"
msgstr "An \"Editor\" writes articles."

msgid "simple_workflow--STATUS--private"
msgstr "Private"
'''.strip()

OLD_SIMPLE_WORKFLOW_MESSAGES = r'''
msgid "simple_workflow--STATUS--no-longer-available"
#. Default: "No Longer Available"
#: ftw/lawgiver/tests/assets/i18nbuilder/profiles/default/workflows/simple_workflow/specification.txt
msgid "No Longer Available"
msgstr "No Longer Available"
'''

Expand Down Expand Up @@ -159,6 +177,7 @@ def test_generate_po_removes_old_messages_of_workflow(self):
po_file.write(OLD_SIMPLE_WORKFLOW_MESSAGES)

I18nBuilder(self.simple_workflow_spec_path).generate_po('en')
I18nBuilder(self.simple_workflow_spec_path).generate_po('en')

self.maxDiff = None
self.assertMultiLineEqual(
Expand Down
12 changes: 6 additions & 6 deletions ftw/lawgiver/tests/test_view_details.py
Expand Up @@ -138,13 +138,13 @@ def test_translations_pot(self, browser):

self.assertMultiLineEqual(
'\n'.join((
'msgid "wf-bar--ROLE--Editor"',
'msgid "Published"',
'msgstr ""',
'',
'msgid "wf-bar--ROLE--Manager"',
'msgid "wf-bar--ROLE--Editor"',
'msgstr ""',
'',
'msgid "wf-bar--STATUS--published"',
'msgid "wf-bar--ROLE--Manager"',
'msgstr ""',
)),
data,
Expand All @@ -157,14 +157,14 @@ def test_translations_po(self, browser):

self.assertMultiLineEqual(
'\n'.join((
'msgid "Published"',
'msgstr "Published"',
'',
'msgid "wf-bar--ROLE--Editor"',
'msgstr "editor"',
'',
'msgid "wf-bar--ROLE--Manager"',
'msgstr "System Administrator"',
'',
'msgid "wf-bar--STATUS--published"',
'msgstr "Published"',
)),
data,
'The default translation content is wrong.')
Expand Down
18 changes: 18 additions & 0 deletions ftw/lawgiver/utils.py
Expand Up @@ -3,6 +3,7 @@
from ftw.lawgiver.interfaces import IWorkflowSpecificationDiscovery
from ftw.lawgiver.wdl.interfaces import IWorkflowSpecificationParser
from ftw.lawgiver.wdl.parser import LowerCaseString
from path import Path
from plone.app.workflow.interfaces import ISharingPageRole
from Products.CMFCore.interfaces import IContentish
from Products.CMFCore.utils import getToolByName
Expand Down Expand Up @@ -183,3 +184,20 @@ def in_development(path):
"""Returns True when the path is in development (source checkout).
"""
return not ('egg' in path or 'site-packages' in path)


def find_egginfo(path):
path = Path(path)
if not path or path == '/':
raise ValueError('WARNING: no *.egg-info directory could be found.')
return None

egginfos = path.dirs('*.egg-info')
if len(egginfos) == 0:
return find_egginfo(path.dirname())

if len(egginfos) > 1:
raise ValueError('WARNING: more than one *.egg-info directory found.')
return None

return egginfos[0]
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -65,6 +65,7 @@
'i18ndude',
'lxml',
'ordereddict',
'path.py',
'plone.app.workflow',
'plone.i18n',
'setuptools',
Expand Down