Jump to content
valan

field label language problem

Recommended Posts

I've spent few hours at this problem, but still can't solve it -

// this code works not as expected - outputs only in default language, even if $user->language is different.
echo $user->fields->get("some_text_field")->label;

// while this code in the same php file works as expected - output follows $user->language
echo $page->any_field; 

Note: some_text_field field label is a multi-language field, all translations available.

If I try to do something like this:

echo $user->fields->get("some_text_field")->label->getLanguageValue($user->language);

it returns:

Error: Call to a member function getLanguageValue() on a non-object

Please, help - I want to output field label in current language! )) Thanks!

Share this post


Link to post
Share on other sites

Meanwhile, discovered why

echo $user->fields->get("some_text_field")->label->getLanguageValue($user->language)  

doesn't work. It is because $user->fields->get("some_text_field")->label returns string. Yes, I'm newbie )))

Still trying to find access to another translation in my field's label field... w/o success after another portion of experiments... 

Share this post


Link to post
Share on other sites

Hi valan,

I've found a solution. The translations of the labels (not default) are stored in the 'data' field in the 'fields' table, as JSON.

Example: {"label1012":"Weight"} where 1012 is the ID of the language.

You can try this code:

$label = 'label';
if ($user->language->name != 'default') {
  $label = "label{$user->language}";
}

// Output label in correct language
echo $user->fields->get('field')->$label;
  • Like 4

Share this post


Link to post
Share on other sites

WOW!!! It works!

Wanze, thank you for help! - I've started to think that problem doesn't have elegant solutions in PW. But you proved that PW has such solution! 

P.S. hope to see this kind of hints documented sometime by core PW team!

  • Like 2

Share this post


Link to post
Share on other sites
$label = 'label';
if ($user->language->title != 'no') {
$label = "label{$user->language}";
}

echo $page->fields->get('phone')->$label;

The above code works great on a regular php page, but I can´t get it to work inside a function - yes, yes - newbie :-)

function renderAuthorData($page) {

	$na = "<span class='na'>n/a</span>";
	$download = $page->files->first()->name;
	
	//Check if author is an employee
	$vista = $page->vista;
	if($vista == 1){
	
	$label = 'label';
	if ($user->language->title != 'no') {
	$label = "label{$user->language}";
	}
	
	$out =	"\n<table class='publication_data'>" .
	"\n\t<tbody>";
		
		//Check if author has a specific function
		if($page->function){
		$out .= "\n\t<tr><th>". ($page->fields->get('function')->$label) ."</th><td>". ($page->function ? $page->function : $na) . "</td></tr>";
		}
		
		$out .= "\n\t<tr><th>". ($page->fields->get('author_title')->$label) ."</th><td>" . ($page->author_title ? : $na) . "</td></tr>" .
				"\n\t<tr><th>". ($page->fields->get('phone')->$label) ."</th><td>" . ($page->phone ? : $na) . "</td></tr>" .
				"\n\t<tr><th>". ($page->fields->get('author_email')->$label) ."</th><td>" . ($page->author_email ? : $na) . "</td></tr>" .
				"\n\t<tr><th>". ($page->fields->get('address')->$label) ."</th><td>" . ($page->address ? : $na) . "</td></tr>" .
				"\n\t<tr><th>CV</th><td><a href='{$page->files->first()->url}'>" . $download . "</a> ({$page->files->first()->filesizeStr})</td></tr>" .
				"\n\t</tbody>" .
				"\n</table>";
		
	}else if($vista == 0){
	
	$out =	"\n\t<div style='clear:both;'><p>{$page->title} er ikke ansatt i Vista Analyse AS, men er medforfatter på følgende publikasjon(er):</p></div>";
	
	}	
	
	return $out;

	}

It would be great to check for $user->language from inside a function. Can anyone help me with this? Probably very easy for someone with more PHP knowledge than me....

(The slightly modified code is from Ryan´s Skyscraper Profile - I have spent a few hours "dissecting" that profile to make a site for client - will share next week in the forum)

Share this post


Link to post
Share on other sites

Hi Peter,

That's because all the API variables like $users, $page, $pages... are not known to the function. PHP - scope problem.

The solution is to use the global wire() function from Pw to get the API variables:

$vista = wire('page')->vista;
// ...
if (wire('user')->language->title != 'no')) {
// ...
  • Like 3

Share this post


Link to post
Share on other sites

Thanks Wanze,

I got the if statement to work, but not the rest...

$label = 'label';
if (wire('user')->language->title != 'no'){ //Works
$label = "label{wire('user')->language}"; //Doesn't work
}

Probably just a matter of correcting my syntax :-)

-Peter

Share this post


Link to post
Share on other sites

Solved it like this:

$lang = wire('user')->language;
$label = 'label';
if (wire('user')->language->title != 'no'){
$label = "label{$lang}";
}

Works great now

Share this post


Link to post
Share on other sites

I have problems rendering the correct field label for anything other than the default langauge.  (this in the template / frontend, not admin)

I'm using PW 2.3.2 dev version, and the values all output fine. It's just that the field labels only show the default language label text, nothing else.

Is there a special syntax I have to use? Or do I still have to manually check for $user->language somehow to get this done? I was under the impression it wouldn't be necessary anymore with 2.3.2. With 4 languages and approx. 50 custom fields, I'd really like to streamline things a bit (all field labels are correctly setup in each language). Or is that something that will be ready only with 2.4?

Share this post


Link to post
Share on other sites

I have a hard time to understand why one need the field labels (in different languages) in the front-end. After all if the it should render the language the user currently is viewing.

We covered this already in another thread and there's the solution above and I don't think there's something like you mention on the plan but maybe I miss something. But it would be easy to build a function or module to help out but there's barely anything needed to get a translated label.

$body = $fields->get("body");
$lang = $languages->get("de");
echo $body->get("label$lang"); // german label

Share this post


Link to post
Share on other sites

Thanks. I'll try that tomorrow morning.

The reason I need it in the frontend is simple: The various fields generate product specifications in the frontend, as lists or tables. Having to hardcode the field-labels for each addtl. language in the template, when it is already defined in the backend, seems unneccessary, tedious duplicate work. Most values are numeric, but the titles (labels) are always strings. I don't think it's that much of a rare / exotic situation.

After all, an english speaking visitor wants to see "weight", not "Gewicht". A French guy expects "poids", etc.

I have a hard time to understand why one need the field labels (in different languages) in the front-end. 

  • Like 1

Share this post


Link to post
Share on other sites

I understand and know this, but why do you need to get the translation when it is just already there. It will output in the language the user views the page ($user->language)

This works just fine in the language the user view the page.

echo $fields->get("body")->label;

Edit: ah, hm it does not? :)

Ok it doesn't get translated as with page fields. Since it's meant to be used for backend context there's no language value for fields settings.

So you either use a $lang variable like this:

$lang = $user->language->isDefault() ? "" : $user->language->id; // Default needs no id
echo $fields->get("body")->get("label$lang");

Or a little hook to add method to the $fields template API var. :)

// from template or a autoload module
$fields->addHook("getLabel", null, "getLabelLang");
function getLabelLang($event){
    $field = $event->arguments(0);
    $lang = wire("user")->language->isDefault() ? "" : wire("user")->language->id;
    $event->return = wire("fields")->get($field)->get("label$lang");
}

// now we use it and it will recognize user lang
echo $fields->getLabel("body");
 
  • Like 10

Share this post


Link to post
Share on other sites

Hooray! Thank you. I'm using your hook now in an include, and it works wonderfully.

Guess I'll have to get acquainted with hooks sooner or later...

Do you think this is worth suggesting in the Wishlist + Roadmap forum?

Share this post


Link to post
Share on other sites

I have a hard time to understand why one need the field labels (in different languages) in the front-end. After all if the it should render the language the user currently is viewing.

For me, it is because I have a hidden "about" section in my page. I have an about_title and about_description field, but to get to open this hidden "about" section, I have a button labeled "about"/"(about in chinese)". I don't want to have to create whole 'nother field just for "about_button". This is why I wanted to just use the label name for my field, which I already have translated.  I searched and found this thread extremely helpful ^^

I am so glad that this thread popped up just as I encountered the same problem. You guys are awesome  :lol: 

Share this post


Link to post
Share on other sites

Dear all,

I know this post is old, but in case someone else stumbles across it, here is a modified version of Soma's getLabel() hook which takes an optional second parameter to decide if you want a fallback to the default language if no localized name of that field is available:

$fields->addHook("getLabel", null, "getLabelLang");
function getLabelLang($event){
    $field = $event->arguments(0);
    $fallback = $event->arguments(1) === null ? true : $event->arguments(1);
    $lang = wire("user")->language->isDefault() ? "" : wire("user")->language->id;
    $field = wire("fields")->get($field);
    $caption = $field->get("label$lang");
    $caption = (count($caption) === 0 && $fallback) ?  $field->get("label") : $caption;
    $event->return = $caption;
}

Usage:

$fields->getLabel("labelName");

-> returns the localized label name with fallback to default language.

$fields->getLabel("labelName", false);

-> returns the label name without fallback to default language.

I am not very good with php, any code improvements welcome!  :)

  • Like 2

Share this post


Link to post
Share on other sites
On 16. November 2015 at 5:36 AM, lenno said:

I know this post is old, but in case someone else stumbles across it, here is a modified version of Soma's getLabel() hook which takes an optional second parameter to decide if you want a fallback to the default language if no localized name of that field is available:

Thanks a lot! ??

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 ICF Church
      Hi 👋
      Anyone else having this problem?
      Requirements:
      - Repeater (matrix & normal) with mutlilanguage fields (text, textarea…) 
      - Backend language set to something other than default (ie. German) 
      Reproduce:
      - Add a new repeater Item (ajax, I found no way to possible to disable it with matrix)

      (Notice how the default language tab is active instead of the backend language…)
      - Write something into the (default language) field
      - Try to save, if field is required, this will not work. If not required, then when reloading, the content will be inside the backend language field, instead of the default language field who was (presumably) active
      Analysis:
      When  loading  a new repeater element with ajax, the default langue tab is active, but the backend language inputfield is visible (with no visual indication). When writing into the field, it will populate the backend language. When manually clicking on the default language tab (which is already active), the field will switch to the actual default language field (which is [now] empty) (that can now be populated…)
      Also Notice, the labels of the elements to be added are in default language as well instead of the translated label (images instead of Bilder)…
      ProcessWire 3.0.148, Profields 0.0.5…
      Is it my system configuration, or does anyone else have the same issue? This is a screen recording of the problem:

      Screen Recording 2020-02-25 at 14.18.31.mov
    • By snobjorn
      Here's my Norwegian language pack for ProcessWire. I've been adding translations over some time, to suit my own projects users needs.
      Last updated:
      2019/06/19 (June 19, 2019)
      Status:
      Not yet complete. Translations that non-superusers will see is prioritized.
      Name:
      ProcessWire-Norwegian-Language-Pack-nb-NO
      Translated using:
      ProcessWire 3.0.133 dev
      Number of files:
      189 wire files and 95 site files – ranging from just started to completely translated. The site files includes translation some free and some pro modules, see the complete list in the README.md at GitHub.
      Available at GitHub:
      https://github.com/snobjorn/processwire-norwegian-language-pack-nb-no
    • By louisstephens
      Hopefully this is the right place, if not, please move it to the proper sub. I installed the multi language module on my development (sandbox) set up not too long ago to test out a few things. From the start, I ran into some issues with dependencies not being met/installed, so I thought that I would simply just uninstall what had been. Unfortunately, that took me down a road of using some code in my home template to remove the modules (cant find it at the moment). After some struggling, I finally got it uninstalled, but it left behind 3 fields,
      language language_files language_files_site I thought that I could simply remove them from the languages template and then delete them, but I get the following error:

      I was wondering, is there a way to remove these using the api? I couldn't add any new users to the setup until I made "language" not required, but I was hoping to just remove all of the fields.
    • By bartelsmedia
      "Deepl" is an unbelievably good (paid) text translation service, that mops the floor with Google Translate.
      They have an API and it would be awesome, if there would be a module, that would integrate it for easy content translation.
      It could be a right-click context menu on the language tab:

      It should ask from which of available other language it shall take translate from.
      What do you think?
    • By Gadgetto
      Hello,
      I'm very new to ProcessWire but already fell in love with this CMS/CMF! I just finished my first small project and as I saw a lot of questions and different answers in this forum on how to set up a nice language switcher for your website, I decided to write my first tutorial.
      ----------
      Please note:
      I rewrote this tutorial since I was made aware and learned that flags should not be used for language selectors!
      There are some threads here in the forum (and from external sources) where this question is discussed:
      https://processwire.com/talk/topic/13196-adding-image-field-to-language/
      http://daily.unitedlanguagegroup.com/stories/editorials/inside-design-language-selector-no-flags
      https://processwire.com/talk/topic/16524-extending-languages-template/
      http://www.flagsarenotlanguages.com/blog/why-flags-do-not-represent-language/
      https://processwire.com/talk/topic/14241-language-names-and-utf8-page-names/
      Thanks,
      @ottogal
      @bernhard
      @jmartsch
      @kongondo
      an all others for your hints!
      ----------
       
      TUTORIAL - Set up a nice language switcher for your website - here we go:
       

      This will be the desired result!
       
      Step 1)
      Setup at least 2 languages in your PW install. In my case it's German (default language) + English:
       

       
      Step 2)
      Add a custom field
      Type = Text
      Name = languagecode
      This will hold the ISO 639-1 two-letter language code for the respective language. The field is needed to provide a simple method for outputting the language code in your templates. Without this field, you will need to programmatically construct your two-letter language code output via PHP (at least for the default language, as ProcessWire doesn't allow to rename the default language and it will always be called default).
      Here is an overview for ISO 639-1 two-letter language codes:
      https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
       

       
      Step 3)
      Add this field to the system template: language.
      To achieve this, go to Setup / Templates and activate the filter Show system templates:
       

       
      Now you can add the previously created field languagecode to the language template.
       

       
      Step 4)
      Edit your languages and fill in the appropriate values.
      a) default (German)
      Name = default (this can't be changed and is read only)
      Title = Deutsch (in both language tabs! - this is important as your visitor should always see his language item ... in his language)
      languagecode = de
       

       
      b) english (English)
      Name = english
      Title = English (in both language tabs! - this is important as your visitor should always see his language item ... in his language)
      languagecode = en
       

       
      Step 5)
      Now we are ready to write our template output!

      As we already have the appropriate two-letter ISO language code (languagecode field), we can use this in our html lang property:
       
      <html lang="<?php echo $user->language->languagecode; ?>">  
      Also the rel alternate output in the html head is simple. Put the following code within your <head></head> area:
       
      <?php // Handle output of 'hreflang' link tags for multi-language (SEO!) foreach ($languages as $language) { if (!$page->viewable($language)) { continue; } // Get the http URL for this page in the given language $url = $page->localHttpUrl($language); // Get the language code using custom languagecode field $languagecode = $language->languagecode; echo PHP_EOL.'<link rel="alternate" hreflang="'.$languagecode.'" href="'.$url.'">'; } ?>  
      In my sample I've used Boostrap 4 and the code below shows a complete navbar with our language switcher (BTW the language switcher will always be visible, even when the bootstrap navbar is collapsed):
       
      <nav id="mainnav" class="navbar navbar-expand-lg navbar-light px-4 px-md-5 sticky-top"> <a class="navbar-brand" href="<?php echo $config->urls->root; ?>"> <img src="<?php echo $config->urls->templates; ?>images/logo-rund-80x80.png" alt=""> Your Site Title </a> <ul class="navbar-nav ml-auto mr-3 mr-lg-0 order-lg-last d-none d-xs-custom-flex language-switcher" aria-label="<?php echo __('Sprache wechseln') ?>"> <?php echo '<li class="nav-item dropdown">'; // Construct the language prompt in the current user language $prompt = $user->language->title.' ('.strtoupper($user->language->languagecode).')'; // Current language = dropdown-toggle echo '<a class="nav-link dropdown-toggle" href="#languages" id="language-select" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">'; echo '<span class="world-icon"></span><span class="sr-only">'._x('(aktuelle Sprache)', 'navigation').': </span> '.$prompt; echo '</a>'; echo '<div id="languages" class="dropdown-menu dropdown-menu-right" aria-labelledby="language-select">'; foreach ($languages as $language) { // Get the http URL for current page in the given language $url = $page->localHttpUrl($language); // Construct the language prompt in the given language $prompt = $language->title.' ('.strtoupper($language->languagecode).')'; // Next language item (except current language) if ($user->language->id != $language->id) { if (!$page->viewable($language)) { echo '<span class="dropdown-item disabled">'.$prompt.'</span>'; } else { echo '<a class="dropdown-item" href="'.$url.'">'.$prompt.'</a>'; } } } echo '</div>'; echo '</li>'; ?> </ul> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarMainMenu" aria-controls="navbarMainMenu" aria-expanded="false" aria-label="<?php echo __('Menü einblenden / ausblenden') ?>"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse my-3 my-lg-0" id="navbarMainMenu"> <ul class="navbar-nav mr-auto"> <?php // Top navigation consists of homepage and its visible children foreach ($homepage->and($homepage->children("template=main-page|news|contact-points")) as $item) { if ($item->id == $page->rootParent->id) { echo '<li class="nav-item active">'; echo '<a class="nav-link" href="'.$item->url.'">'.$item->title.'<span class="sr-only"> '._x('(aktuelle Seite)', 'navigation').'</span></a>'; echo '</li>'; } else { echo '<li class="nav-item">'; echo '<a class="nav-link" href="'.$item->url.'">'.$item->title.'</a>'; echo '</li>'; } } ?> </ul> </div> </nav>  

      That's it! I hope you will like my tutorial and if there are any questions, critics or improvements please let me know!
      Thanks,
      Martin
       
×
×
  • Create New...