Exemple #1
0
 def test_message_invalid_parameter_syntax_in_both(self):
     catalog = Catalog()
     catalog.add("id", string="Hello {a b}")
     with mock_app_catalogs({"el": catalog, "en": catalog}):
         with self.assertLogs(level=logging.ERROR):
             with self.assertRaises(ICUError):
                 localize_html("el", "id", arguments={"a": "you", "b": "!"})
Exemple #2
0
    def test_message_exists_in_no_locales(self):
        def mock_get_translations(locale):
            return MessageTranslator(locale, Catalog())

        with patch("cjworkbench.i18n.trans._get_translations",
                   mock_get_translations):
            with self.assertRaises(KeyError):
                localize_html("el", "id")
Exemple #3
0
    def test_message_invalid_parameter_syntax_in_default(self):
        def mock_get_translations(locale):
            catalog = Catalog()
            if locale == "en":
                catalog.add("id", string="Hello {a b}")
            return MessageTranslator(locale, catalog)

        with patch("cjworkbench.i18n.trans._get_translations",
                   mock_get_translations):
            with self.assertRaises(ICUError):
                localize_html("el", "id", arguments={"a": "you", "b": "!"})
Exemple #4
0
 def test_message_exists_in_given_locale(self):
     en_catalog = Catalog()
     en_catalog.add("id", string="Hello")
     el_catalog = Catalog()
     el_catalog.add("id", string="Hey")
     with mock_app_catalogs({"el": el_catalog, "en": en_catalog}):
         self.assertEqual(localize_html("el", "id"), "Hey")
Exemple #5
0
    def test_message_exists_only_in_default_locale(self):
        def mock_get_translations(locale):
            catalog = Catalog()
            if locale == "en":
                catalog.add("id", string="Hello")
            return MessageTranslator(locale, catalog)

        with patch("cjworkbench.i18n.trans._get_translations",
                   mock_get_translations):
            self.assertEqual(localize_html("el", "id"), "Hello")
Exemple #6
0
 def test_message_invalid_parameter_syntax(self):
     en_catalog = Catalog()
     en_catalog.add("id", string="Hello {a} {b}")
     el_catalog = Catalog()
     el_catalog.add("id", string="Hey {a b}!")
     with mock_app_catalogs({"el": el_catalog, "en": en_catalog}):
         with self.assertLogs(level=logging.ERROR):
             result = localize_html("el",
                                    "id",
                                    arguments={
                                        "a": "you",
                                        "b": "!"
                                    })
         self.assertEqual(result, "Hello you !")
Exemple #7
0
    def test_message_invalid_parameter_syntax(self):
        def mock_get_translations(locale):
            catalog = Catalog()
            if locale == "en":
                catalog.add("id", string="Hello {a} {b}")
            else:
                catalog.add("id", string="Hey {a b}!")
            return MessageTranslator(locale, catalog)

        with patch("cjworkbench.i18n.trans._get_translations",
                   mock_get_translations):
            with self.assertLogs(level=logging.ERROR):
                result = localize_html("el",
                                       "id",
                                       arguments={
                                           "a": "you",
                                           "b": "!"
                                       })
            self.assertEqual(result, "Hello you !")
Exemple #8
0
def trans_html(context,
               message_id,
               *,
               default,
               ctxt="",
               noop=False,
               comment="",
               **kwargs):
    """Translate a message, supporting HTML placeholders and variables.

    The message can contain variables in the form `{var}`. Their values must be given with keys of the form `arg_{variable}`,
    e.g. for the message `"Hello {name}"`, `arg_name` is expected
    The variables can't be named as integers, i.e. `{0}` is not a valid variable name.

    HTML tags and their attributes must have been replaced with placeholders and the original must be provided as follows:
        - Each tag placeholder consists of the name of the tag followed by an integer, e.g. `a` becomes `a0` or `a1` etc.
          You are advised to use consecutive integers starting from 0 for each tag name,
          i.e. you could have `a0`, then `a1`, then `span0`, then `div0`, then `span1`
        - Each attribute is provided (only once) with key `tag_{placeholder}_{attribute_name}`,
          so in order to replace `<a0>...</a0>` with `<a href="/hello" class="red small">...</a>`,
          you need to provide `tag_a0_href="/hello"` and `tag_a0_class="red small"`
        - Tags without attributes (for example `tag_b0`) are supported; you must map them to some value, which will be ignored
        - Tags and their attributes can't contain dashes, so data attributes are not supported
    Nested HTML tags are forbidden; in fact, at this point, the inner ones will be escaped, but you should not rely on this.
    Non-nested tags that have not been mapped in this way will be ignored; in fact, at this point, they will replaced by their escaped contents, but you should not rely on this.

    The locale will be taken from context.
    The `default` argument will only be used in code parsing for message extraction.

    For code parsing reasons, respect the following order when passing more than one of `default`, `ctxt`, and `comment` arguments:
        `default` before `ctxt` before `comment`

    If `noop` is the value `True`, the translation library will not be used and you will just get `None`

    The `comment` argument is ignored here, it's only used in code parsing.

    Examples:
        - `{% trans_html "messages.hello" default="Hello" comment="This can be all caps if you really want it to be" %}`
          Looks up `messages.hello` in the catalog for the current locale;
          if not found, looks up `messages.hello` in the catalog for the default locale;
          if not found, returns `messages.hello`.
          When the code is parsed, the comment and the default will be added to the message catalog.

        - `{% trans_html "messages.hello" default="Hello {name}" arg_name="Adam"%}`
          looks up `messages.hello` in the catalog for the current locale and provides `"Adam"` as a value for `name`;
          if not found, looks up `messages.hello` in the catalog for the default locale;
          if not found, returns `messages.hello`.
          When the code is parsed, the default will be added to the message catalog.

        - `{% trans_html "messages.hello" default="Hello {name}" ctxt="dashboard" arg_name="Adam"%}`
          looks up `messages.hello` with context `dashboard` in the catalog for the current locale and provides `"Adam"` as a value for `name`;
          if not found, looks up `messages.hello` in the catalog for the default locale;
          if not found, returns `messages.hello`.
          When the code is parsed, the context and the default will be added to the message catalog.

        - `{% trans_html "messages.hello" noop=True default="Hello" %}`
          returns None
          When the code is parsed, the default will be added to the message catalog.

        - `{% trans_html "messages.hello" default="<span0>Hello</span0> <span1>you</span1>" tag_span0_class="red big" tag_span1_class="small yellow" tag_span1_id="you" tag_em0="" %}`
          looks up `messages.hello` in the catalog for the current locale and replaces the placeholders with the info in `tag_*` arguments;
          for example, the default message would become `'<span class="red big">Hello</span> <span class="small yellow" id="you">you</span>'`
          When the code is parsed, the default will be added to the message catalog.

        - `{% trans_html some_var default="the default" %}`
          Looks up the content of `some_var` in the catalogs (first for the current and then for the default locale).
          If found, returns it, else returns the content of `some_var`.
          When the code is parsed for message extraction, this will be ignored.
    """
    if noop is True:
        return None

    params = {}
    tags = {}
    for arg in kwargs:
        match_param = trans_param_re.match(arg)
        if match_param:
            params[match_param.group("arg")] = kwargs[arg]
            continue
        match_tag = trans_tag_re.match(arg)
        if match_tag:
            placeholder = match_tag.group("placeholder")
            tag_name = match_tag.group("name")
            tag_attr = match_tag.group("attr")
            if not (placeholder in tags):
                tags[placeholder] = {"tag": tag_name, "attrs": {}}
            tags[placeholder]["attrs"][tag_attr] = kwargs[arg]
            continue
        match_tag = trans_tag_without_attribute_re.match(arg)
        if match_tag:
            placeholder = match_tag.group("placeholder")
            tag_name = match_tag.group("name")
            if not (placeholder in tags):
                tags[placeholder] = {"tag": tag_name, "attrs": {}}
            continue

    try:
        locale_id = context["i18n"]["locale_id"]
    except KeyError as err:
        # context[i18n] needs to be managed by the caller. And sometimes, the
        # caller has a bug. (Seen 2019-08-2019-12-06 01:57:19.327 GMT.) We want
        # Django's exception-handling code to be able to call trans_html().
        #
        # Log the message ID. This should help us with debugging.
        logger.exception(
            "Missing context['i18n']['locale_id'] translating message_id %s",
            message_id)
        locale_id = default_locale

    result = localize_html(locale_id,
                           message_id,
                           context=ctxt or None,
                           tags=tags,
                           arguments=params)
    return mark_safe(result)
Exemple #9
0
 def test_message_invalid_parameter_syntax_in_default(self):
     en_catalog = Catalog()
     en_catalog.add("id", string="Hello {a b}")
     with mock_app_catalogs({"el": Catalog(), "en": en_catalog}):
         with self.assertRaises(ICUError):
             localize_html("el", "id", arguments={"a": "you", "b": "!"})
Exemple #10
0
 def test_message_exists_in_no_locales(self):
     with mock_app_catalogs({"el": Catalog(), "en": Catalog()}):
         with self.assertRaises(KeyError):
             localize_html("el", "id")