Changeset 9
- Timestamp:
- 08/27/06 23:58:29 (4 years ago)
- Files:
-
- Extensions/XL8External.py (modified) (1 diff)
- Extensions/xl8_translation_workflow.py (modified) (4 diffs)
- Extensions/xl8_translation_workflow_scripts.py (modified) (2 diffs)
- content/TranslationDoc.py (modified) (11 diffs)
- content/value.py (deleted)
- i18n/generated.pot (modified) (1 diff)
- skins/PloneXL8/document_byline_xl8.pt (added)
- skins/PloneXL8/dtc_view.pt (modified) (9 diffs)
- skins/PloneXL8/formatDueDate.py (added)
- skins/PloneXL8/getQueryString.py (modified) (3 diffs)
- skins/PloneXL8/getTransOwner.py (modified) (2 diffs)
- skins/PloneXL8/plone_xl8.css (modified) (1 diff)
- skins/PloneXL8/test.py (modified) (1 diff)
- skins/PloneXL8/test2.py (modified) (1 diff)
- skins/PloneXL8/translate_item.cpt (modified) (1 diff)
- skins/PloneXL8/translationdoc_view.pt (added)
- skins/PloneXL8/translationdoc_view.pt.metadata (added)
- skins/PloneXL8/urgency1.gif (added)
- skins/PloneXL8/urgency2.gif (added)
- skins/PloneXL8/urgency3.gif (added)
- tests/testTranslationDoc.py (modified) (3 diffs)
- version.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
Extensions/XL8External.py
r7 r9 1 1 from Products.CMFCore.utils import getToolByName 2 2 from DateTime import DateTime 3 3 4 4 def changeTransOwner(self): Extensions/xl8_translation_workflow.py
r6 r9 49 49 50 50 51 for s in ['to_do', 'in_progress', 'proofread', 'complete', 'source' ]:51 for s in ['to_do', 'in_progress', 'proofread', 'complete', 'source', 'archived']: 52 52 workflow.states.addState(s) 53 53 54 for t in ['re ject', 'retract', 'submit_original', 'begin_work', 'approve', 'submit']:54 for t in ['revert', 'reject', 'retract', 'submit_original', 'begin_work', 'approve', 'archive', 'submit']: 55 55 workflow.transitions.addTransition(t) 56 56 … … 87 87 stateDef = workflow.states['in_progress'] 88 88 stateDef.setProperties(title="""In Progress""", 89 transitions=['submit' ])89 transitions=['submit', 'revert']) 90 90 stateDef.setPermission('Modify portal content', 91 91 0, … … 108 108 stateDef = workflow.states['source'] 109 109 stateDef.setProperties(title="""Source""", 110 transitions=['archive']) 111 stateDef.setPermission('Modify portal content', 112 0, 113 ['Member', 'Manager', 'Reviewer']) 114 115 stateDef = workflow.states['archived'] 116 stateDef.setProperties(title="""Archived""", 110 117 transitions=[]) 111 stateDef.setPermission('Modify portal content',112 0,113 ['Member', 'Manager', 'Reviewer'])114 118 115 119 ## Transitions initialization 120 121 transitionDef = workflow.transitions['revert'] 122 transitionDef.setProperties(title="""Revert to To Do""", 123 new_state_id="""to_do""", 124 trigger_type=1, 125 script_name="""""", 126 after_script_name="""""", 127 actbox_name="""Revert to To Do""", 128 actbox_url="""""", 129 actbox_category="""workflow""", 130 props={'guard_roles': 'Manager;Owner'}, 131 ) 116 132 117 133 ## Creation of workflow scripts … … 207 223 ) 208 224 225 transitionDef = workflow.transitions['archive'] 226 transitionDef.setProperties(title="""Archive""", 227 new_state_id="""archived""", 228 trigger_type=1, 229 script_name="""""", 230 after_script_name="""""", 231 actbox_name="""Archive""", 232 actbox_url="""""", 233 actbox_category="""workflow""", 234 props={'guard_expr': 'here/areTranslationsComplete', 'guard_roles': 'Manager;Owner'}, 235 ) 236 237 ## Creation of workflow scripts 238 for wf_scriptname in ['sendReadyForProof']: 239 if not wf_scriptname in workflow.scripts.objectIds(): 240 workflow.scripts._setObject(wf_scriptname, 241 ExternalMethod(wf_scriptname, wf_scriptname, 242 productname + '.xl8_translation_workflow_scripts', 243 wf_scriptname)) 244 209 245 transitionDef = workflow.transitions['submit'] 210 246 transitionDef.setProperties(title="""Submit for Proofreading""", 211 247 new_state_id="""proofread""", 212 248 trigger_type=1, 213 script_name=""" """,249 script_name="""sendReadyForProof""", 214 250 after_script_name="""""", 215 251 actbox_name="""Submit for Proofreading""", Extensions/xl8_translation_workflow_scripts.py
r6 r9 33 33 from Products.LinguaPlone.I18NBaseObject import AlreadyTranslated 34 34 from DateTime import DateTime 35 from Products.CMFPlone.utils import log_exc 35 36 ##/code-section workflow-script-header 36 37 37 38 38 39 def sendRejectionMail(self,state_change,**kw): 39 pass 40 """ 41 inform the person who submitted the translation for completion 42 that the translation has been rejected 43 """ 44 45 member_tool = getToolByName(self, 'portal_membership') 46 47 obj = state_change.object 48 orig = obj.getCanonical() 49 owner=obj.getOwner().getUserName() 50 user=member_tool.getMemberById(owner) 51 address = user.email 52 53 subject= "[BABELS TRANSLATIONS] Rejected: " + orig.Title() + " => " + obj.Language() 54 text="The [" + obj.Language() + "] translation of '" + orig.Title() \ 55 + "' has been rejected. Please review the translation.\n\n" \ 56 + obj.absolute_url() 57 58 obj.sendNotificationMail(address, subject, text) 40 59 41 60 42 61 43 62 def sendCompletionMail(self,state_change,**kw): 44 pass 63 """ 64 Inform the owner of the canonical translation (i.e., source document) 65 that the translation has been completed 66 """ 67 68 member_tool = getToolByName(self, 'portal_membership') 69 70 obj = state_change.object 71 owner=obj.getOwner().getUserName() 72 user=member_tool.getMemberById(owner) 73 74 orig = obj.getCanonical() 75 orig_owner=orig.getOwner().getUserName() 76 orig_user=member_tool.getMemberById(orig_owner) 77 78 address=(orig_user.email, user.email) 79 80 subject= "[BABELS TRANSLATIONS] Approved: " + orig.Title() + " => " + obj.Language() 81 text="The [" + obj.Language() + "] translation of '" + orig.Title() \ 82 + "' has been approved and marked as complete. The translation's owner is: " + user.fullname \ 83 + " (" + user.email + ").\n\n" + obj.absolute_url() 84 85 obj.sendNotificationMail(address, subject, text) 86 87 88 89 def sendReadyForProof(self, state_change, **kw): 90 """ 91 Inform the owner of the original source document that a translation 92 has been submitted for proofreading 93 """ 94 member_tool = getToolByName(self, 'portal_membership') 95 96 obj = state_change.object 97 owner=obj.getOwner().getUserName() 98 user=member_tool.getMemberById(owner) 99 100 orig = obj.getCanonical() 101 orig_owner=orig.getOwner().getUserName() 102 orig_user=member_tool.getMemberById(orig_owner) 103 104 address=orig_user.email 105 106 subject= "[BABELS TRANSLATIONS] Submitted for proofreading: " + orig.Title() + " => " + obj.Language() 107 text="The [" + obj.Language() + "] translation of '" + orig.Title() \ 108 + "' has submitted for proofreading. The translation's owner is " \ 109 + user.fullname + " (" + user.email + ").\n\n" + obj.absolute_url() 110 111 obj.sendNotificationMail(address, subject, text) 45 112 46 113 … … 86 153 now=DateTime() 87 154 obj.getField('translationModTime').set(obj, now) 155 156 content/TranslationDoc.py
r6 r9 42 42 from Products.CMFCore import CMFCorePermissions 43 43 from Products.stripogram import html2text, html2safehtml 44 from Products.ATReferenceBrowserWidget.ATReferenceBrowserWidget import ReferenceBrowserWidget 44 45 45 46 ##code-section module-header #fill in your manual code here … … 85 86 name='requestedLangs', 86 87 widget=MultiSelectionWidget( 88 description="""Selected translations will be generated as "to do" content objects when source document is submitted for translation. Translation langauges requested subsequently will be generated upon save.""", 87 89 label="Requested translations", 88 90 format="checkbox", 89 description="""Selected translations will be generated as "to do" content objects when source document is submitted for translation. Translation langauges requested subsequently will be generated upon save.""",90 91 label_msgid='PloneXL8_label_requestedLangs', 91 description_msgid='PloneXL8_help_requestedLangs',92 92 i18n_domain='PloneXL8', 93 93 ), … … 129 129 enforceVocabulary=True, 130 130 searchable=1, 131 vocabulary=[ 'Normal', 'Urgent', 'Super Urgent'],132 default= 'Normal',131 vocabulary=[(1, 'Normal'), (2, 'Urgent'), (3, 'Super Urgent')], 132 default=1, 133 133 required=True, 134 134 languageIndependent=1 … … 140 140 widget=CalendarWidget( 141 141 label="Translation due date", 142 show_hm=False, 142 143 label_msgid='PloneXL8_label_dueDate', 143 144 i18n_domain='PloneXL8', 144 145 ), 145 146 languageIndependent=1, 146 searchable=1 147 searchable=1, 148 required=True 147 149 ), 148 150 … … 152 154 widget=CalendarWidget( 153 155 label="Translation proofreading due date", 156 show_hm=False, 154 157 label_msgid='PloneXL8_label_proofDueDate', 155 158 i18n_domain='PloneXL8', 156 159 ), 157 160 languageIndependent=1, 158 searchable=1 161 searchable=1, 162 required=True 159 163 ), 160 164 … … 176 180 ), 177 181 178 # Make this default ATCT field disappear. There must be a better179 # way to do this. Do NOT change the 'Visible' field.180 StringField(182 #Use relatedItems field to allow grouping of translation source 183 #documents. 184 ReferenceField( 181 185 name='relatedItems', 182 default=['dummy',], 183 widget=StringWidget( 184 visible=0, 185 label='Relateditems', 186 widget=ReferenceBrowserWidget( 187 label="Related sources", 188 description="If this document is part of a group of documents, you may create a relationship to the other documents here.", 189 allow_search=1, 190 allow_browse=0, 191 base_query={'review_state':'source'}, 186 192 label_msgid='PloneXL8_label_relatedItems', 187 193 i18n_domain='PloneXL8', 188 194 ), 189 languageIndependent=1 195 languageIndependent=1, 196 allowed_types=('TranslationDoc'), 197 multiValued=1, 198 relationship='Rel1' 190 199 ), 191 200 … … 259 268 allow_discussion = False 260 269 #content_icon = 'TranslationDoc.gif' 261 immediate_view = ' document_view'262 default_view = ' document_view'270 immediate_view = 'translationdoc_view' 271 default_view = 'translationdoc_view' 263 272 suppl_views = () 264 273 typeDescription = "A document used in the context of a Translation Center object." … … 292 301 return value 293 302 294 security.declareProtected(CMFCorePermissions.View, 'sendCompletionMail') 295 def sendCompletionMail(self): 296 """ 297 Send an email to involved parties (Source Doc owner?) when 298 workflow stage changes to Complete. 299 """ 300 pass 303 security.declareProtected(CMFCorePermissions.View, 'sendNotificationMail') 304 def sendNotificationMail(self,to,subject,text): 305 """ 306 Send workflow notificaitons to relevant parties--used with 307 workflow scripts. 308 """ 309 portal_url = getToolByName(self, 'portal_url') 310 plone_utils = getToolByName(self, 'plone_utils') 311 portal = portal_url.getPortalObject() 312 mail_host = plone_utils.getMailHost() 313 charset = plone_utils.getSiteEncoding() 314 from_address = portal.getProperty('email_from_address', None) 315 316 if from_address is None: 317 log('Cannot send notification email: email sender address or name not set') 318 return 319 320 try: 321 mail_host.secureSend(message = text, 322 mto = to, 323 mfrom = from_address, 324 subject = subject, 325 charset = charset) 326 327 except: 328 log_exc('Could not send email from %s to %s regarding completion confirm. \ntext is:\n%s\n' % (from_address, to, text,)) 301 329 302 330 security.declareProtected(CMFCorePermissions.View, 'isTranslation') … … 388 416 return langs 389 417 418 security.declareProtected(CMFCorePermissions.View, 'areTranslationsComplete') 419 def areTranslationsComplete(self): 420 """ 421 422 """ 423 urltool = getToolByName(self, 'portal_url') 424 portal = urltool.getPortalObject() 425 workflow = portal.portal_workflow 426 427 translated = self.getTranslationLanguages() 428 src_lang = self.getCanonicalLanguage() 429 ok=False 430 for lang in translated: 431 if lang != src_lang: 432 obj=self.getTranslation(lang) 433 if workflow.getInfoFor(obj, "review_state", "") != "complete": 434 return False 435 else: 436 ok=True 437 if ok: 438 return True 439 390 440 # Manually created methods 391 392 security.declarePublic('getUrgencies')393 def getUrgencies(self):394 """395 396 """397 pass398 441 399 442 def post_validate(self, REQUEST=None, errors=None): … … 407 450 workflow = portal.portal_workflow 408 451 already_translated = self.getTranslationLanguages() 409 if (workflow.getInfoFor(self, "review_state", "") and self.REQUEST.form.has_key("requestedLangs"))== "source":452 if (workflow.getInfoFor(self, "review_state", "")== "source" and self.REQUEST.form.has_key("requestedLangs")): 410 453 # generate the translation content objects for the requested languages 411 454 # ONLY if the document is already in "source" state and the user wants … … 426 469 self.getField('translationModTime').set(self, now) 427 470 428 security.declarePublic('getDocTypes')429 def getDocTypes(self):430 """431 432 """433 pass434 435 471 436 472 def modify_fti(fti): i18n/generated.pot
r7 r9 16 16 "Preferred-Encodings: latin1 utf-8\n" 17 17 "Domain: PloneXL8\n" 18 19 #. Default: "If this is part of a translation broken into multiple parts, you should create a relation to the other parts." 20 #: content/TranslationDoc.py 21 msgid "PloneXL8_help_relatedItems" 22 msgstr "" 18 23 19 24 #. Default: "Selected translations will be generated as "to do" content objects when source documented is submitted for translation. Translation langauges requested subsequentely will be generated upon save." skins/PloneXL8/dtc_view.pt
r7 r9 33 33 <tal:foldercontents define="contentFilter python:here.getQueryString(request.form); 34 34 contentsMethod python:here.getFolderContents; 35 folderContents python:contentsMethod(contentFilter, batch=True, b_size= 10);35 folderContents python:contentsMethod(contentFilter, batch=True, b_size=20); 36 36 batch folderContents; 37 37 tc_languages here/getTCLanguages; … … 40 40 <form name="filter" method="GET"> 41 41 <table> 42 42 43 <tr> 43 <td><input type="radio" name="isDocSource" value="Yes" tal:attributes="checked python:contentFilter['isDocSource']=='Yes'" onclick="clearTranslationArea();" />Source Documents</td> 44 <td colspan=2 bgcolor="#cccccc"><input type="radio" name="isDocSource" value="No" tal:attributes="checked python:contentFilter['isDocSource']=='No'" />Target Translations</td> 45 <td valign="top"> 46 <input type="submit" value="Filter" /> 47 </td> 48 </tr> 49 <tr> 50 <td>Language: 44 <td><input type="radio" name="isDocSource" value="Yes" tal:attributes="checked python:contentFilter['isDocSource']=='Yes'" onclick="clearTranslationArea();" />Source Language 51 45 <select name="Language" multiple="true" size="5" tal:define="sel_source python:here.selectedSourceLangsForSearch(request.form)"> 52 46 <option value="all" tal:attributes="selected python:'all' in sel_source">All</option> … … 55 49 selected python:lang in sel_source" 56 50 tal:content="lang" /> 57 </select> 51 </select><br /> 52 <input type="checkbox" name="includeArchived" value="Yes" tal:attributes="checked python:contentFilter['includeArchived']=='Yes'" />Include archived sources? 58 53 </td> 59 <td valign="top" bgcolor="#cccccc"> Language:54 <td valign="top" bgcolor="#cccccc"><input type="radio" name="isDocSource" value="No" tal:attributes="checked python:contentFilter['isDocSource']=='No'" />Target Language 60 55 <select name="Language2" multiple="true" size="5" onclick="checkTranslationArea();"> 61 56 <option tal:repeat="lang tc_languages" … … 75 70 </select> 76 71 </td> 72 <td valign="top"> 73 <input type="submit" value="Filter" /> 74 </td> 77 75 </tr> 78 76 </table> … … 101 99 Translations 102 100 </th> 103 <th class="nosort"> 104 <tal i18n:translate="listingheader_created">Created</tal> 105 </th> 101 106 102 <th class="nosort"> 107 103 Deadline … … 136 132 item_orig_lang python:here.getOriginalLang(item); 137 133 item_word_count item/getWordCount; 138 item_due item/getDueDate; 139 item_proof_due item/getProofDueDate; 134 item_due item/getDueDate; 135 item_proof_due item/getProofDueDate; 136 item_urgency item/getUrgency; 140 137 "> 141 138 <td width="250"> 142 <span tal:attributes="class item_type_class"> 139 <img tal:attributes="src python:'urgency' + str(item_urgency) + '.gif'; 140 title item_urgency; 141 alt item_urgency" /> 143 142 <a href="#" 144 143 tal:attributes="href string:${item_id}?set_language=${item_lang}" … … 147 146 </a><br /> 148 147 <span tal:omit-tag="" tal:content="python:item_description[:150]"></span> 149 </span>150 151 148 </td> 152 149 … … 172 169 173 170 174 <td tal:content="python:t oLocalizedTime(item_created)">171 <td tal:content="python:test(item_due, here.formatDueDate(item_due), 'Unspecified.')"> 175 172 August 16, 2001 176 173 </td> 177 174 178 <td tal:content="python:test(item_due, toLocalizedTime(item_due), 'Unspecified.')"> 179 August 16, 2001 180 </td> 181 182 <td tal:content="python:test(item_proof_due, toLocalizedTime(item_proof_due), 'Unspecified.')"> 175 <td tal:content="python:test(item_proof_due, here.formatDueDate(item_proof_due), 'Unspecified.')"> 183 176 August 16, 2001 184 177 </td> … … 202 195 </p> 203 196 </metal:empty> 204 197 <p class="discreet"><img src="urgency2.gif" /> = Urgent 198 <img src="urgency3.gif" /> = Super urgent<br /></p> 205 199 <a href="#" 206 200 tal:attributes="href string:rss?${query_string}"> skins/PloneXL8/getQueryString.py
r3 r9 1 1 ##parameters=req 2 2 ##title=Return query string for processing by catalog search 3 4 if not req.has_key("includeArchived"): 5 req["includeArchived"]="" 3 6 4 7 if req.has_key("Language"): … … 19 22 source="Yes" 20 23 lang="all" 21 state="" 24 state=['source','to_do',] 25 if req["includeArchived"]=="Yes": 26 state.append('archived') 22 27 req["Language2"]="" # make sure this key exists, even if no query 23 24 28 25 29 if source=="Yes": 26 30 # don't read the Target language selection-- 27 # TODO: the HTML field should be disabled on Source search28 31 req["Language"]=lang 29 req["review_state"]="" # ignore workflow state for source searches 32 state=['source','to_do',] 33 if req["includeArchived"]=="Yes": 34 state.append('archived') 35 req["review_state"]=state 36 30 37 else: 31 38 # if it's a search for translations, find translations where … … 42 49 43 50 # behind the scenes 44 req["sort_on"]=" Date"51 req["sort_on"]="getUrgency" 45 52 req["sort_order"]="Reverse" 46 53 skins/PloneXL8/getTransOwner.py
r1 r9 1 ##parameters= item1 ##parameters= 2 2 ##title=Return owner name 3 3 … … 6 6 7 7 from Products.CMFCore.utils import getToolByName 8 obj=item.getObject()8 #obj=item.getObject() 9 9 putils = getToolByName(context, 'plone_utils') 10 owner=putils.getOwnerName( obj)10 owner=putils.getOwnerName(context) 11 11 return owner skins/PloneXL8/plone_xl8.css
r7 r9 17 17 } 18 18 19 .xl8 { 20 background-color: #acacac; 21 } 22 19 23 #xl8_lang_current { 20 24 color: #fafafa; 21 25 background-color: #7b9baa; 22 26 } 23 skins/PloneXL8/test.py
r1 r9 5 5 ##bind script=script 6 6 ##bind subpath=traverse_subpath 7 ##parameters= 7 ##parameters=mydate 8 8 ##title= 9 9 ## 10 10 11 from Products.CMFCore.utils import getToolByName 11 from DateTime import gmtime, strftime 12 return mydate 13 #return strftime("%b %d", gmtime(mydate)) 12 14 13 urltool = getToolByName(context, 'portal_url')14 15 portal = urltool.getPortalObject()16 mtool = getToolByName(context, 'portal_membership')17 putils = getToolByName(context, 'plone_utils')18 19 dtc = getattr(portal, 'dtc-4')20 21 doc = getattr(dtc, 'en-cast')22 #docs=dtc.objectValues()23 #for doc in docs:24 doc2=doc.getCanonical()25 print doc2.Title()26 print doc2.CookedBody()27 print doc2.Creator()28 print putils.getOwnerName(doc2);29 30 #doc.edit(text_format='html', text='<div><b>Cambiamos el texto...</b></div>')31 32 #do= dtc.invokeFactory('TranslationDoc', id='blah14', title="blow me")33 #doc = getattr(dtc, 'blah14')34 #doc.edit(title = 'Foo', description='This is a test')35 #doc.setTitle('Foo2')36 #doc.setDescription("fuck off")37 #doc.editMetadata(title='Appointment')38 #doc.editMetadata(description="boo!")39 #doc.editMetadata(language='en')40 #refreshCatalog(self, clear=0)41 42 #max=10043 #i=044 #while i < max:45 #name="doc" + str(i)46 #do= dtc.invokeFactory('TranslationDoc', id=name)47 #doc = getattr(dtc, name)48 #doc.editMetadata(language='en')49 #print name50 #i=i+151 52 print "done"53 return printedskins/PloneXL8/test2.py
r6 r9 5 5 ##bind script=script 6 6 ##bind subpath=traverse_subpath 7 ##parameters= 7 ##parameters=mydate 8 8 ##title= 9 9 ## 10 10 11 from Products.CMFCore.utils import getToolByName 12 urltool = getToolByName(context, 'portal_url') 13 portal = urltool.getPortalObject() 11 from DateTime import DateTime 14 12 15 now = DateTime() 16 other =context.getTranslationModTime() 17 print now 18 print other 19 print now - other 20 print context.isCanonical() 21 print context.portal_workflow.getInfoFor(context, "review_state", "") 22 print "done" 23 return printed 13 if mydate.isCurrentYear: 14 return mydate.strftime("%b %d") 15 else: 16 return mydate.strftime("%b %d, %Y") skins/PloneXL8/translate_item.cpt
r4 r9 126 126 </div> 127 127 <div tal:condition="python:otherfield.getName()=='text'"> 128 <br /><br /> 128 129 <input type="button" name="copy_source" value="Copy Source ->" onclick="copyToTrans();"/> 130 <br /><br /><br /> 129 131 </div> 130 132 </div> tests/testTranslationDoc.py
r6 r9 92 92 93 93 # from class TranslationDoc: 94 def test_send CompletionMail(self):94 def test_sendNotificationMail(self): 95 95 pass 96 96 … … 127 127 # from class TranslationDoc: 128 128 def test_getAllLanguages(self): 129 pass 130 131 # from class TranslationDoc: 132 def test_areTranslationsComplete(self): 129 133 pass 130 134 … … 245 249 self.failUnless('tdoc2' in self.dtc.objectIds()) 246 250 251 def test_sendCompletionMail(self): 252 pass 253 247 254 def test_pophtml(self): 248 255 pass version.txt
r7 r9 1 0. 3.21 0.4.0 build 22
