This patch introduces two new concepts:

- A renderable text element that will be localized when printed.
- Replaces currently fragmented and unreadable modules help text.

The first part introduces a 'text' element that is a renderable array + a helper function to build such texts, text().

/**
 * Build a structured text element to be rendered later.
 *
 * @param $name
 *   Unique text name
 * @param $text
 *   HTML text
 * @param $variables
 *   Optional variables for text replacement
 *
 * @return
 *   Text array
 */
function text($name, $text, $variables = array(), $options = array()) {
  return array(
    '#type' => 'text',
    '#name' => $name,
    '#text' => $text,
    '#variables' => $variables,
    '#options' => $options,
  );
}

Improves the help system to make use of these elements. Done for the node module only as a proof of concept. Some example:

/**
 * Implements hook_help().
 */
function node_help($path, $arg) {
....
  switch ($path) {
    case 'admin/help#node':
      $build['about'] = text('node.help.admin.about',
        '<h3>About</h3>' .
    	'<p>The Node module manages the creation, editing, deletion, settings, and display of the ' .
        'main site content. Content items managed by the Node module are typically displayed as ' .
        'pages on your site, and include a title, some meta-data (author, creation time, content ' .
        'type, etc.), and optional fields containing text or other data (fields are managed by the ' .
        '<a href="@field">Field module</a>). For more information, see the online handbook entry for ' .
        '<a href="@node">Node module</a></p>',
        array(
        	'@node' => 'http://drupal.org/handbook/modules/node',
        	'@field' => url('admin/help/field'),
        )
      );
     return $build;
}

Pros:
- Text that have a proper identifier (name) can be altered by modules.
- Only text that will be displayed will be localized.
- Localization system though it defaults to current one is pluggable by altering the text element
- Help text for modules is much more readable and flexible.
- It can be used for many other texts in modules that can be 'altered' or 'localized' using different systems.
- It can be also used for configurable texts, localization is pluggable and flexible enough.

Cons:
- Would need improving the po extractor to extract these texts for localization.
- Would require some changes to how big texts are currently translated (though it would make it more powerful and flexible, translators would be able to work with big texts in context, etc..)

Comments

jose reyero’s picture

Issue tags: +D8MI
StatusFileSize
new13.29 KB

Here's the patch, tagging the issue.

jose reyero’s picture

Related, this other patch would first simplify help texts, #1445144: Build better tokens with parameters (and use them to replace help text)
Then we may need to add token replacement capabilities to these renderable texts.

andypost’s picture

Great idea but not sure about text() function. maybe better to rethink a hook_help() to return $build array
Also we have #markup and #item elements that could be extended to support translation

Edit: patch has a lot of Tab characters

jhodgdon’s picture

I was asked to comment on this in regards to the help system. Although we had thougts of completely getting rid of the current hook_help() system for Drupal 8, at this point I can confidently say that it's not going to happen for Drupal 8 (not going into the reasons why, but it isn't).

That said, I don't understand from this issue why the text() function is better than t(), but if you think it is, I have no objection to changing hook_help() to use it.

jhodgdon’s picture

Just to clarify... From the perspective of someone writing hook_help() text, changing from t() to text() doesn't appear to change anything I would need to do, except that I have to think of a unique text name to use as the first argument to text(). The other two arguments, unless I am mistaken, are the same as t().

So can you clarify what the purpose of this change would be? Who is it helping (translators maybe?), and how?

dawehner’s picture

Status: Active » Needs work
+++ b/core/includes/common.incundefined
@@ -2390,6 +2390,29 @@ function l($text, $path, array $options = array()) {
+ * Build a structured text element to be rendered later.

It would be good to document the #localize, #localize_function and #replace feature.
If there is a text() function it should better explain when it's used instead of just plain t().

+++ b/core/modules/help/help.admin.incundefined
@@ -51,10 +51,14 @@ function help_page($name) {
+      	'#items' => $links,
+      	'#title' => t('@module administration pages', array('@module' => $info[$name]['name']))

Here and below in the hook_help implementations are tabs instead of spaces.

One related issue here: #1484002: Add support for named texts for the locale system. Introducing drupal_text()

jose reyero’s picture

Since feedback from documentation team is not possitive (I understand they have different longer term plans) but I still think building texts as arrays is a good idea (so it can be altered, localized later if finally printed, etc) I'm going to re-roll this patch with some important changes:

- Keep help texts as they are (I mean use the same strings) but still wrap them in arrays.
- Make names optional, thus text() would be pretty much like t(), but it will still produce an element array that will be localized later only when rendered.
- Add support for formats (check_markup) filters (filter_xss...), etc..
- Add support for tags and attributes (theme_html_tag) since these texts are often wrapped with some more HTML.

So the main idea of this one is that for longer texts we produce renderable arrays and they can be altered before they go through other operations like running them through t() or applying filters or formats. This way if the text is not finally rendered (a module takes it out the render array or changes it) we don't waste time localizing or formatting it.

jair’s picture

Status: Needs work » Needs review
Issue tags: +Needs reroll

The last submitted patch, 1444980_text_element.patch, failed testing.

alansaviolobo’s picture

Status: Needs work » Needs review
StatusFileSize
new9.07 KB
new5.25 KB

rerolled the patch. There was a problem when creating the interdiff.

Status: Needs review » Needs work

The last submitted patch, 10: add_renderable-1444980-10.patch, failed testing.

jhodgdon’s picture

Um.... How is this text going to be translatable? I mean, how is it going to get into the localize.drupal.org databaes?

And I don't really think this is any more readable than the current way of doing things anyway? How is making a text element more readable than calling t()? The other changes in this patch (reformatting) could be done in t() anyway?

See also #5.

andypost’s picture

Version: 8.0.x-dev » 8.1.x-dev

8.1 meterial

jhodgdon’s picture

Oh, I forgot about this issue!

So I actually have a working system for Configurable Help topics that creates plugins for text segments, in a sandbox project. I should adapt that patch for Core here. See https://www.drupal.org/sandbox/jhodgdon/2369943

Using that system, a hook_help() implementation like this:

      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Help module generates <a href=":help-page">Help reference pages</a> to guide you through the use and configuration of modules, and provides a Help block with page-level help. The reference pages are a starting point for <a href=":handbook">Drupal.org online documentation</a> pages that contain more extensive and up-to-date information, are annotated with user-contributed comments, and serve as the definitive reference point for all Drupal documentation. For more information, see the <a href=":help">online documentation for the Help module</a>.', array(':help' => 'https://www.drupal.org/documentation/modules/help/', ':handbook' => 'https://www.drupal.org/documentation', ':help-page' => \Drupal::url('help.main'))) . '</p>';
      $output .= '<h3>' . t('Uses') . '</h3>';
      $output .= '<dl>';
      $output .= '<dt>' . t('Providing a help reference') . '</dt>';
      $output .= '<dd>' . t('The Help module displays explanations for using each module listed on the main <a href=":help">Help reference page</a>.', array(':help' => \Drupal::url('help.main'))) . '</dd>';
      $output .= '<dt>' . t('Providing page-specific help') . '</dt>';
      $output .= '<dd>' . t('Page-specific help text provided by modules is displayed in the Help block. This block can be placed and configured on the <a href=":blocks">Block layout page</a>.', array(':blocks' => (\Drupal::moduleHandler()->moduleExists('block')) ? \Drupal::url('block.admin_display') : '#')) . '</dd>';
      $output .= '</dl>';

would become a render array, something like this:

$sections = [];
$sections[] = ['#type' => 'header', '#text' => t('About')];
$sections[] = ['#type' => 'paragraph', '#text' => t('The Help module generates <a href=":help-page">Help reference pages</a> to guide you through the use and configuration of modules, and provides a Help block with page-level help. The reference pages are a starting point for <a href=":handbook">Drupal.org online documentation</a> pages that contain more extensive and up-to-date information, are annotated with user-contributed comments, and serve as the definitive reference point for all Drupal documentation. For more information, see the <a href=":help">online documentation for the Help module</a>.', array(':help' => 'https://www.drupal.org/documentation/modules/help/', ':handbook' => 'https://www.drupal.org/documentation', ':help-page' => \Drupal::url('help.main')))];
$sections[] = ['#type' => 'header', '#text' => t('Uses')];
$sections[] = ['#type' => 'description_name', '#text' => t('Providing a help reference')];
$sections[] = ['#type' => 'description_value', t('The Help module displays explanations for using each module listed on the main <a href=":help">Help reference page</a>.', array(':help' => \Drupal::url('help.main')))];
$sections[] = ['#type' => 'description_name', '#text' => t('Providing page-specific help')];
$sections[] = ['#type' => 'description_value', t('Page-specific help text provided by modules is displayed in the Help block. This block can be placed and configured on the <a href=":blocks">Block layout page</a>.', array(':blocks' => (\Drupal::moduleHandler()->moduleExists('block')) ? \Drupal::url('block.admin_display') : '#'))];

$build = [
  '#type' => 'text_sections',
  '#sections' => $sections,
];

Then the 'text_sections' render element and the various text section plugins take care of making this into H3, paragraph, and DL/DT/DD elements.

It doesn't take care of the localization part -- we already have t() for that -- but it does take care of abstracting away some of the embedded HTML stuff.

Thoughts? If this seems like an improvement, I can make that part of the sandbox module into a patch here.

jhodgdon’s picture

As a note... One of the problems identified in the current issue summary here is not really a problem any more: t() is now not translating until later. Instead, it makes a "translatable markup" object and it is only translated if the translation is actually being rendered.

I think that the patch proposed earlier on this issue is not in line with how we are currently doing things in Core either... The translation system has been overhauled with these TranslatableMarkup objects, and rather than introducing a function like text() in common.inc, we'd want to use the render system more directly.

Also, the proposal in the issue summary, where the HTML tags would be added back into the translated strings and the strings would become very long, is not viable given localize.drupal.org. See meta issue #2592487: [meta] Help system overhaul for more details... adding this as its child also.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jhodgdon’s picture

Adding related issue, which also had a patch, but which was abandoned recently.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

vacho’s picture

I think that rather than make another patch(or re-roll) needs to define a good and concerted solutions

With the current way to write help for a module

Agree:
- It isn't have a localizeable text element for use at another part of code.
- It isn't readable and flexible .
- It isn't pluggable.

Current proposal solution:
- Chunk the current $output variable at $output associative array when you can divide in parts your help and this can be standardized too.
In concept It is too according with @jhodgdon proposal solution but in other way.

So to recover the discussion
Another proposal solution:
I think that this is an use that I really will like when I writing a help of module:

$build = [
 'title' => '....',
 'about' => '...',
 'uses' => '...'
 'references' => [
    'website' => some link
    'repository' =>some link
    'documentation' =>some link
 ]
]

Where we will write only the main thinks on documentations with references to hard documentations that almost all contribute modules have in other places.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.