Jump to content
seddass

Search in multilanguage site with multilang fields

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

Share this post


Link to post
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

Share this post


Link to post
Share on other sites

Great! Thanks, Ryan!

I am still amazed of the power of the selectors engine.

  • Like 1

Share this post


Link to post
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.

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.

Share this post


Link to post
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

Share this post


Link to post
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

Share this post


Link to post
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".

Share this post


Link to post
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).

Share this post


Link to post
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?

Share this post


Link to post
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... ???

Share this post


Link to post
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

Share this post


Link to post
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?

Share this post


Link to post
Share on other sites

Well what multilanguage setup are you using there? Any modules?

Well the language switch links are already right. How are you generating the url on them or also on the navigation?

Share this post


Link to post
Share on other sites

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)?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
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 Pip
      Hi Everyone!
      I'd like to set a different label on my Title (PageTitle) field in one particular template.  Is there a way to do so? 
      Thanks. 
    • By benbyf
      Hello, and welcome to what I though was either my client being silly and changing things, or some evil doer. Turns out its reproducible and therefore something in Proceswire (I checked my templates and modules but couldnt find anything that would be doing this...). So what is it doing? Check out the video for evidence.
      A repeater field is interacting with a page template and another repeater field somehow to swap the fields in the template and repeater over...
      I have a template called team, and a repeater field called team_repeater with label Team. Some how and for some reason, when I change my fields on repeater called main_menu_links my team template gets those fields and when I try and revert the team template fields to the fields it should have, they get given to the repeater main_menu_links. Also this to say HELP!!!!!
      video: https://www.dropbox.com/s/exkdhc6n7x0xpsa/strange-repeater-PW-mega-bug.mov?dl=0
    • By nabo
      Hello
      this is my snippet
      public function init() { if($this->wire('user')->isSuperuser()) { $this->wire()->addHookAfter('ProcessPageEdit::buildFormSettings', $this, 'buildForm'); $this->wire()->addHookBefore('ProcessPageEdit::processInput', $this, 'saveForm'); } } public function buildForm(HookEvent $event) { $p = $event->object->getPage(); $inputfields = $event->return; $fieldset = $this->wire('modules')->get("InputfieldFieldset"); $fieldset->attr('id', 'my_fieldset'); $fieldset->label = __("My Renders"); $fieldset->collapsed = Inputfield::collapsedYes; $field = $this->wire('modules')->get("InputfieldTextarea"); $field->attr('name', 'renders'); $field->attr('value', $p->renders); $field->label = $this->_('Renders'); $fieldset->append($field); $inputfields->append($fieldset); } public function saveForm($event) { $page = $this->pages->get($this->input->post->id); $page->set('renders', $this->input->post->renders); } It builds correctly the inputs, I edit the field renders but when I save the page the value of this inputfield remain blank.
      What's wrong?
    • By carlitoselmago
      I'm building a fieldtype/inputfield to visually select a grid like Bootstrap since it's the first time coding such thing, I'm basing my code in FieldtypeColorPicker since the base structure is the same, a graphical UI helper to finally output a string as value.
      The problem is I try to save the value as something like "1,2,3" referencing the index of each column selected but it gets converted as an int value so "1,2,3" becomes "1" if input random text it gets converted as "0".
      Here is the code:
      https://github.com/carlitoselmago/FieldtypeGridSpace
      Here's an screenshot of how it looks

    • By snobjorn
      I have a website with multiple content types that I want to be accessible through search. I really like the live search on processwire.com, that sorts content types while typing. I tried to find the code to recreate this, with no luck. Does anyone know if this is jquery, specific jquery plugins, json/xml cached files, and what kind of PHP code is used? Any tip that point me in the right direction would be much apperciated.
      The search result listing seems fairly easy to create with sorting through parameters.
×
×
  • Create New...