2012-01-09 16 views
5

Tengo un formulario que quiero traducir del inglés a muchos idiomas. Puedo hacerlo con gettext o el almacén de datos y he elegido gettext para el rendimiento, pero también podría usar el almacén de datos para almacenar mis traducciones. Las traducciones reales se almacenan en archivos .po que compilo con poedit a archivos de localización .mo. La vista de la forma es: enter image description here¿Cómo localizar mi wtform?

Las validaciones también se localizan pero esa categoría se debe exigir que no está funcionando: enter image description here

Y el código de fondo es

class MyTextInput(TextInput): 

    def __init__(self, error_class=u'has_errors'): 
     super(MyTextInput, self).__init__() 
     self.error_class = error_class 

    def __call__(self, field, **kwargs): 
     if field.errors: 
      c = kwargs.pop('class', '') or kwargs.pop('class_', '') 
      kwargs['class'] = u'%s %s' % (self.error_class, c) 
     return super(MyTextInput, self).__call__(field, **kwargs) 


class MyPasswordInput(PasswordInput): 

    def __init__(self, error_class=u'has_errors'): 
     super(MyPasswordInput, self).__init__() 
     self.error_class = error_class 

    def __call__(self, field, **kwargs): 
     if field.errors: 
      c = kwargs.pop('class', '') or kwargs.pop('class_', '') 
      kwargs['class'] = u'%s %s' % (self.error_class, c) 
     return super(MyPasswordInput, self).__call__(field, **kwargs) 


class RequiredIf(Required): 

    # a validator which makes a field required if 
    # another field is set and has a truthy value 

    def __init__(
     self, 
     other_field_name, 
     *args, 
     **kwargs 
     ): 

     self.other_field_name = other_field_name 
     super(RequiredIf, self).__init__(*args, **kwargs) 

    def __call__(self, form, field): 
     other_field = form._fields.get(self.other_field_name) 
     if other_field is None: 
      raise Exception('no field named "%s" in form' 
          % self.other_field_name) 
     if other_field.data: 
      logging.info('other_field.data 2' + str(other_field.data)) 
      super(RequiredIf, self).__call__(form, field) 


class MyTextArea(TextArea): 

    def __init__(self, error_class=u'has_errors'): 
     super(MyTextArea, self).__init__() 
     self.error_class = error_class 

    def __call__(self, field, **kwargs): 
     if field.errors: 
      c = kwargs.pop('class', '') or kwargs.pop('class_', '') 
      kwargs['class'] = u'%s %s' % (self.error_class, c) 
     return super(MyTextArea, self).__call__(field, **kwargs) 


from wtforms.widgets import html_params 


class SelectWithDisable(object): 

    """ 
    Renders a select field. 

    If `multiple` is True, then the `size` property should be specified on 
    rendering to make the field useful. 

    The field must provide an `iter_choices()` method which the widget will 
    call on rendering; this method must yield tuples of 
    `(value, label, selected, disabled)`. 
    """ 

    def __init__(self, multiple=False): 
     self.multiple = multiple 

    def __call__(self, field, **kwargs): 
     kwargs.setdefault('id', field.id) 
     if self.multiple: 
      kwargs['multiple'] = 'multiple' 
     html = [u'<select %s>' % html_params(name=field.name, **kwargs)] 
     for (val, label, selected, disabled) in field.iter_choices(): 
      html.append(self.render_option(val, label, selected, 
         disabled)) 
     html.append(u'</select>') 
     return HTMLString(u''.join(html)) 

    @classmethod 
    def render_option(
     cls, 
     value, 
     label, 
     selected, 
     disabled, 
     ): 
     options = {'value': value} 
     if selected: 
      options['selected'] = u'selected' 
     if disabled: 
      options['disabled'] = u'disabled' 
     return HTMLString(u'<option %s>%s</option>' 
          % (html_params(**options), 
          escape(unicode(label)))) 


class SelectFieldWithDisable(SelectField): 

    widget = SelectWithDisable() 

    def iter_choices(self): 
     for (value, label, selected, disabled) in self.choices: 
      yield (value, label, selected, disabled, self.coerce(value) 
        == self.data) 


from wtforms.widgets import html_params, HTMLString 
from cgi import escape 


class MyOption(object): 

    def __call__(self, field, **kwargs): 
     options = dict(kwargs, value=field._value()) 
     if field.checked: 
      options['selected'] = True 

     label = field.label.text 
     render_params = (html_params(**options), escape(unicode(label))) 
     return HTMLString(u'<option %s>%s</option>' % render_params) 


class AdForm(Form): 

    my_choices = [ 
     ('1', _('All categories')), 
     ('disabled', _('VEHICLES')), 
     ('2', _('Cars')), 
     ('3', _('Motorcycles')), 
     ('4', _('Accessories & Parts')), 
     ('disabled', _('PROPERTIES')), 
     ('7', _('Apartments')), 
     ('8', _('Houses')), 
     ('9', _('Commercial properties')), 
     ('10', _('Land')), 
     ('disabled', _('ELECTRONICS')), 
     ('12', _('Mobile phones & Gadgets')), 
     ('13', _('TV/Audio/Video/Cameras')), 
     ('14', _('Computers')), 
     ('disabled', _('HOME & PERSONAL ITEMS')), 
     ('16', _('Home & Garden')), 
     ('17', _('Clothes/Watches/Accessories')), 
     ('18', _('For Children')), 
     ('disabled', _('LEISURE/SPORTS/HOBBIES')), 
     ('20', _('Sports & Outdoors')), 
     ('21', _('Hobby & Collectables')), 
     ('22', _('Music/Movies/Books')), 
     ('23', _('Pets')), 
     ('20', _('BUSINESS TO BUSINESS')), 
     ('24', _('Hobby & Collectables')), 
     ('25', _('Professional/Office equipment')), 
     ('26', _('Business for sale')), 
     ('disabled', _('JOBS & SERVICES')), 
     ('28', _('Jobs')), 
     ('29', _('Services')), 
     ('30', _('Events & Catering')), 
     ('31', _('Others')), 
     ] 
    nouser = HiddenField(_('No user')) #dummy variable to know whether user is logged in 
    name = TextField(_('name'), 
        [validators.Required(message=_('Name is required' 
        ))], widget=MyTextInput()) 
    title = TextField(_('Subject'), 
         [validators.Required(message=_('Subject is required' 
        ))], widget=MyTextInput()) 
    text = TextAreaField(_('Text'), 
         [validators.Required(message=_('Text is required' 
         ))], widget=MyTextArea()) 
    phonenumber = TextField(_('phone'), [validators.Optional()]) 
    phoneview = BooleanField(_('Display phone number on site')) 
    price = TextField(_('Price'), [validators.Regexp('^[0-9]+$', 
         message=_('This is not an integer number, please see the example and try again' 
        )), validators.Optional()], widget=MyTextInput()) 
    password = PasswordField(_('password'), 
          validators=[RequiredIf('nouser', 
          message=_('Password is required'))], 
          widget=MyPasswordInput()) 
    email = TextField(_('Email'), 
         [validators.Required(message=_('Email is required' 
        )), 
         validators.Email(message=_('Your email is invalid' 
        ))], widget=MyTextInput()) 
    category = SelectField(choices=my_choices, option_widget=MyOption()) 

    def validate_name(form, field): 
     if len(field.data) > 50: 
      raise ValidationError(_('Name must be less than 50 characters' 
           )) 

    def validate_email(form, field): 
     if len(field.data) > 60: 
      raise ValidationError(_('Email must be less than 60 characters' 
           )) 

    def validate_price(form, field): 
     if len(field.data) > 8: 
      raise ValidationError(_('Price must be less than 9 integers' 
           )) 

el código de la plantilla correspondiente es :

<div class="labelform"> 
    <label> 
{% trans %}Category{% endtrans %}: 
</label> 
    </div></td><td> 
    <div class="adinput"> 

    <select name="{{ form.category.name }}"> 
    {% for option in form.category %} 
     {% if option.data == 'disabled' %} 
      {{ option(disabled=True) }} 
     {% else %} 
      {{ option }} 
     {% endif %} 
    {% endfor %} 
    </select> 

    <div id="err_category" style="display: none; color: red; font-weight: bold;"> 
     <span class="error" id="err_msg_category"></span> 
    </div> 
    </div> 
    </td></tr><tr><td> 
    <div class="labelform"></div></td><td> 
    <div class="adinput"> 
     <label for="private_ad" id='lprivate_ad'> 
     <input id="private_ad" name="company_ad" value="0" checked="checked" type="radio" /> 
{% trans %}Private{% endtrans %}  
     </label> 
    <label for="company_ad" id='lcompany_ad'> 
     <input id="company_ad" name="company_ad" value="1" type="radio" />  
{% trans %}Company{% endtrans %} 
    </label> 
    </div> 
    </td></tr><tr><td valign="top"> 
    {{ form.name.label }}:</td><td> 
    <div class="adinput"> 
{% if user or current_user %} 
    <input type="text" id="name" name="name" value="{{ current_user.name }}{% if not current_user %}{{ user.nickname() }}{% endif %}" size="35" maxlength="50" readonly/> 
    {% else %} 
    {{ form.name|safe }} 
{% endif %} 
{% if form.name.errors %} <div class="red"> 
     <ul class="errors">{% for error in form.name.errors %}<li>{{ error }}</li>{% endfor %}</ul></div> 
    {% endif %} 
    </div> 
    </td></tr><tr><td valign="top"> 
{{ form.email.label }}:</td><td> 
    <div class="adinput"> 
{% if user.email or current_user.email %} 
<input type="text" id="email" name="email" value="{{ current_user.email }}{% if not current_user %}{{ user.email() }}{% endif %}" size="35" maxlength="60" readonly /> 
    {% else %} 
    {{ form.email|safe }} 
{% endif %}{% if form.email.errors %} <div class="maintext"> 
     <ul class="errors">{% for error in form.email.errors %}<li>{{ error }}</li>{% endfor %}</ul></div> 
    {% endif %} 
    </div> 
    </td></tr><tr><td valign="top">{% if not user and not current_user %} 
{{ form.password.label }}: 
     </td><td> <div class="adinput">{{ form.password|safe }}{% trans %}Choose a password{% endtrans %}</div>{% if form.password.errors %} <div class="maintext"> 
     <ul class="errors">{% for error in form.password.errors %}<li>{{ error }}</li>{% endfor %}</ul></div> 
    {% endif %}{% endif %} 

    </td></tr><tr><td valign="top"> 
    {{ form.phonenumber.label }}: 
    </td><td valign="top"> 
    <div class="adinput"> 
    {{ form.phonenumber(size="17", maxlength="14")|safe }}{% trans %}Use areacode{% endtrans %}<br> 
    {{ form.phoneview|safe }} 
    <label for="phone_hidden">{% trans %}View on site{% endtrans %}</label><br /> 
    {{mareacode}}. 
    <div id="err_phone" style="display: none;"> 
     <span class="warning" id="err_msg_phone"></span> 
    </div> 
    </div></td></tr><tr><td valign="top"> 
    <div class="labelform"> 
{% filter capitalize %}{% trans %}content type{% endtrans %}{% endfilter %}:</div></td><td> 
    <div class="adinput" id="dtype"> 
    <label style="cursor:pointer;" for="type_s" id="ltype_s"> 
     <input type="radio" name="type" id="type_s" value="s" checked="checked" /> 
{% trans %}For sale{% endtrans %} 
    </label> 
     <label style="cursor:pointer;" for="type_k" id="ltype_k"> 
     <input type="radio" name="type" id="type_w" value="w" />{% trans %}Wanted{% endtrans %} 
    </label> 
      <div id="warn_type" style="display: none;"> 
       <span class="warning" id="err_msg_type"></span> 
      </div> 
     </div> 
</td></tr> 



<!-- 
<tr> 
<th style="display: table-cell;">Reg. Year:</th> 
<td class="param_cell_regdate" style="display: table-cell;"> 
<select id="regdate" name="regdate"> 
<div id="err_regdate" style="display: none"> 
<div class="warning" style="display:none; clear:both; float:none; white-space:nowrap"> </div> 
</td> 
</tr> 
--> 


<tr><td valign="top"> 
{{ form.title.label }}: 
    </td><td> 
{{ form.title(size='47', maxlength='50', placeholder=_('Please use a descriptive title'))}}{% if form.title.errors %} 
     <div class="maintext"> <ul class="errors">{% for error in form.title.errors %}<li>{{ error }}</li>{% endfor %}</ul></div> 
    {% endif %} 
    <br/> 
    </td></tr><tr><td valign="top"> 
{{ form.text.label }}: 
    </td><td colspan="2"> 
    <div class="adinput"> 
    {{form.text(cols="45", rows="10", placeholder=_('Please describe the product or service in a few simple sentences'))|safe}} 
{% if form.text.errors %} <div class="maintext"> 
     <ul class="errors">{% for error in form.text.errors %}<li>{{ error }}</li>{% endfor %}</ul></div> 
    {% endif %} 
    </div></td></tr><tr><td> 
{{ form.price.label }}: 
     </td><td> 
     <div class="adinput" id="dprice" style="display: block;">{% if host == "www.montao.com.br" %}R${% else %} 
</label><select name="currency" class="currencySelect"> 
<option value="EUR" >Euros</option> 
<option value="AUD">{% trans %}Australian{% endtrans %} Dollars</option> 
<option value="BRL" {% if logo == "Montao.com.br" %}selected{% endif %}>{% trans %}Brazilian{% endtrans %} Real</option> 
<option value="GBP">{% trans %}British{% endtrans %} Pounds</option> 
<option value="CAD">{% trans %}Canadian{% endtrans %} Dollars</option> 
<option value="CZK">{% trans %}Czech{% endtrans %} Koruny</option> 
<option value="DKK">{% trans %}Danish{% endtrans %} Kroner</option> 
<option value="HKD">{% trans %}Hong Kong{% endtrans %} Dollars</option> 
<option value="HUF">{% trans %}Hungarian{% endtrans %} Forints</option> 
<option value="INR">{% trans %}Indian{% endtrans %} Rupee</option> 
<option value="ILS">{% trans %}Israeli{% endtrans %} New Shekels</option> 
<option value="JPY">{% trans %}Japanese{% endtrans %} Yen</option> 
<option value="MXN">{% trans %}Mexican{% endtrans %} Pesos</option> 
<option value="NZD">{% trans %}New Zealand{% endtrans %} Dollars</option> 
<option value="NOK">{% trans %}Norwegian{% endtrans %} Kroner</option> 
<option value="PHP">{% trans %}Philippine{% endtrans %} Pesos</option> 
<option value="PLN">{% trans %}Polish{% endtrans %} Zlotych</option> 
<option value="SGD">{% trans %}Singapore{% endtrans %} Dollars</option> 
<option value="SEK">{% trans %}Swedish{% endtrans %} Kronor</option> 
<option value="CHF">{% trans %}Swiss{% endtrans %} Francs</option> 
<option value="TWD">{% trans %}Taiwan{% endtrans %} New Dollars</option> 
<option value="THB">{% trans %}Thai{% endtrans %} Baht</option> 
<option value="USD">U.S. Dollars</option> 
</select>{% endif %}{{ form.price|safe }}{% if logo == "Montao.com.br" %},{% else %}.{% endif %}00 ({% trans %}Optional - do not include period, comma or cents{% endtrans %}) 
{% if form.price.errors %} 
     <ul class="errors">{% for error in form.price.errors %}<li>{{ error }}</li>{% endfor %}</ul> 
    {% endif %} 
    </div> 
    </td></tr><tr><td> 
<div class="labelform"> 
    <label>{% trans %}Post a photo{% endtrans %}</label> 
    </div></td><td> 
    <div class="adinput"> 
    <input type="file" multiple="true" name="file[]" size="35" id="file" />({% filter capitalize %}{% trans %}optional{% endtrans %}{% endfilter %}. {% trans %}Use CTRL on your keyboard to select multiple images.{% endtrans %}) {{resize}} 
    </div> 
    </td></tr><tr><td></td><td><div class="labelform"></div><div class="adinput"> 
<!-- 
{% if not isHuman %} 
{% trans %}You missed the anti-spam test! No problem, please try again:{% endtrans %} 
{% endif %} 
{{capture|safe}} 
--> 
<input type="submit" name="validate" value='{% trans %}Continue{% endtrans %}' /></div></td></tr></table></form> 

La forma en que recibo la entrada de formulario es con HTTP P OST:

 form = AdForm(self.request.params) 
     if form.validate(): 
      ad.title = form.title.data 
      ad.name = form.name.data 
      ad.email = form.email.data 
      ad.phoneview = form.phoneview.data 
      try: 
       if form.phonenumber.data: 
        ad.phonenumber = form.phonenumber.data 
      except:# to do: change to finally 
       pass 

      ad.text = form.text.data 
      ad.set_password(form.password.data) 
      ad.price = form.price.data.replace(' ', '').replace(',00', 
        '').replace('.00', '') 
      try: 
       if form.price.data: 
        ad.integer_price = form.price.data.replace(' ', '' 
          ).replace(',00', '').replace('.00', '') 
      except: 
       pass 
      ad.url = self.request.host 
      ad.place = self.request.get('place') 
      ad.postaladress = self.request.get('place') 
      ad.put() 
     else: 
      logging.info('form did not validate') 
      self.render_jinja('insert_jinja', 
           facebook_app_id=facebookconf.FACEBOOK_APP_ID, 
           form=form, 
           form_url=blobstore.create_upload_url('/upload_form' 
          )) 
      return 
     if self.request.get('currency'): 
      ad.currency = self.request.get('currency') 
     if self.request.get('cg'): 
      ad.category = self.request.get('cg') # form.cg.data 
     if self.request.get('company_ad') == '1': 
      ad.company_ad = True 
     ad.put() 

     if self.request.host.find('montao') > 0 \ 
      or self.request.host.find('localhost') > 0: 
      path = os.path.join(os.path.dirname(__file__), 'market', 
           'market_ad_preview.html') 
      ad.url = self.request.host 

     for upload in self.get_uploads(): 
      try: 
       img = Image(reference=ad) 
       img.primary_image = upload.key() 
       img.put() 
       ad.put() 
      except: # to do: change to finally 
       pass 
     ad.put() 
     msg = _('Added %s.') % str(self.request.get('title')) 
     message = mail.EmailMessage(sender=self.current_email, 
            subject=(ad.title if ad.title else '' 
            )) 
     if self.request.host != 'www.montao.com.br': 
      message.body = 'Dear ' + ad.name \ 
       + '\nThank you for registering with ' \ 
       + self.request.host \ 
       + '! To edit your ad, click edit from the menu. ' \ 
       + self.request.host + '/vi/' + str(ad.key().id()) \ 
       + '''.html 
We invite you to visit our home page where you can find latest information on new business announcements from us. From there you can also upload and download videos, music and images. 
If you like, you can also add us on Facebook: apps.facebook.com/koolbusiness''' 
      message.to = ad.email 
      message.send() 
     self.redirect('/vi/%d.html' % (ad.key().id(),)) 

¿Por qué no se traducen mis categorías? ¿Cuál es la mejor manera de manejar mis categorías cuando la opción también podría poder deshabilitarse y en esos casos obtener un fondo gris? ¿Puedes ver más formas de mover el renderizado desde HTML codificado y código de plantilla a wtforms?

Gracias de antemano por cualquier respuesta o comentario

Respuesta

1

debe utilizar algún tipo de Lazy gettext en las definiciones de opciones.

Cuestiones relacionadas