[Zope3-checkins] CVS: Zope3/src/zope/app/i18n/browser - __init__.py:1.1 configure.zcml:1.1 exportimport.pt:1.1 exportimport.py:1.1 i18n_domain.gif:1.1 synchronize.pt:1.1 synchronize.py:1.1 translate.pt:1.1 translate.py:1.1 translatemessage.pt:1.1

Stephan Richter srichter at cosmos.phy.tufts.edu
Mon Mar 8 18:34:19 EST 2004


Update of /cvs-repository/Zope3/src/zope/app/i18n/browser
In directory cvs.zope.org:/tmp/cvs-serv4661/src/zope/app/i18n/browser

Added Files:
	__init__.py configure.zcml exportimport.pt exportimport.py 
	i18n_domain.gif synchronize.pt synchronize.py translate.pt 
	translate.py translatemessage.pt 
Log Message:


Moved zope.app.browser.services.translation to zope.i18n.browser. Updated the
code to reflect the new API of using utilities.




=== Added File Zope3/src/zope/app/i18n/browser/__init__.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Translation Service Views

$Id: __init__.py,v 1.1 2004/03/08 23:34:18 srichter Exp $
"""
from zope.i18n.interfaces import ITranslationDomain

class BaseView(object):

    __used_for__ = ITranslationDomain

    def getAllLanguages(self):
        """Get all available languages from the Translation Domain."""
        return self.context.getAllLanguages()


=== Added File Zope3/src/zope/app/i18n/browser/configure.zcml ===
<zope:configure 
  xmlns:zope="http://namespaces.zope.org/zope"
  xmlns="http://namespaces.zope.org/browser">

  <pages 
      permission="zope.ManageServices" 
      for="zope.i18n.interfaces.ITranslationDomain"
      class=".translate.Translate">

    <page name="translate.html" template="translate.pt" 
          menu="zmi_views" title="Translate" />
    <page name="translateMessage.html" template="translatemessage.pt" />
    <page name="editMessages.html" attribute="editMessages" />
    <page name="deleteMessages.html" attribute="deleteMessages" />
    <page name="addLanguage.html" attribute="addLanguage" />
    <page name="changeEditLanguages.html" attribute="changeEditLanguages" />
    <page name="deleteLanguages.html" attribute="deleteLanguages" />
    <page name="changeFilter.html" attribute="changeFilter" />

  </pages>


  <pages 
      permission="zope.ManageServices" 
      for="zope.i18n.interfaces.ITranslationDomain"
      class=".exportimport.ExportImport">
    
    <page name="exportImportForm.html" template="exportimport.pt"
          menu="zmi_views" title="Import/Export" />
    <page name="export.html" attribute="exportMessages" />
    <page name="import.html" attribute="importMessages" />

  </pages>


  <pages
      permission="zope.ManageServices" 
      for="zope.i18n.interfaces.ITranslationDomain"
      class=".synchronize.Synchronize">
    
    <page name="synchronizeForm.html" template="synchronize.pt"
          menu="zmi_views" title="Synchronize" />
    <page name="synchronize.html" attribute="synchronize" />
    <page name="synchronizeMessages.html" attribute="synchronizeMessages" />
    <page name="saveSettings.html" attribute="saveSettings" />

  </pages>

  <defaultView
      for="zope.i18n.interfaces.ITranslationDomain"
      name="translate.html"/>

  <!-- Menu entry for "Add Utility" menu -->
  <addMenuItem
      class="zope.app.i18n.translationdomain.TranslationDomain"
      title="Translation Domain"
      description="A Persistent Translation Domain"
      permission="zope.ManageServices"
      />

  <!-- Custom Domain registration screen -->
  <addform
      label="New Translation Domain Registration"
      for="zope.app.i18n.interfaces.ILocalTranslationDomain"
      name="addRegistration.html"
      schema="zope.app.interfaces.services.utility.IUtilityRegistration"
      class="zope.app.browser.services.utility.AddRegistration"
      permission="zope.ManageServices"
      content_factory="zope.app.i18n.translationdomain.DomainRegistration"
      arguments="name interface componentPath"
      set_after_add="status"
      fields="name interface componentPath permission status"
      usage="addingdialog" />

  <icon 
      name="zmi_icon" 
      for="zope.i18n.interfaces.ITranslationDomain"
      file="./i18n_domain.gif" />

</zope:configure>


=== Added File Zope3/src/zope/app/i18n/browser/exportimport.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <title metal:fill-slot="title" i18n:translate="">
    Translation Domain - Translate
  </title>
</head>
<body>
<div metal:fill-slot="body">

  <h3 i18n:translate="">Import and Export Messages</h3>

  <p i18n:translate="">
    Here you can export and import messages from your Translation Domain.
  </p>

  <form action="./" method="post" enctype="multipart/form-data">
    <table cols="2" width="100%" border="0">
      <tr>
        <td width="50%">
          <div class="form-label" i18n:translate="">Select Languages:</div>
          <div>
            <select name="languages:list" size="3" style="width: 80%"
                    multiple="multiple">
              <option value="" 
                      tal:attributes="value language"
                      tal:content="language"
                      tal:repeat="language view/getAllLanguages"></option>
            </select>
          </div>
        </td>
        <td width="50%" valign="top">
          <div class="form-label" i18n:translate="">Import File Name:</div>
          <div>
            <input type="file" name="file" size="20" value="" />
          </div>
          <div>
            <input type="submit" name="@@import.html:method" value="Import" 
                   i18n:attributes="value import-button"/>
            <input type="submit" name="@@export.html:method" value="Export" 
                   i18n:attributes="value export-button"/>
          </div>
        </td>
      </tr>
    </table>
  </form>

</div>
</body>
</html>


=== Added File Zope3/src/zope/app/i18n/browser/exportimport.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Message Export/Import View

$Id: exportimport.py,v 1.1 2004/03/08 23:34:18 srichter Exp $
"""
from zope.app.i18n.browser import BaseView
from zope.i18n.interfaces import IMessageExportFilter, IMessageImportFilter

class ExportImport(BaseView):

    def exportMessages(self, languages):
        self.request.response.setHeader('content-type',
                                        'application/x-gettext')
        filter = IMessageExportFilter(self.context)
        return filter.exportMessages(languages)

    def importMessages(self, languages, file):
        filter = IMessageImportFilter(self.context)
        filter.importMessages(languages, file)
        return self.request.response.redirect(self.request.URL[-1])


=== Added File Zope3/src/zope/app/i18n/browser/i18n_domain.gif ===
  <Binary-ish file>

=== Added File Zope3/src/zope/app/i18n/browser/synchronize.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <title metal:fill-slot="title" i18n:translate="">
    Translation Service - Synchronize
  </title>

  <style metal:fill-slot="style_slot" type="text/css">
    <!--
    .state0 {color: green;}
    .state1 {color: yellow;}
    .state2 {color: yellow;}
    .state3 {color:  red;}
    .state4 {color:  red;}
    -->
  </style>

</head>

<body>
<div metal:fill-slot="body">

  <table cols="3" width="100%" border="0" cellspacing="0">
    <form action="./" method="post">
      <tr>
        <td width="40%">
          <div class="form-label" i18n:translate="">Server URL</div>
          <div>
            <input type="text" size="40" name="sync_url" value=""
                   tal:attributes="value view/sync_url" />
          </div>
          <div i18n:translate="">Username</div>
          <div>
            <input type="text" size="40" name="sync_username" value=""
                   tal:attributes="value view/sync_username" />
          </div>
          <div i18n:translate="">Password</div>
          <div>
            <input type="password" size="40" name="sync_password" value=""
                   tal:attributes="value view/sync_password" />
          </div>
        </td>
        <td width="30%">
          <div i18n:translate="">Select Languages:</div>
          <div>
            <select name="sync_languages:list" size="6" style="width: 80%" 
                    multiple="multiple">
              <tal:block repeat="language view/getAllLanguages">
              <option value="" 
                      tal:attributes="value language"
                      tal:content="language"
                      tal:condition="python: language not in
                                     view.sync_languages" ></option>
              <option value="" selected="1"
                      tal:attributes="value language"
                      tal:content="language"
                      tal:condition="python: language in
                                     view.sync_languages" ></option>
              </tal:block>
            </select>
          </div>
        </td>
        <td width="30%">
          <div align="center">
            <div>
              <input type="submit" name="saveSettings.html:method" 
                     value="Save Settings" 
                     i18n:attributes="value save-settings-button" />
            </div><br />
            <div>
              <input type="submit" name="synchronize.html:method" 
                     value="Synchronize"
                     i18n:attributes="value synchronize-button"/>
            </div>
          </div>
        </td>
      </tr>
    </form>
  </table>
  <br />

  <form action="./"
        tal:condition="view/canConnect">
    <table cols="5" width="95%" border="0" cellpadding="2" cellspacing="0" 
           class="listing">
      <tr>
        <th width="16">&nbsp;</th>
        <th width="55%" i18n:translate="">Message Id</th>
        <th width="15%" i18n:translate="">Language</th>
        <th width="20%" i18n:translate="">Status</th>
      </tr>
      <tal:block repeat="message python: view.queryMessages().items()">
        <tr tal:define="number repeat/message/number;
                        oddrow repeat/message/odd"
            tal:attributes="class python: oddrow and 'odd' or 'even'">
          <td width="16">
            <input type="hidden"
                   tal:attributes="name python: 'update-msgid-%i' %number;
                                   value python: message[0][0]" />
            <input type="hidden"
                   tal:attributes="name python: 'update-language-%i' %number;
                                   value python: message[0][1]" />
            <input type="checkbox" name="message_ids:list"
                       tal:attributes="value python: number" />
          </td>
          <td tal:content="python: message[0][0]">Hello World!</td>
          <td tal:content="python: message[0][1]">en</td>
          <td>
            <b tal:content="python: view.getStatus(*message[1])"
               tal:attributes="class python:'state%i' %
                               view.getStatus(message[1][0], message[1][1], 0)"
              >status</b>
          </td>
        </tr>
      </tal:block>
    </table>
    <div>
      <input type="submit" name="@@synchronizeMessages.html:method" 
             value="Update" i18n:attributes="value update-button"/>
    </div>
  </form>

  <p tal:condition="python: not view.canConnect()" i18n:translate="">
    No connection could be made to remote data source.
  </p>

</div>
</body>
</html>


=== Added File Zope3/src/zope/app/i18n/browser/synchronize.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Synchronize with Foreign Translation Services

$Id: synchronize.py,v 1.1 2004/03/08 23:34:18 srichter Exp $
"""
import httplib
import urllib
import xmlrpclib
from base64 import encodestring

from zope.app.i18n.browser import BaseView
from zope.app.i18n import ZopeMessageIDFactory as _

DEFAULT = 'http://localhost:8080/++etc++site/default/zope'

class Synchronize(BaseView):

    messageStatus = [_('Up to Date'), _('New Remote'), _('Out of Date'),
                     _('Newer Local'), _('Does not exist')]

    def __init__(self, context, request):
        super(Synchronize, self).__init__(context, request)

        self.sync_url = self.request.cookies.get(
            'sync_url', DEFAULT)
        self.sync_url = urllib.unquote(self.sync_url)
        self.sync_username = self.request.cookies.get('sync_username', 'admin')
        self.sync_password = self.request.cookies.get('sync_password', 'admin')
        self.sync_languages = filter(None, self.request.cookies.get(
            'sync_languages', '').split(','))


    def _connect(self):
        '''Connect to the remote server via XML-RPC HTTP; return status'''
        # make sure the URL contains the http:// prefix
        if not self.sync_url.startswith('http://'):
            url = 'http://' + self.sync_url
        else:
            url = self.sync_url

        # Now try to connect
        self._connection = xmlrpclib.Server(
            url, transport = BasicAuthTransport(self.sync_username,
                                                self.sync_password))

        # check whether the connection was made and the Master Babel Tower
        # exists
        try:
            self._connection.getAllLanguages()
            return 1
        except:
            self._connection = None
            return 0


    def _disconnect(self):
        '''Disconnect from the sever; return None'''
        if hasattr(self, '_connection') and self._connection is not None:
            self._connection = None


    def _isConnected(self):
        '''Check whether we are currently connected to the server; return
        boolean'''
        if not hasattr(self, '_connection'):
            self._connection = None

        if not self._connection is None and self._connection.getAllLanguages():
            return 1
        else:
            return 0


    def canConnect(self):
        '''Checks whether we can connect using this server and user data;
        return boolean'''
        if self._isConnected():
            return 1
        else:
            try:
                return self._connect()
            except:
                return 0


    def getAllLanguages(self):
        connected = self._isConnected()
        if not connected: connected = self._connect()

        if connected:
            return self._connection.getAllLanguages()
        else:
            return []



    def queryMessages(self):
        connected = self._isConnected()
        if not connected: connected = self._connect()

        if connected:
            fmsgs = self._connection.getMessagesFor(self.sync_languages)
        else:
            fmdgs = []

        return self.context.getMessagesMapping(self.sync_languages,
                                               fmsgs)


    def getStatus(self, fmsg, lmsg, verbose=1):
        state = 0
        if fmsg is None:
            state = 4
        elif lmsg is None:
            state = 1
        elif fmsg['mod_time'] > lmsg['mod_time']:
            state = 2
        elif fmsg['mod_time'] < lmsg['mod_time']:
            state = 3
        elif fmsg['mod_time'] == lmsg['mod_time']:
            state = 0

        if verbose:
            return self.messageStatus[state]
        return state


    def saveSettings(self):
        self.sync_languages = self.request.form.get('sync_languages', [])
        self.request.response.setCookie('sync_languages',
                                             ','.join(self.sync_languages))
        self.request.response.setCookie('sync_url',
                            urllib.quote(self.request['sync_url']).strip())
        self.request.response.setCookie('sync_username',
                                             self.request['sync_username'])
        self.request.response.setCookie('sync_password',
                                             self.request['sync_password'])

        return self.request.response.redirect(self.request.URL[-1]+
                                                   '/@@synchronizeForm.html')


    def synchronize(self):
        mapping = self.queryMessages()
        self.context.synchronize(mapping)
        return self.request.response.redirect(self.request.URL[-1]+
                                                   '/@@synchronizeForm.html')


    def synchronizeMessages(self):
        idents = []
        for id in self.request.form['message_ids']:
            msgid = self.request.form['update-msgid-'+id]
            language = self.request.form['update-language-'+id]
            idents.append((msgid, language))

        mapping = self.queryMessages()
        new_mapping = {}
        for item in mapping.items():
            if item[0] in idents:
                new_mapping[item[0]] = item[1]

        self.context.synchronize(new_mapping)
        return self.request.response.redirect(self.request.URL[-1]+
                                                   '/@@synchronizeForm.html')



class BasicAuthTransport(xmlrpclib.Transport):
    def __init__(self, username=None, password=None, verbose=0):
        self.username=username
        self.password=password
        self.verbose=verbose

    def request(self, host, handler, request_body, verbose=0):
        # issue XML-RPC request

        self.verbose = verbose

        h = httplib.HTTP(host)
        h.putrequest("POST", handler)

        # required by HTTP/1.1
        h.putheader("Host", host)

        # required by XML-RPC
        h.putheader("User-Agent", self.user_agent)
        h.putheader("Content-Type", "text/xml")
        h.putheader("Content-Length", str(len(request_body)))

        # basic auth
        if self.username is not None and self.password is not None:
            h.putheader("AUTHORIZATION", "Basic %s" %
                        encodestring("%s:%s" % (self.username, self.password)
                                     ).replace("\012", ""))
        h.endheaders()

        if request_body:
            h.send(request_body)

        errcode, errmsg, headers = h.getreply()

        if errcode != 200:
            raise xmlrpclib.ProtocolError(host + handler,
                                          errcode, errmsg, headers)

        return self.parse_response(h.getfile())


=== Added File Zope3/src/zope/app/i18n/browser/translate.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <title metal:fill-slot="title" i18n:translate="">
    Translation Domain - Translate
  </title>
</head>

<body>
<div metal:fill-slot="body">
  
  <table cols="3" width="100%" border="0">
    <tr>
      <td width="35%">
        <form action="./" method="post">
          <div class="form-label" i18n:translate="">Select Languages:</div>
          <div>
            <select name="languages:list" size="3" style="width: 80%"
                    multiple="multiple">
              <tal:block repeat="language view/getAllLanguages">
                <option value="" 
                        tal:attributes="value language"
                        tal:content="language"
                        tal:condition="python: language not in
                                       view.getEditLanguages()" ></option>
                <option value="" selected="1"
                        tal:attributes="value language"
                        tal:content="language"
                        tal:condition="python: language in
                                       view.getEditLanguages()" ></option>
              </tal:block>
            </select>
          </div>
          <div>
            <input class="form-element" type="submit" 
                   name="@@changeEditLanguages.html:method" value="Edit"
                   i18n:attributes="value edit-button" />
            <input class="form-element" type="submit" 
                   name="@@deleteLanguages.html:method" value="Delete"
                   i18n:attributes="value delete-button" />
          </div>
        </form>
      </td>
      <td width="35%" align="right" valign="top">
        <form action="." method="post">
          <div class="form-label" i18n:translate="">New Language:</div>
          <div>
            <input type="text" name="language" size="20" value="" />
            <input type="submit" name="@@addLanguage.html:method" value="Add" 
                   i18n:attributes="value add-button" />
          </div>
        </form>
      </td>
      <td width="30%" align="right" valign="top">
        <form action="./" method="post">
          <div class="form-label" 
               i18n:translate="">Filter (% - wildcard):</div>
          <div>
            <input type="text" name="filter" size="25" value=""
                   tal:attributes="value request/filter|default" />
          </div>
          <div>
            <input type="submit" name="@@changeFilter.html:method" 
                   value="Filter" 
                   i18n:attributes="value filter-button"/>
          </div>
        </form>
      </td>
    </tr>
  </table>

  <form action="./" method="post">
    <table width="100%" cellspacing="0" cellpadding="3" border="0" 
           class="listing">
      <tr class="list-header" align="left">
        <th width="16">&nbsp;</th>
        <th i18n:translate="">Message Id</th>
        <th tal:repeat="language python:view.getEditLanguages()"
            tal:content="language">de</th>
      </tr>    
      <tal:block repeat="message python: view.getMessages()">
      <tr tal:define="oddrow repeat/message/odd"
          tal:attributes="class python: oddrow and 'odd' or 'even'">
              <td>
                <input type="hidden"
                 tal:attributes="name python: 'edit-msg_id-%i' %message[1];
                                 value python: message[0]" />
          <input type="checkbox" name="message_ids:list"
                 tal:attributes="value python: message[1]" />
        </td>
        <td tal:content="python: message[0]">
          default
        </td>
        <td tal:repeat="language python:view.getEditLanguages()">
          <textarea cols="20" rows="2"
              tal:attributes="name python: 'edit-%s-%i' %(language, message[1])"
              tal:content="python: view.getTranslation(message[0], 
                                                       language)"></textarea>
        </td>
      </tr>
      </tal:block>
      <tr>
        <th colspan="3"
           tal:attributes="colspan python:len(view.getEditLanguages())+3">
          Add new messages
        </th>
      </tr>
    
      <tal:block repeat="count python: range(5)">
      <tr tal:define="oddrow repeat/count/odd"
          tal:attributes="class python: oddrow and 'odd' or 'even'">
              <td width="16">&nbsp;</td>
              <td>
                <textarea cols="20" rows="2" name=""
                      tal:attributes="name string:new-msg_id-${count}"
                ></textarea> 
              </td>
              <td tal:repeat="language python:view.getEditLanguages()">
                <textarea cols="20" rows="2" name=""
                  tal:attributes="name string:new-${language}-${count}"
                ></textarea> 
              </td>
      </tr>
      </tal:block>
    </table>
    
    <div>
      <input class="form-element" type="submit" 
             name="@@editMessages.html:method" value="Edit Messages"
             i18n:attributes="value" />&nbsp;
      <input class="form-element" type="submit" 
             name="@@deleteMessages.html:method" value="Delete Messages"
             i18n:attributes="value" />
    </div>
  </form>

</div>
</body>
</html>


=== Added File Zope3/src/zope/app/i18n/browser/translate.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Translation GUI

$Id: translate.py,v 1.1 2004/03/08 23:34:18 srichter Exp $
"""
from zope.app.i18n.browser import BaseView

class Translate(BaseView):

    def getMessages(self):
        """Get messages"""
        filter = self.request.get('filter', '%')
        messages = []
        for msg_id in self.context.getMessageIds(filter):
            messages.append((msg_id, len(messages)))

        return messages


    def getTranslation(self, msgid, target_lang):
        return self.context.translate(msgid, target_language=target_lang)


    def getEditLanguages(self):
        '''get the languages that are selected for editing'''
        languages = self.request.cookies.get('edit_languages', '')
        return filter(None, languages.split(','))


    def editMessage(self):
        msg_id = self.request['msg_id']
        for language in self.getEditLanguages():
            msg = self.request['msg_lang_%s' %language]
            if msg != self.context.translate(msg_id,
                                             target_language=language):
                self.context.updateMessage(msg_id, msg, language)
        return self.request.response.redirect(self.request.URL[-1])


    def editMessages(self):
        # Handle new Messages
        for count in range(5):
            msg_id = self.request.get('new-msg_id-%i' %count, '')
            if msg_id:
                for language in self.getEditLanguages():
                    msg = self.request.get('new-%s-%i' %(language, count),
                                           msg_id)
                    self.context.addMessage(msg_id, msg, language)

        # Handle edited Messages
        keys = filter(lambda k: k.startswith('edit-msg_id-'),
                      self.request.keys())
        keys = map(lambda k: k[12:], keys)
        for key in keys:
            msg_id = self.request['edit-msg_id-'+key]
            for language in self.getEditLanguages():
                msg = self.request['edit-%s-%s' %(language, key)]
                if msg != self.context.translate(msg_id,
                                                 target_language=language):
                    self.context.updateMessage(msg_id, msg, language)

        return self.request.response.redirect(self.request.URL[-1])


    def deleteMessages(self, message_ids):
        for id in message_ids:
            msgid = self.request.form['edit-msg_id-%s' %id]
            for language in self.context.getAvailableLanguages():
                # Some we edit a language, but no translation exists...
                try:
                    self.context.deleteMessage(msgid, language)
                except KeyError:
                    pass
        return self.request.response.redirect(self.request.URL[-1])


    def addLanguage(self, language):
        self.context.addLanguage(language)
        return self.request.response.redirect(self.request.URL[-1])


    def changeEditLanguages(self, languages=[]):
        self.request.response.setCookie('edit_languages',
                                        ','.join(languages))
        return self.request.response.redirect(self.request.URL[-1])


    def changeFilter(self):
        filter = self.request.get('filter', '%')
        self.request.response.setCookie('filter', filter)
        return self.request.response.redirect(self.request.URL[-1])


    def deleteLanguages(self, languages):
        for language in languages:
            self.context.deleteLanguage(language)
        return self.request.response.redirect(self.request.URL[-1])


=== Added File Zope3/src/zope/app/i18n/browser/translatemessage.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <title metal:fill-slot="title" i18n:translate="">
    Translation Service - Translate
  </title>
</head>

<body>
<div metal:fill-slot="body">

  <form action="./" method="post">
    <input type="hidden" name="msg_id" value=""
           tal:attributes="value request/msgid" />
    <table>
      <tr>
        <th i18n:translate="">Message Id</th>
        <td tal:content="request/msgid">Message Id of the message.</td>
      </tr>
      <tr tal:repeat="language view/getEditLanguages">
        <th tal:content="language">Language</th>
        <td>
          <textarea cols="80" rows="10" name=""
                    tal:attributes="name string:msg_lang_${language}" 
                    tal:content="python: view.getTranslation( 
                                 request['msgid'], language)"
           >Translation of Message</textarea>
        </td>
      </tr>
    </table>
    <input class="form-element" type="submit" 
           name="@@editMessage.html:method" value="Edit Message"
           i18n:attributes="value" />
  </form>

</div>
</body>
</html>




More information about the Zope3-Checkins mailing list