Example #1
0
def test_locale_argument_acceptance():
    # Testing None input.
    normalized_locale = localedata.normalize_locale(None)
    assert normalized_locale == None
    locale_exist = localedata.exists(None)
    assert locale_exist == False

    # # Testing list input.
    normalized_locale = localedata.normalize_locale(['en_us', None])
    assert normalized_locale == None
    locale_exist = localedata.exists(['en_us', None])
    assert locale_exist == False
Example #2
0
def get_locale():
  locale = flask.request.cookies.get('locale', config.LOCALE_DEFAULT)
  if locale not in config.LOCALE:
    locale = config.LOCALE_DEFAULT
  if not localedata.exists(locale):
    locale = 'en'
  return locale
Example #3
0
def get_jinja_env(template_loader, locale):
    """
    Set up the Jinja environment, 

    (In the future we may have another system for providing theming;
    for now this is good enough.)
    """
    setup_gettext(locale)

    # If we have a jinja environment set up with this locale, just
    # return that one.
    if SETUP_JINJA_ENVS.has_key(locale):
        return SETUP_JINJA_ENVS[locale]

    template_env = jinja2.Environment(
        loader=template_loader, autoescape=True,
        extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'])

    template_env.install_gettext_callables(
        mg_globals.translations.gettext,
        mg_globals.translations.ngettext)

    # All templates will know how to ...
    # ... fetch all waiting messages and remove them from the queue
    template_env.globals['fetch_messages'] = messages.fetch_messages

    if exists(locale):
        SETUP_JINJA_ENVS[locale] = template_env

    return template_env
Example #4
0
    def __init__(self, language, territory=None, script=None, variant=None):
        """Initialize the locale object from the given identifier components.

        >>> locale = Locale('en', 'US')
        >>> locale.language
        'en'
        >>> locale.territory
        'US'

        :param language: the language code
        :param territory: the territory (country or region) code
        :param script: the script code
        :param variant: the variant code
        :raise `UnknownLocaleError`: if no locale data is available for the
                                     requested locale
        """
        self.language = language
        self.territory = territory
        self.script = script
        self.variant = variant
        self.__data = None

        identifier = str(self)
        if not localedata.exists(identifier):
            raise UnknownLocaleError(identifier)
Example #5
0
def _contextual_locale(context):
    """Return locale from the context, falling back to a default if invalid."""
    request = context.get("request")
    locale = request.LANGUAGE_CODE
    if not localedata.exists(locale):
        locale = settings.LANGUAGE_CODE
    return locale
Example #6
0
 def __init__(self, language, territory = None, script = None, variant = None):
     self.language = language
     self.territory = territory
     self.script = script
     self.variant = variant
     self.__data = None
     identifier = str(self)
     if not localedata.exists(identifier):
         raise UnknownLocaleError(identifier)
Example #7
0
def _format_decimal(num, format=None):
    """Returns the string of a number formatted for the current language.

    Uses django's translation.get_language() to find the current language from
    the request.
    Falls back to the default language if babel does not support the current.

    """
    lang = translation.get_language()
    if not localedata.exists(lang):
        lang = settings.LANGUAGE_CODE
    locale = Locale(translation.to_locale(lang))
    return Format(locale).decimal(num, format)
Example #8
0
def _format_decimal(num, format=None):
    """Returns the string of a number formatted for the current language.

    Uses django's translation.get_language() to find the current language from
    the request.
    Falls back to the default language if babel does not support the current.

    """
    lang = translation.get_language()
    if not localedata.exists(lang):
        lang = settings.LANGUAGE_CODE
    locale = Locale(translation.to_locale(lang))
    return Format(locale).decimal(num, format)
Example #9
0
def get_jinja_env(template_loader, locale):
    """
    Set up the Jinja environment,

    (In the future we may have another system for providing theming;
    for now this is good enough.)
    """
    set_thread_locale(locale)

    # If we have a jinja environment set up with this locale, just
    # return that one.
    if locale in SETUP_JINJA_ENVS:
        return SETUP_JINJA_ENVS[locale]

    # jinja2.StrictUndefined will give exceptions on references
    # to undefined/unknown variables in templates.
    template_env = jinja2.Environment(
        loader=template_loader,
        autoescape=True,
        undefined=jinja2.StrictUndefined,
        extensions=["jinja2.ext.i18n", "jinja2.ext.autoescape", TemplateHookExtension],
    )

    template_env.install_gettext_callables(
        mg_globals.thread_scope.translations.ugettext, mg_globals.thread_scope.translations.ungettext
    )

    # All templates will know how to ...
    # ... fetch all waiting messages and remove them from the queue
    # ... construct a grid of thumbnails or other media
    # ... have access to the global and app config
    template_env.globals["fetch_messages"] = messages.fetch_messages
    template_env.globals["app_config"] = mg_globals.app_config
    template_env.globals["global_config"] = mg_globals.global_config
    template_env.globals["version"] = _version.__version__
    template_env.globals["auth"] = mg_globals.app.auth

    template_env.filters["urlencode"] = url_quote_plus

    # add human readable fuzzy date time
    template_env.globals["timesince"] = timesince

    # allow for hooking up plugin templates
    template_env.globals["get_hook_templates"] = get_hook_templates

    template_env.globals = hook_transform("template_global_context", template_env.globals)

    if exists(locale):
        SETUP_JINJA_ENVS[locale] = template_env

    return template_env
Example #10
0
    def __init__(self):
        from pylons import config

        # Get names of the locales
        # (must be a better way than scanning for i18n directory?)
        known_locales = ['en'] + [locale_name for locale_name in os.listdir(i18n_path) \
                                  if localedata.exists(locale_name)]
        self._locale_names, self._default_locale_name = self._work_out_locales(
            known_locales, config)
        self._locale_objects = map(Locale.parse, self._locale_names)
        self._default_locale_object = Locale.parse(self._default_locale_name)

        self._aliases = LOCALE_ALIASES
        self._aliases['pt'] = 'pt_BR'  # Default Portuguese language to
Example #11
0
    def __init__(self):
        from pylons import config

        # Get names of the locales
        # (must be a better way than scanning for i18n directory?)
        known_locales = ["en"] + [
            locale_name for locale_name in os.listdir(i18n_path) if localedata.exists(locale_name)
        ]
        self._locale_names, self._default_locale_name = self._work_out_locales(known_locales, config)
        self._locale_objects = map(Locale.parse, self._locale_names)
        self._default_locale_object = Locale.parse(self._default_locale_name)

        self._aliases = LOCALE_ALIASES
        self._aliases["pt"] = "pt_BR"  # Default Portuguese language to
Example #12
0
def _get_locales():
    # FIXME this wants cleaning up and merging with get_locales_from_config()
    assert not config.get('lang'), \
        ('"lang" config option not supported - please use ckan.locale_default '
         'instead.')
    locales_offered = config.get('ckan.locales_offered', '').split()
    filtered_out = config.get('ckan.locales_filtered_out', '').split()
    locale_default = config.get('ckan.locale_default', 'en')
    locale_order = config.get('ckan.locale_order', '').split()

    locales = ['en']
    if config.get('ckan.i18n_directory'):
        i18n_path = os.path.join(config.get('ckan.i18n_directory'), 'i18n')
    else:
        i18n_path = os.path.dirname(ckan.i18n.__file__)
    locales += [l for l in os.listdir(i18n_path) if localedata.exists(l)]

    assert locale_default in locales, \
        'default language "%s" not available' % locale_default

    locale_list = []
    for locale in locales:
        # no duplicates
        if locale in locale_list:
            continue
        # if offered locales then check locale is offered
        if locales_offered and locale not in locales_offered:
            continue
        # remove if filtered out
        if locale in filtered_out:
            continue
        # ignore the default as it will be added first
        if locale == locale_default:
            continue
        locale_list.append(locale)
    # order the list if specified
    ordered_list = [locale_default]
    for locale in locale_order:
        if locale in locale_list:
            ordered_list.append(locale)
            # added so remove from our list
            locale_list.remove(locale)
    # add any remaining locales not ordered
    ordered_list += locale_list

    return ordered_list
Example #13
0
File: i18n.py Project: yrchen/ckan
def _get_locales():
    # FIXME this wants cleaning up and merging with get_locales_from_config()
    assert not config.get('lang'), \
        ('"lang" config option not supported - please use ckan.locale_default '
         'instead.')
    locales_offered = config.get('ckan.locales_offered', '').split()
    filtered_out = config.get('ckan.locales_filtered_out', '').split()
    locale_default = config.get('ckan.locale_default', 'en')
    locale_order = config.get('ckan.locale_order', '').split()

    locales = ['en']
    if config.get('ckan.i18n_directory'):
        i18n_path = os.path.join(config.get('ckan.i18n_directory'), 'i18n')
    else:
        i18n_path = os.path.dirname(ckan.i18n.__file__)
    locales += [l for l in os.listdir(i18n_path) if localedata.exists(l)]

    assert locale_default in locales, \
        'default language "%s" not available' % locale_default

    locale_list = []
    for locale in locales:
        # no duplicates
        if locale in locale_list:
            continue
        # if offered locales then check locale is offered
        if locales_offered and locale not in locales_offered:
            continue
        # remove if filtered out
        if locale in filtered_out:
            continue
        # ignore the default as it will be added first
        if locale == locale_default:
            continue
        locale_list.append(locale)
    # order the list if specified
    ordered_list = [locale_default]
    for locale in locale_order:
        if locale in locale_list:
            ordered_list.append(locale)
            # added so remove from our list
            locale_list.remove(locale)
    # add any remaining locales not ordered
    ordered_list += locale_list

    return ordered_list
Example #14
0
def get_gettext_translation(locale):
    """
    Return the gettext instance based on this locale
    """
    # Later on when we have plugins we may want to enable the
    # multi-translations system they have so we can handle plugin
    # translations too

    # TODO: fallback nicely on translations from pt_PT to pt if not
    # available, etc.
    if locale in SETUP_GETTEXTS:
        this_gettext = SETUP_GETTEXTS[locale]
    else:
        this_gettext = gettext.translation(
            'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
        if localedata.exists(locale):
            SETUP_GETTEXTS[locale] = this_gettext
    return this_gettext
Example #15
0
def get_gettext_translation(locale):
    """
    Return the gettext instance based on this locale
    """
    # Later on when we have plugins we may want to enable the
    # multi-translations system they have so we can handle plugin
    # translations too

    # TODO: fallback nicely on translations from pt_PT to pt if not
    # available, etc.
    if locale in SETUP_GETTEXTS:
        this_gettext = SETUP_GETTEXTS[locale]
    else:
        this_gettext = gettext.translation(
            'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
        if localedata.exists(locale):
            SETUP_GETTEXTS[locale] = this_gettext
    return this_gettext
Example #16
0
def setup_gettext(locale):
    """
    Setup the gettext instance based on this locale
    """
    # Later on when we have plugins we may want to enable the
    # multi-translations system they have so we can handle plugin
    # translations too

    # TODO: fallback nicely on translations from pt_PT to pt if not
    # available, etc.
    if SETUP_GETTEXTS.has_key(locale):
        this_gettext = SETUP_GETTEXTS[locale]
    else:
        this_gettext = gettext.translation(
            'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
        if exists(locale):
            SETUP_GETTEXTS[locale] = this_gettext

    mg_globals.setup_globals(
        translations=this_gettext)
Example #17
0
def format_price(value, currency):
    """
    Format decimal value as currency
    """
    try:
        value = Decimal(value)
    except (TypeError, InvalidOperation):
        return ''
    language = get_language()
    if not language:
        language = settings.LANGUAGE_CODE
    locale_code = to_locale(language)
    if not localedata.exists(locale_code):
        localedata.load(locale_code)
    locale = Locale(locale_code)
    currency_format = locale.currency_formats.get('standard')
    pattern = currency_format.pattern
    pattern = re.sub(
        '(\xa4+)', '<span class="currency">\\1</span>', pattern)
    result = format_currency(value, currency, pattern, locale=locale_code)
    return mark_safe(result)
Example #18
0
def datetimeformat(context, value, format='shortdatetime'):
    """
    Returns date/time formatted using babel's locale settings. Uses the
    timezone from settings.py
    """
    if not isinstance(value, datetime.datetime):
        # Expecting date value
        raise ValueError

    tzinfo = timezone(settings.TIME_ZONE)
    tzvalue = tzinfo.localize(value)
    # Babel uses underscore as separator.
    locale = context['request'].locale
    if not localedata.exists(locale):
        locale = settings.LANGUAGE_CODE
    locale = locale.replace('-', '_')

    # If within a day, 24 * 60 * 60 = 86400s
    if format == 'shortdatetime':
        # Check if the date is today
        if value.toordinal() == datetime.date.today().toordinal():
            formatted = _lazy('Today at %s') % format_time(
                                    tzvalue, format='short', locale=locale)
        else:
            formatted = format_datetime(tzvalue, format='short', locale=locale)
    elif format == 'longdatetime':
        formatted = format_datetime(tzvalue, format='long', locale=locale)
    elif format == 'date':
        formatted = format_date(tzvalue, locale=locale)
    elif format == 'time':
        formatted = format_time(tzvalue, locale=locale)
    elif format == 'datetime':
        formatted = format_datetime(tzvalue, locale=locale)
    else:
        # Unknown format
        raise DateTimeFormatError

    return jinja2.Markup('<time datetime="%s">%s</time>' % \
                         (tzvalue.isoformat(), formatted))
Example #19
0
File: api.py Project: dag/stutuz
def entry():
    if not request.args.get('id'):
        return jsonerror("Missing required argument 'id'.", 400)
    if request.args['id'] not in db['entries']:
        return jsonerror('Undefined entry.', 404)
    if 'locale' in request.args and \
       not localedata.exists(request.args['locale']):
        return jsonerror('Invalid locale.', 400)

    entry = db['entries'][request.args['id']]
    data = dict(id=entry.id, type=entry.type)
    if hasattr(entry, 'affixes'):
        data['affixes'] = [affix.encode('utf-8') for affix in entry.affixes]
    if hasattr(entry, 'class_'):
        data['class'] = entry.class_

    locale = request.args.get('locale')
    if entry.history(locale):
        definition = entry.history(locale).newest.object
        data['definition'] = definition.definition
        data['notes'] = definition.notes
    return jsonify(data)
Example #20
0
def get_jinja_env(template_loader, locale):
    """
    Set up the Jinja environment,

    (In the future we may have another system for providing theming;
    for now this is good enough.)
    """
    mg_globals.thread_scope.translations = get_gettext_translation(locale)

    # If we have a jinja environment set up with this locale, just
    # return that one.
    if SETUP_JINJA_ENVS.has_key(locale):
        return SETUP_JINJA_ENVS[locale]

    # jinja2.StrictUndefined will give exceptions on references
    # to undefined/unknown variables in templates.
    template_env = jinja2.Environment(
        loader=template_loader, autoescape=True,
        undefined=jinja2.StrictUndefined,
        extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'])

    template_env.install_gettext_callables(
        mg_globals.thread_scope.translations.ugettext,
        mg_globals.thread_scope.translations.ungettext)

    # All templates will know how to ...
    # ... fetch all waiting messages and remove them from the queue
    # ... construct a grid of thumbnails or other media
    # ... have access to the global and app config
    template_env.globals['fetch_messages'] = messages.fetch_messages
    template_env.globals['app_config'] = mg_globals.app_config
    template_env.globals['global_config'] = mg_globals.global_config

    template_env.filters['urlencode'] = url_quote_plus

    if exists(locale):
        SETUP_JINJA_ENVS[locale] = template_env

    return template_env
Example #21
0
def test_locale_name_cleanup():
    """
    Test that locale identifiers are cleaned up to avoid directory traversal.
    """
    no_exist_name = os.path.join(tempfile.gettempdir(),
                                 "babel%d.dat" % random.randint(1, 99999))
    with open(no_exist_name, "wb") as f:
        pickle.dump({}, f)

    try:
        name = os.path.splitext(
            os.path.relpath(no_exist_name, localedata._dirname))[0]
    except ValueError:
        if sys.platform == "win32":
            pytest.skip("unable to form relpath")
        raise

    assert not localedata.exists(name)
    with pytest.raises(IOError):
        localedata.load(name)
    with pytest.raises(UnknownLocaleError):
        Locale(name)
Example #22
0
    def __init__(self, *args, **kwargs):
        """
        Takes two additional keyword arguments:

        :param cartpos: The cart position the form should be for
        :param event: The event this belongs to
        """
        cartpos = self.cartpos = kwargs.pop('cartpos', None)
        orderpos = self.orderpos = kwargs.pop('orderpos', None)
        pos = cartpos or orderpos
        item = pos.item
        questions = pos.item.questions_to_ask
        event = kwargs.pop('event')
        self.all_optional = kwargs.pop('all_optional', False)

        super().__init__(*args, **kwargs)

        if item.admission and event.settings.attendee_names_asked:
            self.fields['attendee_name_parts'] = NamePartsFormField(
                max_length=255,
                required=event.settings.attendee_names_required,
                scheme=event.settings.name_scheme,
                titles=event.settings.name_scheme_titles,
                label=_('Attendee name'),
                initial=(cartpos.attendee_name_parts
                         if cartpos else orderpos.attendee_name_parts),
            )
        if item.admission and event.settings.attendee_emails_asked:
            self.fields['attendee_email'] = forms.EmailField(
                required=event.settings.attendee_emails_required,
                label=_('Attendee email'),
                initial=(cartpos.attendee_email
                         if cartpos else orderpos.attendee_email),
                widget=forms.EmailInput(attrs={'autocomplete': 'email'}))

        for q in questions:
            # Do we already have an answer? Provide it as the initial value
            answers = [a for a in pos.answerlist if a.question_id == q.id]
            if answers:
                initial = answers[0]
            else:
                initial = None
            tz = pytz.timezone(event.settings.timezone)
            help_text = rich_text(q.help_text)
            label = escape(q.question)  # django-bootstrap3 calls mark_safe
            required = q.required and not self.all_optional
            if q.type == Question.TYPE_BOOLEAN:
                if q.required:
                    # For some reason, django-bootstrap3 does not set the required attribute
                    # itself.
                    widget = forms.CheckboxInput(
                        attrs={'required': 'required'})
                else:
                    widget = forms.CheckboxInput()

                if initial:
                    initialbool = (initial.answer == "True")
                else:
                    initialbool = False

                field = forms.BooleanField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=initialbool,
                    widget=widget,
                )
            elif q.type == Question.TYPE_NUMBER:
                field = forms.DecimalField(
                    label=label,
                    required=required,
                    help_text=q.help_text,
                    initial=initial.answer if initial else None,
                    min_value=Decimal('0.00'),
                )
            elif q.type == Question.TYPE_STRING:
                field = forms.CharField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=initial.answer if initial else None,
                )
            elif q.type == Question.TYPE_TEXT:
                field = forms.CharField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    widget=forms.Textarea,
                    initial=initial.answer if initial else None,
                )
            elif q.type == Question.TYPE_COUNTRYCODE:
                field = CountryField().formfield(
                    label=label,
                    required=required,
                    help_text=help_text,
                    widget=forms.Select,
                    empty_label='',
                    initial=initial.answer if initial else None,
                )
            elif q.type == Question.TYPE_CHOICE:
                field = forms.ModelChoiceField(
                    queryset=q.options,
                    label=label,
                    required=required,
                    help_text=help_text,
                    widget=forms.Select,
                    to_field_name='identifier',
                    empty_label='',
                    initial=initial.options.first() if initial else None,
                )
            elif q.type == Question.TYPE_CHOICE_MULTIPLE:
                field = forms.ModelMultipleChoiceField(
                    queryset=q.options,
                    label=label,
                    required=required,
                    help_text=help_text,
                    to_field_name='identifier',
                    widget=forms.CheckboxSelectMultiple,
                    initial=initial.options.all() if initial else None,
                )
            elif q.type == Question.TYPE_FILE:
                field = forms.FileField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=initial.file if initial else None,
                    widget=UploadedFileWidget(position=pos,
                                              event=event,
                                              answer=initial),
                )
            elif q.type == Question.TYPE_DATE:
                field = forms.DateField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=dateutil.parser.parse(initial.answer).date()
                    if initial and initial.answer else None,
                    widget=DatePickerWidget(),
                )
            elif q.type == Question.TYPE_TIME:
                field = forms.TimeField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=dateutil.parser.parse(initial.answer).time()
                    if initial and initial.answer else None,
                    widget=TimePickerWidget(
                        time_format=get_format_without_seconds(
                            'TIME_INPUT_FORMATS')),
                )
            elif q.type == Question.TYPE_DATETIME:
                field = SplitDateTimeField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=dateutil.parser.parse(
                        initial.answer).astimezone(tz)
                    if initial and initial.answer else None,
                    widget=SplitDateTimePickerWidget(
                        time_format=get_format_without_seconds(
                            'TIME_INPUT_FORMATS')),
                )
            elif q.type == Question.TYPE_PHONENUMBER:
                babel_locale = 'en'
                # Babel, and therefore django-phonenumberfield, do not support our custom locales such das de_Informal
                if localedata.exists(get_language()):
                    babel_locale = get_language()
                elif localedata.exists(get_language()[:2]):
                    babel_locale = get_language()[:2]
                with language(babel_locale):
                    default_country = guess_country(event)
                    default_prefix = None
                    for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
                        if str(default_country) in values:
                            default_prefix = prefix
                    try:
                        initial = PhoneNumber().from_string(
                            initial.answer) if initial else "+{}.".format(
                                default_prefix)
                    except NumberParseException:
                        initial = None
                    field = PhoneNumberField(
                        label=label,
                        required=required,
                        help_text=help_text,
                        # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just
                        # a country code but no number as an initial value. It's a bit hacky, but should be stable for
                        # the future.
                        initial=initial,
                        widget=WrappedPhoneNumberPrefixWidget())
            field.question = q
            if answers:
                # Cache the answer object for later use
                field.answer = answers[0]

            if q.dependency_question_id:
                field.widget.attrs[
                    'data-question-dependency'] = q.dependency_question_id
                field.widget.attrs[
                    'data-question-dependency-values'] = escapejson_attr(
                        json.dumps(q.dependency_values))
                if q.type != 'M':
                    field.widget.attrs[
                        'required'] = q.required and not self.all_optional
                    field._required = q.required and not self.all_optional
                field.required = False

            self.fields['question_%s' % q.id] = field

        responses = question_form_fields.send(sender=event, position=pos)
        data = pos.meta_info_data
        for r, response in sorted(responses, key=lambda r: str(r[0])):
            for key, value in response.items():
                # We need to be this explicit, since OrderedDict.update does not retain ordering
                self.fields[key] = value
                value.initial = data.get('question_form_data', {}).get(key)

        for k, v in self.fields.items():
            if v.widget.attrs.get(
                    'autocomplete') or k == 'attendee_name_parts':
                v.widget.attrs['autocomplete'] = 'section-{} '.format(
                    self.prefix) + v.widget.attrs.get('autocomplete', '')
Example #23
0
def check_locale(locale):
  locale = locale.lower()
  if locale not in config.LOCALE:
    locale = config.LOCALE_DEFAULT
  return locale if localedata.exists(locale) else 'en'
Example #24
0
def get_jinja_env(template_loader, locale):
    """
    Set up the Jinja environment,

    (In the future we may have another system for providing theming;
    for now this is good enough.)
    """
    set_thread_locale(locale)

    # If we have a jinja environment set up with this locale, just
    # return that one.
    if locale in SETUP_JINJA_ENVS:
        return SETUP_JINJA_ENVS[locale]

    # The default config does not require a [jinja2] block.
    # You may create one if you wish to enable additional jinja2 extensions,
    # see example in config_spec.ini
    jinja2_config = mg_globals.global_config.get('jinja2', {})
    local_exts = jinja2_config.get('extensions', [])

    # jinja2.StrictUndefined will give exceptions on references
    # to undefined/unknown variables in templates.
    template_env = jinja2.Environment(
        loader=template_loader,
        autoescape=True,
        undefined=jinja2.StrictUndefined,
        extensions=[
            'jinja2.ext.i18n', 'jinja2.ext.autoescape', TemplateHookExtension
        ] + local_exts)

    template_env.install_gettext_callables(
        mg_globals.thread_scope.translations.ugettext,
        mg_globals.thread_scope.translations.ungettext)

    # All templates will know how to ...
    # ... fetch all waiting messages and remove them from the queue
    # ... construct a grid of thumbnails or other media
    # ... have access to the global and app config
    template_env.globals['fetch_messages'] = messages.fetch_messages
    template_env.globals['app_config'] = mg_globals.app_config
    template_env.globals['global_config'] = mg_globals.global_config
    template_env.globals['version'] = _version.__version__
    template_env.globals['auth'] = mg_globals.app.auth

    template_env.filters['urlencode'] = url_quote_plus

    # add human readable fuzzy date time
    template_env.globals['timesince'] = timesince

    # allow for hooking up plugin templates
    template_env.globals['get_hook_templates'] = get_hook_templates

    template_env.globals = hook_transform('template_global_context',
                                          template_env.globals)

    #### THIS IS TEMPORARY, PLEASE FIX IT
    ## Notifications stuff is not yet a plugin (and we're not sure it will be),
    ## but it needs to add stuff to the context.  This is THE WRONG WAY TO DO IT
    from mediagoblin import notifications
    template_env.globals['get_notifications'] = notifications.get_notifications
    template_env.globals[
        'get_notification_count'] = notifications.get_notification_count
    template_env.globals[
        'get_comment_subscription'] = notifications.get_comment_subscription

    if exists(locale):
        SETUP_JINJA_ENVS[locale] = template_env

    return template_env
Example #25
0
def translate():
    '''
    Edita la traducción a un idioma
    '''
    def fix_values(entry,sample=False):
        '''
        Si la traduccion contiene campos de valores los sustituimos por ______[X] y ponemos un ejemplo de uso,
        además se eliminan los saltos de linea
        '''
        result=re.finditer(r'(%\(([^\)]+)\)([s|d]))', entry.msgstr)
        subs=dict()
        # se cargan los ejemplos si es necesario
        if entry.msgid in samples:
            subs=samples[entry.msgid]

        # para cada valor encontrado se sustituye por _____[X]
        for i,item in enumerate(result):
            entry.msgstr=entry.msgstr.replace(item.group(1),"_____["+str(i+1)+"]")
            # para los ejemplos numericos se utiliza uno aleatorio
            if item.group(3)=="d":
                subs[item.group(2)]=random.randint(2,10)

        if sample:
            if subs!={}:
                return (entry.msgid,(entry.msgstr,_(entry.msgid,**subs)))
            else:
                return (entry.msgid,(entry.msgstr,False))

        # se sustituyen los saltos de linea html y se devuelve todo
        return (entry.msgid,entry.msgstr.replace("<br>","\n").replace("<br />","\n").replace("<br/>","\n") if "<br" in entry.msgstr else entry.msgstr)

    languages = localedata.load(g.lang)["languages"]
    keystrcoll = cmp_to_key(locale.strcoll)
    form = None
    forml = SelectLanguageForm(request.form)
    forml.lang.choices = [("", "-- "+_("choose_language")+" --")] + sorted(
        ((code, localedata.load(code)["languages"][code].capitalize()+" ("+languages[code].capitalize()+")")
            for code, language in languages.items()
            if code in current_app.config["TRANSLATE_LANGS"] and not code in current_app.config["LANGS"] and localedata.exists(code) and code in localedata.load(code)["languages"]),
        key=lambda x: keystrcoll(x[1]))

    total=99999
    no_translation=0
    msgids=[]
    lang_edit = request.args.get("lang")
    if not lang_edit in languages:
        lang_edit = None

    formfields = {}
    # mostrar el idioma a traducir
    if lang_edit is not None:
        forml.lang.default=lang_edit
        # cargar idioma actual
        current_lang = dict(fix_values(entry,True) for entry in polib.pofile(lang_path(g.lang)))

        # si existe el idioma se carga, sino vacio
        lpath = lang_path(lang_edit)
        new_lang = dict(fix_values(entry) for entry in polib.pofile(lpath)) if lpath else {}

        # recorre los ids en ingles y los coge el mensaje del idioma actual y el valor del nuevo
        for i, (msgid, msgstr) in enumerate(fix_values(entry,True) for entry in polib.pofile(lang_path("en"))):
            # se excluyen los textos legales que concluyen con safe_
            if not msgid.startswith(("safe_","admin_")):
                # si no esta traducida la cadena en el idioma actual se deja vacio
                if not msgid in new_lang:
                    no_translation+=1
                    new_lang[msgid]=""

                # si el mensaje esta traducido al idioma actual se usa, sino se usa el ingles
                if msgid in current_lang:
                    msg=current_lang[msgid][0]
                    description=current_lang[msgid][1]
                else:
                    msg=msgstr[0]
                    description=msgstr[1]

                # si la traduccion es mayor de 80 caracteres se utiliza un textarea en vez de un input text
                length=len(new_lang[msgid] or msg)
                if length>80:
                    formfields[msgid]=TextAreaField(msg,default=new_lang[msgid],description=description)
                    # se le establecen las filas al text area dependiendo del tamaño de la traduccion
                    formfields["_args_%s" % msgid]={"rows":length/50}
                else:
                    formfields[msgid]=TextField(msg,default=new_lang[msgid],description=description)
                    formfields["_args_%s" % msgid]={}

                #se añade a la lista que se le envia al formulario
                msgids.append(msgid)

        total=float(len(msgids))
        form=expanded_instance(TranslateForm, formfields, request.form, prefix="translate_")
        # si es el envio de la traducción
        if request.method == 'POST' and form.validate():
            pagesdb.create_translation({"ip":request.remote_addr,"user_lang":g.lang,"dest_lang":lang_edit,"texts":{field.short_name: field.data for field in form if not field.short_name in ("captcha", "submit_form") and field.data!=new_lang[field.short_name]}})
            flash("translation_sent")
            return redirect(url_for('index.home'))

    if lang_edit: forml.lang.data = lang_edit
    # sino se muestra la seleccion de idioma a traducir
    g.title+=_("translate_to_your_language")
    return render_template('pages/translate.html',
        page_title=_("translate_to_your_language"),
        lang=lang_edit,
        forml=forml,
        form=form,
        msgids=msgids,
        complete=round(((total-no_translation)/total)*100,2))
def test_mixedcased_locale():
    for l in localedata.locale_identifiers():
        locale_id = ''.join(
            [methodcaller(random.choice(['lower', 'upper']))(c) for c in l])
        assert localedata.exists(locale_id)
Example #27
0
def test_locale_identification():
    for l in localedata.locale_identifiers():
        assert localedata.exists(l)
Example #28
0
 def init(self):
     """Create .po language file from .pot template, overwrite it if it exists."""
     if not localedata.exists(self.lang):
         # workaround for missing locale in babel package
         localedata._cache[self.lang] = {}
     self._run('init', '-l', self.lang, '-i', self.po_template, '-o', self.po_file)
Example #29
0
File: utils.py Project: Elchi3/kuma
def _get_request_locale(request):
    """Return locale from the request, falling back to a default if invalid."""
    locale = request.LANGUAGE_CODE
    if not localedata.exists(locale):
        locale = settings.LANGUAGE_CODE
    return locale
Example #30
0
def get_jinja_env(app, template_loader, locale):
    """
    Set up the Jinja environment,

    (In the future we may have another system for providing theming;
    for now this is good enough.)
    """
    set_thread_locale(locale)

    # If we have a jinja environment set up with this locale, just
    # return that one.
    if locale in SETUP_JINJA_ENVS:
        return SETUP_JINJA_ENVS[locale]

    # The default config does not require a [jinja2] block.
    # You may create one if you wish to enable additional jinja2 extensions,
    # see example in config_spec.ini 
    jinja2_config = app.global_config.get('jinja2', {})
    local_exts = jinja2_config.get('extensions', [])

    # jinja2.StrictUndefined will give exceptions on references
    # to undefined/unknown variables in templates.
    template_env = jinja2.Environment(
        loader=template_loader, autoescape=True,
        undefined=jinja2.StrictUndefined,
        extensions=[
            'jinja2.ext.i18n', 'jinja2.ext.autoescape',
            TemplateHookExtension] + local_exts)

    if six.PY2:
        template_env.install_gettext_callables(mg_globals.thread_scope.translations.ugettext,
                                           mg_globals.thread_scope.translations.ungettext)
    else:
        template_env.install_gettext_callables(mg_globals.thread_scope.translations.gettext,
                                           mg_globals.thread_scope.translations.ngettext)

    # All templates will know how to ...
    # ... fetch all waiting messages and remove them from the queue
    # ... construct a grid of thumbnails or other media
    # ... have access to the global and app config
    # ... determine if the language is rtl or ltr
    template_env.globals['fetch_messages'] = messages.fetch_messages
    template_env.globals['app_config'] = app.app_config
    template_env.globals['global_config'] = app.global_config
    template_env.globals['version'] = _version.__version__
    template_env.globals['auth'] = app.auth
    template_env.globals['is_rtl'] = is_rtl(locale)
    template_env.filters['urlencode'] = url_quote_plus

    # add human readable fuzzy date time
    template_env.globals['timesince'] = timesince

    # allow for hooking up plugin templates
    template_env.globals['get_hook_templates'] = get_hook_templates

    template_env.globals = hook_transform(
        'template_global_context', template_env.globals)

    #### THIS IS TEMPORARY, PLEASE FIX IT
    ## Notifications stuff is not yet a plugin (and we're not sure it will be),
    ## but it needs to add stuff to the context.  This is THE WRONG WAY TO DO IT
    from mediagoblin import notifications
    template_env.globals['get_notifications'] = notifications.get_notifications
    template_env.globals[
        'get_notification_count'] = notifications.get_notification_count
    template_env.globals[
        'get_comment_subscription'] = notifications.get_comment_subscription

    if exists(locale):
        SETUP_JINJA_ENVS[locale] = template_env

    return template_env
Example #31
0
    def __init__(self, *args, **kwargs):
        """
        Takes two additional keyword arguments:

        :param cartpos: The cart position the form should be for
        :param event: The event this belongs to
        """
        cartpos = self.cartpos = kwargs.pop('cartpos', None)
        orderpos = self.orderpos = kwargs.pop('orderpos', None)
        pos = cartpos or orderpos
        item = pos.item
        questions = pos.item.questions_to_ask
        event = kwargs.pop('event')
        self.all_optional = kwargs.pop('all_optional', False)

        super().__init__(*args, **kwargs)

        add_fields = {}

        if item.admission and event.settings.attendee_names_asked:
            add_fields['attendee_name_parts'] = NamePartsFormField(
                max_length=255,
                required=event.settings.attendee_names_required
                and not self.all_optional,
                scheme=event.settings.name_scheme,
                titles=event.settings.name_scheme_titles,
                label=_('Attendee name'),
                initial=(cartpos.attendee_name_parts
                         if cartpos else orderpos.attendee_name_parts),
            )
        if item.admission and event.settings.attendee_emails_asked:
            add_fields['attendee_email'] = forms.EmailField(
                required=event.settings.attendee_emails_required
                and not self.all_optional,
                label=_('Attendee email'),
                initial=(cartpos.attendee_email
                         if cartpos else orderpos.attendee_email),
                widget=forms.EmailInput(attrs={'autocomplete': 'email'}))
        if item.admission and event.settings.attendee_company_asked:
            add_fields['company'] = forms.CharField(
                required=event.settings.attendee_company_required
                and not self.all_optional,
                label=_('Company'),
                max_length=255,
                initial=(cartpos.company if cartpos else orderpos.company),
            )

        if item.admission and event.settings.attendee_addresses_asked:
            add_fields['street'] = forms.CharField(
                required=event.settings.attendee_addresses_required
                and not self.all_optional,
                label=_('Address'),
                widget=forms.Textarea(
                    attrs={
                        'rows': 2,
                        'placeholder': _('Street and Number'),
                        'autocomplete': 'street-address'
                    }),
                initial=(cartpos.street if cartpos else orderpos.street),
            )
            add_fields['zipcode'] = forms.CharField(
                required=event.settings.attendee_addresses_required
                and not self.all_optional,
                max_length=30,
                label=_('ZIP code'),
                initial=(cartpos.zipcode if cartpos else orderpos.zipcode),
                widget=forms.TextInput(attrs={
                    'autocomplete': 'postal-code',
                }),
            )
            add_fields['city'] = forms.CharField(
                required=event.settings.attendee_addresses_required
                and not self.all_optional,
                label=_('City'),
                max_length=255,
                initial=(cartpos.city if cartpos else orderpos.city),
                widget=forms.TextInput(attrs={
                    'autocomplete': 'address-level2',
                }),
            )
            country = (cartpos.country if cartpos else
                       orderpos.country) or guess_country(event)
            add_fields['country'] = CountryField(
                countries=CachedCountries).formfield(
                    required=event.settings.attendee_addresses_required
                    and not self.all_optional,
                    label=_('Country'),
                    initial=country,
                    widget=forms.Select(attrs={
                        'autocomplete': 'country',
                    }),
                )
            c = [('', pgettext_lazy('address', 'Select state'))]
            fprefix = str(
                self.prefix
            ) + '-' if self.prefix is not None and self.prefix != '-' else ''
            cc = None
            if fprefix + 'country' in self.data:
                cc = str(self.data[fprefix + 'country'])
            elif country:
                cc = str(country)
            if cc and cc in COUNTRIES_WITH_STATE_IN_ADDRESS:
                types, form = COUNTRIES_WITH_STATE_IN_ADDRESS[cc]
                statelist = [
                    s for s in pycountry.subdivisions.get(country_code=cc)
                    if s.type in types
                ]
                c += sorted([(s.code[3:], s.name) for s in statelist],
                            key=lambda s: s[1])
            elif fprefix + 'state' in self.data:
                self.data = self.data.copy()
                del self.data[fprefix + 'state']

            add_fields['state'] = forms.ChoiceField(
                label=pgettext_lazy('address', 'State'),
                required=False,
                choices=c,
                widget=forms.Select(attrs={
                    'autocomplete': 'address-level1',
                }),
            )
            add_fields['state'].widget.is_required = True

        field_positions = list([(n,
                                 event.settings.system_question_order.get(
                                     n if n != 'state' else 'country', 0))
                                for n in add_fields.keys()])

        for q in questions:
            # Do we already have an answer? Provide it as the initial value
            answers = [a for a in pos.answerlist if a.question_id == q.id]
            if answers:
                initial = answers[0]
            else:
                initial = None
            tz = pytz.timezone(event.settings.timezone)
            help_text = rich_text(q.help_text)
            label = escape(q.question)  # django-bootstrap3 calls mark_safe
            required = q.required and not self.all_optional
            if q.type == Question.TYPE_BOOLEAN:
                if q.required:
                    # For some reason, django-bootstrap3 does not set the required attribute
                    # itself.
                    widget = forms.CheckboxInput(
                        attrs={'required': 'required'})
                else:
                    widget = forms.CheckboxInput()

                if initial:
                    initialbool = (initial.answer == "True")
                else:
                    initialbool = False

                field = forms.BooleanField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=initialbool,
                    widget=widget,
                )
            elif q.type == Question.TYPE_NUMBER:
                field = forms.DecimalField(
                    label=label,
                    required=required,
                    min_value=q.valid_number_min or Decimal('0.00'),
                    max_value=q.valid_number_max,
                    help_text=q.help_text,
                    initial=initial.answer if initial else None,
                )
            elif q.type == Question.TYPE_STRING:
                field = forms.CharField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=initial.answer if initial else None,
                )
            elif q.type == Question.TYPE_TEXT:
                field = forms.CharField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    widget=forms.Textarea,
                    initial=initial.answer if initial else None,
                )
            elif q.type == Question.TYPE_COUNTRYCODE:
                field = CountryField(
                    countries=CachedCountries,
                    blank=True,
                    null=True,
                    blank_label=' ',
                ).formfield(
                    label=label,
                    required=required,
                    help_text=help_text,
                    widget=forms.Select,
                    empty_label=' ',
                    initial=initial.answer if initial else
                    (guess_country(event) if required else None),
                )
            elif q.type == Question.TYPE_CHOICE:
                field = forms.ModelChoiceField(
                    queryset=q.options,
                    label=label,
                    required=required,
                    help_text=help_text,
                    widget=forms.Select,
                    to_field_name='identifier',
                    empty_label='',
                    initial=initial.options.first() if initial else None,
                )
            elif q.type == Question.TYPE_CHOICE_MULTIPLE:
                field = forms.ModelMultipleChoiceField(
                    queryset=q.options,
                    label=label,
                    required=required,
                    help_text=help_text,
                    to_field_name='identifier',
                    widget=QuestionCheckboxSelectMultiple,
                    initial=initial.options.all() if initial else None,
                )
            elif q.type == Question.TYPE_FILE:
                field = ExtFileField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=initial.file if initial else None,
                    widget=UploadedFileWidget(position=pos,
                                              event=event,
                                              answer=initial),
                    ext_whitelist=(".png", ".jpg", ".gif", ".jpeg", ".pdf",
                                   ".txt", ".docx", ".gif", ".svg", ".pptx",
                                   ".ppt", ".doc", ".xlsx", ".xls", ".jfif",
                                   ".heic", ".heif", ".pages", ".bmp", ".tif",
                                   ".tiff"),
                    max_size=10 * 1024 * 1024,
                )
            elif q.type == Question.TYPE_DATE:
                attrs = {}
                if q.valid_date_min:
                    attrs['data-min'] = q.valid_date_min.isoformat()
                if q.valid_date_max:
                    attrs['data-max'] = q.valid_date_max.isoformat()
                field = forms.DateField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=dateutil.parser.parse(initial.answer).date()
                    if initial and initial.answer else None,
                    widget=DatePickerWidget(attrs),
                )
                if q.valid_date_min:
                    field.validators.append(MinDateValidator(q.valid_date_min))
                if q.valid_date_max:
                    field.validators.append(MaxDateValidator(q.valid_date_max))
            elif q.type == Question.TYPE_TIME:
                field = forms.TimeField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=dateutil.parser.parse(initial.answer).time()
                    if initial and initial.answer else None,
                    widget=TimePickerWidget(
                        time_format=get_format_without_seconds(
                            'TIME_INPUT_FORMATS')),
                )
            elif q.type == Question.TYPE_DATETIME:
                field = SplitDateTimeField(
                    label=label,
                    required=required,
                    help_text=help_text,
                    initial=dateutil.parser.parse(
                        initial.answer).astimezone(tz)
                    if initial and initial.answer else None,
                    widget=SplitDateTimePickerWidget(
                        time_format=get_format_without_seconds(
                            'TIME_INPUT_FORMATS'),
                        min_date=q.valid_datetime_min,
                        max_date=q.valid_datetime_max),
                )
                if q.valid_datetime_min:
                    field.validators.append(
                        MinDateTimeValidator(q.valid_datetime_min))
                if q.valid_datetime_max:
                    field.validators.append(
                        MaxDateTimeValidator(q.valid_datetime_max))
            elif q.type == Question.TYPE_PHONENUMBER:
                babel_locale = 'en'
                # Babel, and therefore django-phonenumberfield, do not support our custom locales such das de_Informal
                if localedata.exists(get_language()):
                    babel_locale = get_language()
                elif localedata.exists(get_language()[:2]):
                    babel_locale = get_language()[:2]
                with language(babel_locale):
                    default_country = guess_country(event)
                    default_prefix = None
                    for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
                        if str(default_country) in values:
                            default_prefix = prefix
                    try:
                        initial = PhoneNumber().from_string(
                            initial.answer) if initial else "+{}.".format(
                                default_prefix)
                    except NumberParseException:
                        initial = None
                    field = PhoneNumberField(
                        label=label,
                        required=required,
                        help_text=help_text,
                        # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just
                        # a country code but no number as an initial value. It's a bit hacky, but should be stable for
                        # the future.
                        initial=initial,
                        widget=WrappedPhoneNumberPrefixWidget())
            field.question = q
            if answers:
                # Cache the answer object for later use
                field.answer = answers[0]

            if q.dependency_question_id:
                field.widget.attrs[
                    'data-question-dependency'] = q.dependency_question_id
                field.widget.attrs[
                    'data-question-dependency-values'] = escapejson_attr(
                        json.dumps(q.dependency_values))
                if q.type != 'M':
                    field.widget.attrs[
                        'required'] = q.required and not self.all_optional
                    field._required = q.required and not self.all_optional
                field.required = False

            add_fields['question_%s' % q.id] = field
            field_positions.append(('question_%s' % q.id, q.position))

        field_positions.sort(key=lambda e: e[1])
        for fname, p in field_positions:
            self.fields[fname] = add_fields[fname]

        responses = question_form_fields.send(sender=event, position=pos)
        data = pos.meta_info_data
        for r, response in sorted(responses, key=lambda r: str(r[0])):
            for key, value in response.items():
                # We need to be this explicit, since OrderedDict.update does not retain ordering
                self.fields[key] = value
                value.initial = data.get('question_form_data', {}).get(key)

        for k, v in self.fields.items():
            if v.widget.attrs.get(
                    'autocomplete') or k == 'attendee_name_parts':
                v.widget.attrs['autocomplete'] = 'section-{} '.format(
                    self.prefix) + v.widget.attrs.get('autocomplete', '')
Example #32
0
def _contextual_locale(context):
    """Return locale from the context, falling back to a default if invalid."""
    locale = context['request'].locale
    if not localedata.exists(locale):
        locale = settings.LANGUAGE_CODE
    return locale
Example #33
0
def _get_request_locale(request):
    """Return locale from the request, falling back to a default if invalid."""
    locale = request.LANGUAGE_CODE
    if not localedata.exists(locale):
        locale = settings.LANGUAGE_CODE
    return language_to_locale(locale)
Example #34
0
def test_mixedcased_locale():
    for l in localedata.locale_identifiers():
        locale_id = ''.join([
            methodcaller(random.choice(['lower', 'upper']))(c) for c in l])
        assert localedata.exists(locale_id)
Example #35
0
def _contextual_locale(context):
    """Return locale from the context, falling back to a default if invalid."""
    locale = context['request'].locale
    if not localedata.exists(locale):
        locale = settings.LANGUAGE_CODE
    return locale
def test_locale_identification():
    for l in localedata.locale_identifiers():
        assert localedata.exists(l)
Example #37
0
def check_locale(locale):
    locale = locale.lower()
    if locale not in config.LOCALE:
        locale = config.LOCALE_DEFAULT
    return locale if localedata.exists(locale) else 'en'
Example #38
0
 def validate(self, element, state):
     if not localedata.exists(element.value):
         return self.note_error(element, state, 'invalid_locale')
     return True
Example #39
0
def translate():
    '''
    Edita la traducción a un idioma
    '''

    languages = localedata.load(g.lang)["languages"]
    keystrcoll = cmp_to_key(locale.strcoll)
    form = None
    forml = SelectLanguageForm(request.form)
    forml.lang.choices = [("", "-- "+_("choose_language")+" --")] + sorted(
        ((code, localedata.load(code)["languages"][code].capitalize()+" ("+languages[code].capitalize()+")")
            for code, language in languages.items()
            if code in current_app.config["TRANSLATE_LANGS"] and not code in current_app.config["LANGS"] and localedata.exists(code) and code in localedata.load(code)["languages"]),
        key=lambda x: keystrcoll(x[1]))

    total=99999
    no_translation=0
    msgids=[]
    lang_edit = request.args.get("lang")
    if not lang_edit in languages:
        lang_edit = None

    formfields = {}
    # mostrar el idioma a traducir
    if lang_edit is not None:
        forml.lang.default=lang_edit
        # cargar idioma actual
        current_lang = dict(fix_lang_values(entry,True) for entry in polib.pofile(lang_path(g.lang)))

        # si existe el idioma se carga, sino vacio
        lpath = lang_path(lang_edit)
        new_lang = dict(fix_lang_values(entry) for entry in polib.pofile(lpath)) if lpath else {}

        # recorre los ids en ingles y los coge el mensaje del idioma actual y el valor del nuevo
        for i, (msgid, msgstr) in enumerate(fix_lang_values(entry,True) for entry in polib.pofile(lang_path("en"))):
            # se excluyen los textos legales que concluyen con safe_
            if not msgid.startswith(current_app.config["PRIVATE_MSGID_PREFIXES"]):
                # si no esta traducida la cadena en el idioma actual se deja vacio
                if not msgid in new_lang:
                    no_translation+=1
                    new_lang[msgid]=""

                # si el mensaje esta traducido al idioma actual se usa, sino se usa el ingles
                if msgid in current_lang:
                    msg=current_lang[msgid][0]
                    description=current_lang[msgid][1]
                else:
                    msg=msgstr[0]
                    description=msgstr[1]

                # si la traduccion es mayor de 80 caracteres se utiliza un textarea en vez de un input text
                length=len(new_lang[msgid] or msg)
                if length>50:
                    formfields[msgid]=TextAreaField(msg,default=new_lang[msgid],description=description)
                    # se le establecen las filas al text area dependiendo del tamaño de la traduccion
                    formfields["_args_%s" % msgid]={"rows":length/15}
                else:
                    formfields[msgid]=TextField(msg,default=new_lang[msgid],description=description)
                    formfields["_args_%s" % msgid]={}

                #se añade a la lista que se le envia al formulario
                msgids.append(msgid)

        total=float(len(msgids))
        form=expanded_instance(TranslateForm, formfields, request.form, prefix="translate_")
        # si es el envio de la traducción
        if request.method == 'POST' and form.validate():
            pagesdb.create_translation({"ip":request.remote_addr,"user_lang":g.lang,"dest_lang":lang_edit,"texts":{field.short_name: field.data for field in form if not field.short_name in ("captcha", "submit_form") and field.data!=new_lang[field.short_name]}})
            flash("translation_sent")
            return redirect(url_for('index.home'))

    if lang_edit: forml.lang.data = lang_edit
    # sino se muestra la seleccion de idioma a traducir
    g.title+=_("translate_to_your_language")
    return render_template('pages/translate.html',
        page_title=_("translate_to_your_language"),
        pagination=["submitlink","submitlink",2,2],
        lang=lang_edit,
        forml=forml,
        form=form,
        pname="translate",
        msgids=msgids,
        complete=round(((total-no_translation)/total)*100,2))
 def _validate(self, val):
     if not localedata.exists(val):
         raise db.BadValueError('Not a valid locale')