Problem/Motivation

The text on examples/filter_example does not display properly because '<time />' is passed as part of the first argument of t().

Proposed resolution

Pass array('@tag' => '<time />') as the second argument to t().

While looking at the source to make this change, I noticed some typos in the comments. The patches I submitted fix these, and move one comment block.

Since the string 'foo' might be accidentally translated, I also pass array('@foo' => 'foo') as the second argument to t(). Comment 11 suggests that this is a bad idea, so I also made patches that do not contain this change.

Original report by [benjifisher]

API page: http://api.drupal.org/api/examples/filter_example--filter_example.module

Describe the problem you have found:
In _filter_example_information(), the HTML tag '<time />' is not escaped. I suggest rewriting the function as

function _filter_example_information() {
  return t("There are two filters in this example. The first (foo filter) just replaces
    'foo' with a configurable replacement. The second replaces the string
    '!tag' with the current time. To use these filters, go to !link and
    configure one of the input formats.",
    array(
      '!tag' => htmlspecialchars('<time />'),
      '!link' => l("admin/config/content/formats", "admin/config/content/formats"),
    )
  );
}

Of course, you can use a literal string instead of calling htmlspecialchars() if you prefer.

P.S. I have trouble when previewing this bug report. The Description box is empty after I click the Preview button. :-(

Comments

benjifisher’s picture

P.P.S. While you are at it, I suggest putting the comment block headed

 /*
  * Foo filter

after the implementation of _filter_example_information().

benjifisher’s picture

Project: Examples for Developers » Drupal core
Version: 7.x-1.x-dev » 7.x-dev
Component: Filter Example » documentation
Status: Needs review » Active

Sorry to do this piecemeal, but I have more problems with the comment block

/*
 * Foo filter
 *
 * Drupal has several content formats (they are not filters), and in our example
 * the foo replacement can be configured for each one of them, allowing an html
 * or php replacement, so the module includes a settings callback, with options
 * to configure that replacements. Also, a Tips callback will help showing the
 * current replacement for the content type being edited.
 */
  1. I think the term "content formats" should be replaced by "text formats."
  2. What does "html or php replacement" mean? I tried using <?php 7+5 ?> and variants as the replacement text, and got odd results: the first "foo" was replaced with the default "bar", and the rest of the text was deleted.

The function _filter_example_filter_foo_tips() contains the line

return t('<em>foo</em> replaced with %replacement.', array('%replacement' => $replacement));

I would use

return t('%foo replaced with %replacement.', array('%foo' => 'foo', '%replacement' => $replacement));

since 'foo' should not be translated. Ditto for the long form of the tip.

There is a typo in the comment block

/*
 * Time filter process callback
 *
 * Now, in the "process" step, we'll search for our escaped time tags and
 * to the real filtering: replace the xml tag with the date.
 */

The word "to" on the last line should be "do".

jhodgdon’s picture

Project: Drupal core » Examples for Developers
Version: 7.x-dev » 7.x-1.x-dev
Component: documentation » Filter Example

Moving to Examples project for triage/fixing

mile23’s picture

Benjifisher, would you like to submit a patch? If you've never made a patch before, this is a good chance to learn how. :-)

http://drupal.org/patch

benjifisher’s picture

Yes, I have made patches before, and I am happy to make one for this issue. I just need a hint for how to get this file. AFAIK it is not part of the distribution tarball. Also, do you like my use of htmlspecialchars() or should I just use

      '!tag' => '&lt;time /&gt;',

in the patch?

rfay’s picture

You're in the right module now.

You can check out examples with git clone git://git.drupal.org/project/examples.git --branch 7.x-1.x

benjifisher’s picture

Status: Active » Needs review
StatusFileSize
new3.34 KB

The attached patch fixes the problems discussed in this issue:

  1. HTML tags are properly escaped in _filter_example_information().
  2. The comment block headed * Foo filter is moved after the implementation of _filter_example_information().
  3. In that comment block, "content formats" is replaced by "text formats" and the phrase "allowing an html or php replacement" is removed. Line breaks are adjusted.
  4. In _filter_example_filter_foo_tips(), the string 'foo' should not be translated, so it is replaced with a token. Since the same two tokens are used in the long and short versions of the tip, a new variable is used as the second argument of t().
  5. In the comment block headed * Time filter process callback, the phrase, "to the real filtering" is changed to "do the real filtering".

In (1) I did not use htmlspecialchars() as I originally suggested. (KISS)

benjifisher’s picture

Status: Needs review » Active

P.S. Thanks to jhodgdon for moving this to the right queue and to rfay for the git instructions.

rfay’s picture

Status: Active » Needs review
benjifisher’s picture

StatusFileSize
new3.82 KB

I noticed a typo in one of the comments, so the attached patch includes one more chunk.

rfay’s picture

Project: Drupal core » Examples for Developers
Version: 7.x-dev » 7.x-1.x-dev
Component: documentation » Filter Example
Status: Active » Needs work

I don't really understand some of what you're doing here.

The purpose of the simple 'foo' filter is to statically transform the string 'foo' to whatever is configured. But you're trying to make it do something more complex?

+++ b/filter_example/filter_example.module
@@ -119,12 +122,13 @@ function _filter_example_filter_foo_process($text, $filter, $format) {
-    return t('Every instance of "foo" in the input text will be replaced with a configurable value. You can configure this value and put whatever you want there. The replacement value is "%replacement".', array('%replacement' => $replacement));
+    return t('Every instance of "%foo" in the input text will be replaced with a configurable value. You can configure this value and put whatever you want there. The replacement value is "%replacement".', $args);

The value 'foo' is not configurable, but rather its replacement is. Why are you tokenizing 'foo'?

Powered by Dreditor.

benjifisher’s picture

I agree that 'foo' is not configurable. The reason I tokenize it is to protect it from accidental translation. I admit it is unlikely that a French translator would turn it into 'Chaque instance de "feu" dans le texte d'entrée ...' (replacing "foo" with something that sounds similar) but I think it is possible. Maybe a more realistic concern is the Russian translation: Google suggests 'Каждый экземпляр "Foo" в ввода текста', and capitalizing "foo" breaks it.

rfay’s picture

The idea of Examples is to be a teaching module, so we want to avoid introducing distractions. So we definitely won't make 'foo' replaceable, as that just distracts from the job at hand.

But re #7 I think everything else is OK. Would you mind rerolling with just documentation improvements? (Everything but #4)

benjifisher’s picture

StatusFileSize
new2.77 KB

I count the contents of _filter_example_filter_foo_tips() (or any other help text) as documentation. I still do not think that my patch made 'foo' "replaceable."

But you are the boss, so I am submitting a patch with the changes to _filter_example_filter_foo_tips() reverted. In other words, the same patch as in #10, but without item 4 from comment #7.

benjifisher’s picture

Status: Needs work » Needs review

Have to change the status to get the patch tested. Still learning ...

droplet’s picture

Status: Needs review » Needs work
+++ b/filter_example/filter_example.moduleundefined
@@ -69,12 +59,25 @@ function _filter_example_information() {
+      '!tag' => '&lt;time /&gt;',

I think this line should be
'@tag' => '<time />',

or as placeholder
'%tag' => '<time />',

easier to read.
http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/t/7

and line #174 of this module:

function _filter_example_filter_time_tips($filter, $format, $long = FALSE) {
  return t('<em>&lt;time /&gt;</em> is replaced with the current time.');
}

It needs fix too if we fix above part.

benjifisher’s picture

droplet, thanks for the review.

I agree that using @tag makes it easier to read. The change you suggest to _filter_example_filter_time_tips() will make it easier to read, too, but I would not say it "needs fix" since it generates the same HTML either way.

I will make both the changes you suggest. What do you think of replacing "foo" with a token (or placeholder)? See comments 2, 11, 12 above.

droplet’s picture

It defined as a filter feature and hardcoded (that means we cannot change tag). Pass through variable prevents translation mistake. It's the only reason why I think it should be change. Otherwise hardcoded all into strings directly is okay.

CORE module is hardcoded them directly.

benjifisher’s picture

Status: Needs work » Needs review
StatusFileSize
new4.17 KB
new5.36 KB

The attached patches implement the two suggestions in #16. They are based on the patch in #10, but the second patch (with "minimal" in the file name) passes 'foo' as part of the first parameter to t() instead of using array('@foo' => 'foo'), as requested in #11.

I still think that it makes sense to pass 'foo' in the second parameter of t() in order to prevent accidental translation. This does not make the string 'foo' "configurable": in fact, it stops the translator from accidentally "configuring" it in the filter tips and elsewhere.

Am I missing some important difference between @foo and %foo? Comment #16 suggests a difference, but my understanding is that the % form just adds <em> tags.

I think it is time to edit the summary ...

rfay’s picture

Yes, %foo only adds em tags (or whatever theme_placeholder() decides).

rfay’s picture

Status: Needs review » Fixed

OK, I accepted the typo fixes and stuff, but just fixed the OP with &gt; and &lt;, which is a very straightforward approach to the original problem. Sorry, I should have just said that in the first place. I felt like all the added t() arguments just added complexity to the code for no reason.

If I've missed something here, please straighten me out.

Committed to d7: cac2088
D8: af4fdc3

rfay’s picture

StatusFileSize
new2.85 KB

Forgot to attach the actual patch

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes

adding a summary now that there are too many comments to read easily