Jump to content

Where to hook to override language to output for field


Recommended Posts

I'm a bit at a loss where to put my hooks. My requirement is to have a checkbox in the page (already there) that tells my module to pull fields (i.e. body, headline etc., but possibly others too in the near future) from the default language, no matter if there's a value set in the current language, and apply some replacement before rendering (think HannaCode-like, though with a whole dictionary database for technical terms behind it).

Now, I'm unsure where to hook. I've looked through the LanguageSupport modules and tried to spy in HannaCode, but I've not been able to wrap my head around all the getLanguage..., getFormatted... and whatnot hookable methods involved. Attempts at overriding LanguageSupportFIelds::hookFieldtypeFormatValue and extending its logic somehow ended up with an endless recursion. If anybody could give me a few pointers (or method names) I should look for, this would be great.

Link to comment
Share on other sites

Thank you! That was exactly the place. I had to fiddle a bit because I tried at first with $page->getLanguageValue which again led to an infinite recursion, but this works:

    public function init() {
        $this->addHookBefore('FieldtypeText::formatValue', $this, 'hookBeforeFormatValue');

    public function hookBeforeFormatValue($event)
        $page = $event->arguments(0);
        $field = $event->arguments(1);
        $value = $event->arguments(2);

        if( $field->name == 'body' && $page->isMultiLang == 1 && ! $this->user->language->isDefault() )
            $lang = $this->user->language;
            $this->user->language = wire('languages')->get('default');
            $value = $page->get($field->name);
            $this->user->language = $lang;
            // Pattern replacement part comes here
            $event->return = $value;
            $event->replace = true;

I've thought about making the valid field names configurable in the template definition, but that's probably a bit too steep right now. Thanks again!

Link to comment
Share on other sites

Huh. My enthusiasm was premature. Unfortunately, this only works if I don't need to modify the text value in the default language. If I try to do the latter, I once again end up in an infinite recursion.

I tried to move the default language replacement part into a textformatter, but then the value gets replaced with the original one again. I'm at a loss.

Link to comment
Share on other sites

The recursion happens cause you get the field from pagr which triggers formatValue again. Maybe it's better to get the unformatted value getUnformatted(field) that will get the object with the languages inside or prevent recursion with a marker you set to the page to ignore them. Maybe also a after hook works better as there might be the language module song theit work too. Or set hook to after those of the language modules.

I'm still not sure what exactly you try to do and why.

Link to comment
Share on other sites

I'm still not sure what exactly you try to do and why.

Basically, I've got migrated articles in multiple languages. The body text in the default language (German) contains translation tags in the form of "{TR:Teil}: xxx.yyy.zzz - {TR:Gehäuse}". These TR tags need to be read, the text extracted, translated and  replaced (or, if accessed in the default language, just the tags stripped) so the page displays "part: xxx.yyy.zzz - housing" for English and "Teil: xxx.yyy.zzz -Gehäuse" for German.

There may be a body text in English as well, so relying on the "use text from default language if empty" feature is unfortunately not sufficient.

Link to comment
Share on other sites

Why don't you just build a textformatter instead of fiddling around with some hooks? These can be very simple compared to what the hanna code module looks like. Here is one I build recently: http://pastebin.com/Tc1sHvD2. I just don't know if this will play well with your vision of mixing and matching language fields with your own translation stuff. I can't really see, how you want this to work, as it seems like this stuff "{TR:Teil}: xxx.yyy.zzz - {TR:Gehäuse}" shouldn't be part of each language's text, but still kinda be part of each one.

Link to comment
Share on other sites

Thank you both, Soma and LostKobrakai. Textformatter and getUnformatted in combination were what I was missing! Here's the working code - short and to the point:

    public function formatValue(Page $page, Field $field, &$value)
        if( $page->isMultiLang == 1 )
            if( $this->user->language != 'default' )
                $value = $page->getUnformatted($field->name)->getDefaultValue();
            $value = preg_replace_callback('/\{TR:([^}]+)\}/', array($this, "translate"), $value);

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By Robin S
      Process Images
      A basic, proof-of-concept Textformatter module for ProcessWire. When the Textformatter is applied to a rich text field it uses Simple HTML DOM to find <img> tags in the field value and passes each img node through a hookable TextformatterProcessImages::processImg() method.
      This is a very simple module that doesn't have any configurable settings and doesn't do anything to the field value unless you hook the TextformatterProcessImages::processImg() method.
      Hook example
      When added to /site/ready.php the hook below will replace any Pageimages in a rich text field with a 250px square variation and wrap the <img> tag in a link to the original full-size image.
      For help with Simple HTML DOM refer to its documentation.
      $wire->addHookAfter('TextformatterProcessImages::processImg', function(HookEvent $event) { // The Simple HTML DOM node for the <img> tag /** @var \simple_html_dom_node $img */ $img = $event->arguments(0); // The Pageimage in the <img> src, if any (will be null for external images) /** @var Pageimage $pageimage */ $pageimage = $event->arguments(1); // The Page object in case you need it /** @var Page $page */ $page = $event->arguments(2); // The Field object in case you need it /** @var Field $field */ $field = $event->arguments(3); // Only for images that have a src corresponding to a PW Pageimage if($pageimage) { // Set the src to a 250x250 variation $img->src = $pageimage->size(250,250)->url; // Wrap the img in a lightbox link to the original $img->outertext = "<a class='lightboxclass' href='{$pageimage->url}'>{$img->outertext}</a>"; } });  
      GitHub: https://github.com/Toutouwai/TextformatterProcessImages
      Modules directory: https://processwire.com/modules/textformatter-process-images/
    • By Mike Rockett
      A ProcessWire wrapper for the awesome PHP Typography class, originally authored by KINGdesk LLC and enhanced by Peter Putzer in wp-Typography. Like Smartypants, it supercharges text fields with enhanced typography and typesetting, such as smart quotations, hyphenation in 59 languages, ellipses, copyright-, trade-, and service-marks, math symbols, and more.
      It's based on the PHP-Typography library found over at wp-Typography, which is more frequently updated and feature rich that its original by KINGdesk LLC.
      The module itself is fully configurable. I haven't done extensive testing, but there is nothing complex about this, and so I only envisage a typographical bug here and there, if any.
    • By daniel_puehringer
      Hi community,

      I am using the "PageTable" Module (also called "ProFields: Page Table") and the built in "Language" Module (also called "Languages Support").

      With the help of PageTable I was able to create several content elements which should usually be displayed in German(default language) and English.

      However some Content Elements should only be shown in German and NOT in English.

      Well sounds easy, right? Not so fast. I really love this CMS, but I have not found a solution for this problem yet.
      As you can see in the screenshots attached I tried to uncheck the "active" Checkbox for the english language to completely hide the content element for english users.

      However no matter what I do the german text shows on the english page.
      If I leave the "content-should-not-be-shown-in-english"(see Screenshot Number 2) blank and save the page, the page will inherit the german page url "content-element-with-simple-text-which-should-only-be-shown-in-german".

      My question therefore is:
      How can I hide a specific content-element for only one language?

      I´m using the latest processwire & module versions.

      The code which I use to render the content elements looks like this:
      //Info: contentelements is a field of type "ProFields: Page Table" <?php foreach ($page->contentelements as $element): echo($element->render()); endforeach; ?> filename: basic-page.php

      I would really appreciate your help since I haven´t found a solution after reading through quite a lot of forum posts.

      All the best,

    • By MoritzLost
      This is a textformatter module that will automatically replace titles of other pages on your site with links to those pages. For example, if you have a template glossary-term, and mention the exact title of one page using that template in a textfield, the title will be automatically linked to that page (if the textfield uses that formatter). This is good for SEO, and saves you some manual labour. You can configure which templates should get automatically linked, and of course the formatter is only active for the fields you add this formatter to. Note that if you need more manual control over when and where titles are automatically linked, you're probably better of using Autolink from a Glossary by @mr-fan.
      Allows you to limit the automatic links by template. Only includes published & visible pages by default, with an option to include hidden pages. Automatically excludes the current page, with an option to change that behaviour. Allows you to configure the minimum title length for linked pages. Doesn't overwrite existing links, and detects most edge cases (titles inside other tag's attributes, titles inside existing links et c.). Supports multi-language sites. Titles will only be linked if a title in the current language is set. Can add configurable attributes to all automatically created links. This includes the ability to use page fields as replacement patterns for attributes. For example, you can create CSS classes that include the name of the template of the linked page. Extensive options and hooks to change the generated markup completely. Need <mark> elements with a title attribute based on a page field instead of a link? No problem. See the example project below. Prefer oldest or newest page in the case of duplicate titles. Queries the database directly for improved performance. Has options to switch between case sensitive and case insensitive modes, and force case sensitive behaviour even for case insensitive database collations. Allows you to overwrite the module configuration via the API to call the module with different settings for different requirements on the same site. Download & Documentation
      The module is now available in the modules directory: https://modules.processwire.com/modules/textformatter-page-title-links/
      You can download & install it through the backend using the classname TextformatterPageTitleLinks.
      To install it manually, download or clone the module from the Github repository into your site/modules folder and install through the backend.
      The complete documentation can be found in the README in the repository. Make sure to check out the module configuration page after installing the module.
      PHP 7.1 or higher ProcessWire 3+ (it will probably work in older versions, I haven't tested those though). This is my first module, I hope it may become useful to some of you 🙂
      If you find any errors or have some other suggestions or feedback, let me know!
    • By Robin S
      File Info
      A textformatter module for ProcessWire. The module can add information to local Pagefile links in two ways:
      As extra markup before, within or after the link As data attributes on the link (handy if you want to use a Javascript tooltip library, for instance) Screenshots
      Module config

      Example of output

      Install the File Info module.
      Add the textformatter to one or more CKEditor fields.
      Add markup action (and general)
      Select "Add markup to links" Select the Pagefile attributes that will be retrieved. The attribute "filesizeStrCustom" is similar to the core "filesizeStr" attribute but allows for setting a custom number of decimal places. If you select the "modified" or "created" attributes then you can define a date format for the value. Enter a class string to add to the links if needed. Define the markup that will be added to the links. Surround Pagefile attribute names in {brackets}. Attributes must be selected in the "Pagefile attributes" section in order to be available in the added markup. If you want include a space character at the start or end of the markup then you'll need >= PW 3.0.128. Select where the markup should be added: prepended or appended within the link, before the link, or after the link. Add data attributes action
      Select "Add data attributes to links" Select the Pagefile attributes that will be retrieved. These attributes will be added to the file links as data attributes. Attributes with camelcase names will be converted to data attribute names that are all lowercase, i.e. filesizeStrCustom becomes data-filesizestrcustom. Hook
      If you want to customise or add to the attributes that are retrieved from the Pagefile you can hook TextformatterFileInfo::getFileAttributes(). For example:
      $wire->addHookAfter('TextformatterFileInfo::getFileAttributes', function(HookEvent $event) { $pagefile = $event->arguments(0); $page = $event->arguments(1); $field = $event->arguments(2); $attributes = $event->return; // Add a new attribute $attributes['sizeNote'] = $pagefile->filesize > 10000000 ? 'This file is pretty big' : 'This file is not so big'; $event->return = $attributes; });  
  • Create New...