Jump to content

Search in multilanguage site with multilang fields


seddass
 Share

Recommended Posts

Hi all,

Hope that there is a quick tip that someone already know...

Is it possible to search in multilanguage fields only in the current language values without to search in the default language as fallback? See the quote below.

We will assume that the current user's language is Dutch and that this is a language installed in the system. We will also assume that the field "body" is a multi-language textarea field. Because the user's current language is Dutch, the following API call matches any pages that contain the phrase "welkom vrienden" (welcome friends) in the Dutch body field OR the default body field. If there are other languages installed, it does not attempt to search them.

In other words.. I would like to search only in the current language (Dutch), no matter if some of the Dutch language values are empty. Is it possible?

Thanks

Link to comment
Share on other sites

Not technically a supported feature at present, but I think you can get the result you want. You'd take a query like this:

$pages->find("body*=something");

and convert it to this:

$pages->find("body.data{$user->language}*=something"); 

That should return just the pages that match the current user's language, rather than including the default language.

  • Like 3
Link to comment
Share on other sites

  • 5 months later...

Not technically a supported feature at present, but I think you can get the result you want. You'd take a query like this:

$pages->find("body*=something");

and convert it to this:

$pages->find("body.data{$user->language}*=something"); 

That should return just the pages that match the current user's language, rather than including the default language.

Sorry to dig this up, but I've followed these instructions, changing:

$matches = $pages->find("title|body|sidebar*=$q, limit=50, id!=1"); 

to

$matches = $pages->find("body.data{$user->language}*=$q, limit=50, id!=1"); 

and the following error shows up:

Error Exception: Unknown column 'field_body.data1029' in 'field list' (in /home/v3maran/public_html/wire/core/Database.php line 118)

Any clue why this is happening? I am using the built in multilanguage module. Thank you.

Link to comment
Share on other sites

(Edit: This just got deprecated ;), but I'll still leave it here - see "Part 2").

Go and see Setup -> Fields -> body. What's the type of the field?

I'm guessing it's "Textarea" as there doesn't seem to be fields for different languages in the database. That kind of selector would work only for fields of type *Language, "TextareaLanguage" in this case most likely.

You can change the type safely, but still after that for the selector to work in a reasonable way you'd have to input some content in the very language you're using in your search. But that was actually what you must have been trying to do anyway. :)

(..a few hours later..)

Part 2

Had another idea a bit later and while the earlier explanation could have been right, there's another possibility as well. And I think this is much more probable than the first one as I can't understand why you'd be using a selector like that if you didn't already have actual multilingual data in there - stupid me.

So now I'm thinking 1029 is the id of you default language (see Setup -> Languages -> default - what's the value of id parameter?). That special kind of selector would only work for languages other than the default one as its field is named just "data", not "data1029" for instance. So when the language is set to default ($user->language->name == 'default'), you'd have to use a regular selector without the ".data{$user->language}" part (or just ".data" without the id, I think).

Next part will follow in the morning - hope not.

Edited by nik
  • Like 2
Link to comment
Share on other sites

Nik is right about this. You probably want to change your selector to something like this:

$field = $user->language->isDefault() ? "body" : "body.data" . $user->language; 
$matches = $pages->find("$field*=$q"); 

That will force it to not consider the default language in the matches at all.

However, most of the time you should just do this, which already takes languages into account:

$matches = $pages->find("body*=$q"); 

So whether the user searches for "Beer" or "Cerveza" they will still get to the right page. If you exclude the default language, then that fallback never happens.

  • Like 5
Link to comment
Share on other sites

Thanks for both answers. My content fields are all multilanguage and work perfectly with everything else.

I implemented the changes Ryan pointed out and the error is gone. However, now the language resets always to the default one. I type the string, hit the button and the language changes back and displays results on that specific language.

You can check it here: http://maran.pt/

Try searching in portuguese (default) for "armario" and then, in english for "locker".

Link to comment
Share on other sites

I have that set in the header, it should load properly. However, I may have another loophole when I build the search form:

<form id='search_form' action='<?php echo $config->urls->root?>pesquisa/' method='get'>

The 'pesquisa' is the name of the search page. I believe this should change in order to get the /pt/ or /en/ after it, right?

Link to comment
Share on other sites

I think this will just depend on how and where you are setting the language. You'll want to make sure you are setting $user->language somewhere before your search (and before any output).

I now realized that part. Search.php treats things differently, so I would need to set the language before the output construction. However I am still unaware on how to achieve this since I tried to use the head.inc language related code lines, and nothing resulted from that. Here's what I have:

$lang = $user->language;
$langname = $lang->name == 'default' ? 'pt' : $lang->name;

I make no sense of this because I don't think it is setting anything (just storing the current languag in variables for further use), but everything else works. How can that be? I am confused now... ???

Link to comment
Share on other sites

When switching to language en, the search form is not changing it's action url.

<form id='search_form' action='/pesquisa/' method='get'>
 <input type='text' name='q' id='search_query' value='' />
 <button type='submit' id='search_submit'>Search</button>
</form>

When I manually enter http://maran.pt/en/search/?q=locker it seems to work.

  • Like 1
Link to comment
Share on other sites

Yes, Soma, I agree with you on that. I believe I have to place the language alias before. And about that, I have a question that is connected to this problem. When I want to link to a page, instead of typing the URL with the normal name, I would like to get the URL depending on the language I am at. Here's what I do, but I think this solution is not vert elegant...

$homepage = $pages->get("/");
$children = $homepage->children->find("name=pagename");
$child = $children->first();

Then I use $child->url for the url's link. Is there a easier way?

Link to comment
Share on other sites

  • 1 year later...

1.

$field = $user->language->isDefault() ? "body" : "body.data" . $user->language; 
$matches = $pages->find("$field*=$q"); 
2.
$matches = $pages->find("body*=$q");

WOW! The first one just made my day..thank you!!  :)

The second one is not working for name field is that correct?

Couldn't get it working $pages->get("name*=$q") it's only getting default language (find-> wasn't working for me neither)?

Link to comment
Share on other sites

  • 4 years later...
On 9/30/2012 at 6:00 PM, ryan said:

Nik is right about this. You probably want to change your selector to something like this:


$field = $user->language->isDefault() ? "body" : "body.data" . $user->language; 
$matches = $pages->find("$field*=$q"); 
 

That will force it to not consider the default language in the matches at all.

However, most of the time you should just do this, which already takes languages into account:


$matches = $pages->find("body*=$q"); 
 

So whether the user searches for "Beer" or "Cerveza" they will still get to the right page. If you exclude the default language, then that fallback never happens.

Hey,

I just wanted to say that this kind of functionality is super important for many websites. I just spend three hours looking for a solution until I stumbled on this. Seriously consider adding it to the documentation.

Now I can easily show only news item that actually has content in the relevant language.

  • Like 2
Link to comment
Share on other sites

  • 1 year later...

Maybe it is worth rethinking this implementation? When checking is a field is empty or not, for example, fallback to default is a bug. The hack solution is kinda ugly and unintuitive.
And one of PW's strongest points is multi-language support. What do you think,  @ryan?

P.S. I just tried it out one more time. It seems that if you check if the field is empty using just the field name, it checks only the default language. So if the field has text in user lang but not in default, the check is falsely false. So might be a real bug here.

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
 Share

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Guy Incognito
      We have a client's Processwire site where the Pageimage::size() method has stopped working. It's creating small white PNGs in the assets folder instead of the resized image as usual.
      Their hosting was recently upgraded and switched to PHP 7.4 and I'm wondering if a they've removed a PHP package or changed a server config to cause this.
      Does anyone know if the image resizing functionality requires specific PHP modules I need to check for?
      I've checked the folder permissions on the server - this all looks fine.
      TIA,
      J
    • By Cesco
      Hi is possible to hide FieldsetTab if page has field set to certain value?
      It's possible for other field type by Input->Visibility->if... but not for FieldsetTab. 
      Thanks
      Francesco
    • By ErikMH
      So, if I do this right at the top of a template PHP file:
      <?php namespace ProcessWire; function myFunction() { global $config; echo $config->dateFormat; }; ?> I, predictably, get this in my front end (once I figured out about the necessary global $config; line):
      Y-m-d H:i:s Happy camper. But if I try to access $session variables in the same way:
      <?php namespace ProcessWire; function myFunction() { global $session; echo $session->future; }; ?> I’m told there is no $session object; it responds exactly as if I hadn’t included the global $session statement:
      PHP Notice: Trying to get property 'future' of non-object in .../public/site/templates/home.php:5 I thought the problem might conceivably have to do with my private variables, so I tried the provided hasCookie() method:
      <?php namespace ProcessWire; function myFunction() { global $session; print_r($session->hasCookie()); }; ?> With essentially the same result:
      Error Call to a member function hasCookie() on null $session variables and methods are fully accessible and work exactly as expected if placed immediately outside of myFunction().
      I am rapidly running out of hair. Is this intentional? Or a bug? Can anyone confirm that they see this behavior? Can anyone think of a workaround? Thanks!
      ProcessWire: 3.0.179
      PHP: 7.4.19
       
    • By prestoav
      Hi all,
      I could have sworn I used to be able to use the site generic 'title' field as a sub field of a repeater field. However I've tried to do this on two 3.0.165 sites recently and, while it will add the title field in the repeater field setup, it wont save the repeater title sub field's content when the repeater is used in a page template and edited.
      It;'s not a big issue but I wondered if this was a known restriction?
    • By spercy16
      I was previously using individual fields to capture and output multiple cards onto my web page but after recently learning about repeaters would prefer to use this field type, as it will be a lot more user friendly for end users to create new cards. I tried to modify my code to grab the fields from the new Repeater field(s) but am getting this error message on the page:
      Here is the code I'm currently trying to use for the cards:
      <?php // https://processwire.com/api/arrays/ // check if the array of images has items foreach($page->tall_card as $card) { $count = 0; $count++; $options = array( 'quality' => 70 ); $image = $card->image; $img = $card->image->size(550, 400, $options); $cardHeading = $card->title; $cardBody = $card->plain_paragraph; $raised = $card->raised_amount; $goal = $card->goal_amount; $link = $card->link; if ($raised == 0 ) : $percent = 0; else: $percent = $raised_amount / $goal_amount * 100; endif; if ($percent <= 5) : $percent = 0; endif; ?> <span id="card<?php echo $count?>" class="card"> <img class="cardThumb" src="<?php echo $img->url; ?>" alt="<?php echo $image->description; ?> Thumbnail" /> <div class="cardBody"> <div class="cardText"> <h2><?php echo $cardHeading; ?></h2> <?php echo $cardBody; ?> </div> <div class="progressBarSection"> <progress class="progressBar" id="progressbar<?php echo $count; ?>" value="<?php echo $percent; ?>" max="100"></progress> <span class="raisedAmount"> $<?php echo $raised; ?> usd </span> <span class="goalAmount"> $<?php echo $goal; ?> usd </span> </div> <div class="primaryBtn"> <a href="https://www.paypal.com/donate?hosted_button_id= <?php echo $link; ?> &source=url"> <button> <i class="fas fa-donate"></i> Donate </button> </a> </div> </div> </span> <?php } ?> Thanks in advance for any help!
×
×
  • Create New...