Multilang page restrict structur field

Hello,

Is it possible in a multi-lang-page to restrict a structure field to only one language?

Greetings perry

Yes, you can set translate: false but as far as I know this only works on the structure field level, not for individual fields inside the structure field.

there is no connection to the individual entries. By that I mean if I create three entries A B C in the DE version, I will not find them in the FR version. Therefore my idea in the structur field not to allow the multilanguage.

another approach would be to merge the content of the different languages in the template. how can i get the content of a specific language ?


<?php $events = []; ?>
<?php foreach ($pages->find('mitglieder')->children()->published() as $article) : ?>

	<?php
	$sd = $article->dates()->toArray();

	foreach ($sd['dates']->toStructure() as $dates) : ?>

		<?php
		array_push($events, [
			"username" => $article->title(),
			"date" => strtotime($dates->date()),
			"title" => $dates->title(),
			"location" => $dates->location(),
			"city" => $dates->city(),
			"website" => $dates->website(),
			"festival" => $dates->festival(),
			"canton" => $dates->canton()
		]);
		?>

	<?php endforeach ?>
<?php endforeach ?>

To be honest, I don’t understand what you are trying to do in your code snippet, nor how it relates to your original questions.

What is in the dates() field here, or what does $sd return?

And regarding your original question: Can you please rephrase and explain exactly what your are trying to achieve?

the snippet is the part in the template which I use to display the structure field content. however, it will still be filtered depending on your language choice.

I guess it’s not possible to limit a structur field in a multilang page to one language. That’s why I’m trying to merge the struturfield entries of all languages in the template.

As already mentioned above, you can set the translate option to false for a complete structure field, example:

        fields:
          social:
            label: On the web
            type: structure
            translate: false
            columns:
              platform: true
            fields:
              platform:
                label: Platform
                type: text
                width: 1/2
              url:
                label: URL
                type: url
                width: 1/2

This will then prevent the structure field from being translated and will show a disabled field in non-default languages:

And will show the default language content in all languages.

Since most users only enter content in their own language, I would force them with translate: false to switch to the default language . it is therefore better to look for the solution in the front-end and to merge the content.

Fair enough, was just answering your original questions.

To get the content of a specific language, pass the language code to the content() method, example:

$somefield = $page->content('en')->get('somefield');
2 Likes

What I’ve tried doesn’t seem to work?

I try to check whether the content file (txt) exists in the respective language, if so then loop over the structur field.

What am I doing wrong?

Maybe that’s the problem: The “mitglieder” pages are “users” that become content pages with a model.

<?php foreach ($pages->find('mitglieder')->children()->published() as $article) : ?>

	<?php

	if ($article->content('de')->get("dates")->exists()) :
		$sd = $article->dates()->toArray();

		foreach ($sd['dates']->toStructure() as $dates) : ?>


			<?php
			array_push($events, [
				"username" => $article->title(),
				"date" => strtotime($dates->date()),
				"title" => $dates->title(),
				"location" => $dates->location(),
				"city" => $dates->city(),
				"website" => $dates->website(),
				"festival" => $dates->festival(),
				"canton" => $dates->canton()
			]);
			?>

	<?php endforeach;
	endif;


	?>


	<?php
	if ($article->content('fr')->get("dates")->exists()) :
		$sd = $article->dates()->toArray();

		foreach ($sd['dates']->toStructure() as $dates) : ?>


			<?php
			array_push($events, [
				"username" => $article->title(),
				"date" => strtotime($dates->date()),
				"title" => $dates->title(),
				"location" => $dates->location(),
				"city" => $dates->city(),
				"website" => $dates->website(),
				"festival" => $dates->festival(),
				"canton" => $dates->canton()
			]);
			?>

	<?php endforeach;
	endif;

	?>


	<?php
	if ($article->content('it')->get("dates")->exists()) :
		$sd = $article->dates()->toArray();

		foreach ($sd['dates']->toStructure() as $dates) : ?>


			<?php
			array_push($events, [
				"username" => $article->title(),
				"date" => strtotime($dates->date()),
				"title" => $dates->title(),
				"location" => $dates->location(),
				"city" => $dates->city(),
				"website" => $dates->website(),
				"festival" => $dates->festival(),
				"canton" => $dates->canton()
			]);
			?>

	<?php endforeach;
	endif;

	?>



<?php endforeach ?>

Well, you are not checking if the content file exists but if the field exists, which is two different things. Also, if the pages are virtual pages, they don’t have a content file anyway, unless you have also redefined the content file method.

This condition will usually be true, because the field exists even if empty. And it will not be empty in the non-default languages if the field is not empty in the default language. But the question is if this is even important, because you can filter by unique events in the end.

What you haven’t answered is what $sd = $article->dates()->toArray(); returns. I don’t understand what you are doing there and if it is part of the issue or not.

What you haven’t answered is what $sd = $article->dates()->toArray(); returns. I don’t understand what you are doing there and if it is part of the issue or not.

beacause my model looks like that:


<?php

class MembersPage extends Page
{
  public function children()
  {
    $usersPages = [];
    $users      = kirby()->users();
    foreach ($users as $key => $user) {
      $userPages[] = [
        'slug'     => Str::slug($user->username()),
        'num'      => $user->indexOf($users),
        'template' => 'member',
        'model'    => 'member',
        'content'  => [
          'title'    => $user->username(),
          'role'  => $user->role(),
          'type'    => $user->member_type()->value(),
          'street'    => $user->street(),
          'city'    => $user->city(),
          'zip'    => $user->zip(),
          'website'    => $user->website(),
          'about'    => $user->about(),
          'userid'    => $user->id(),
          'cover'    => $user->cover()->yaml(),
          'canton'    => $user->canton(),
          'dates'  => $user->dates(),
          'blackboard'  => $user->blackboard()
        ]
      ];
    }
    return Pages::factory($userPages, $this);

  }

}

That doesn’t explain what dates or $user->dates() is.

“dates” is the structure field

dates:
        label:
          de: Spielplan
          fr: Spielplan
          it: Spielplan
        type: structure
        fields:
          title:
            label: 
              de: Titel
              fr: Titel
              it: Titel
            type: text
            required: true
          date:
            label: Date
            type: date
            default: today
            time: true
          canton:
            label: 
              de: Kanton
              fr: Canton
              it: Cantone
            type: select
            required: true
            translate: true
            options:
              AG: AG
              AI: AI
              AR: AR
              BE: BE
              BL: BL
              BS: BS
              FR: FR
              GE: GE
              GL: GL
              GR: GR
              JU: JU
              LU: LU
              NE: NE
              NW: NW
              OW: OW
              SG: SG
              SH: SH
              SO: SO
              SZ: SZ
              TG: TG
              TI: TI
              UR: UR
              VD: VD
              VS: VS
              ZG: ZG
              ZH: ZH
          location:
            label:
              de: Veranstaltungsort
              fr: Veranstaltungsort
              it: Veranstaltungsort
            type: text
            width: 1/3
          city:
            label:
              de: Ortschaft
              fr: Ortschaft
              it: Ortschaft
            type: text
            width: 1/3
          website:
            label: 
              de: Website
              fr: Website
              it: Website
            type: url
            width: 1/3
          festival:
            label: 
              de: Festival
              fr: Festival
              it: Festival
            type: checkboxes
            width: 1/3
            options:
              - Festiva

l

What I don’t understand is how you can only display the content of a field that exists in the specific language without displaying the default language.

$dates->content("it")->get("title"),

so i get the content of the default language

What I want to do is loop through the structure field in the respective language and only save it in an array if there is content (without failback default language).

at the end i have an array with all entries of the structure fields and can display them regardless of the selected language.

But then this line is superflous.

Just call to structure on the dates field:

foreach ($article->dates()->toStructure() as $dates) : ?>

without first creating an array from the dates.

okay, the problem is with the model

from
'dates' => $user->dates(),

to

      'dates'  => $user->dates()->yaml(),

now I can use toStructure directly

With this snippet I should now get back the content of the structure fields of all languages, but unfortunately that doesn’t work.
I am not getting any content back.
:woman_shrugging:
Am I making a mistake in thinking or why doesn’t it work?

	<?php $events = []; ?>
<?php foreach ($pages->find('mitglieder')->children()->published() as $article) : ?>
	<?php

	foreach ($kirby->languages() as $language) :
		foreach ($article->content($language->code())->get("dates")->toStructure() as $dates) :


			array_push($events, [
				"username" => $article->title(),
				"date" => strtotime($dates->date()),
				"title" => $dates->title(),
				"location" => $dates->location(),
				"city" => $dates->city(),
				"website" => $dates->website(),
				"festival" => $dates->festival(),
				"canton" => $dates->canton()
			]);

		endforeach;
	endforeach;

	?>

<?php endforeach ?>

The problem I still see here is that you haven’t defined any translations in your page model, but just the content array.

why is that necessary? If you change the language in the front-end, the content appears in the selected language, so the information must also be accessible from the template. This is also okay for the remaining fields, but not for the structure field because I want to display the content of all languages independently which language was selected by the user.

maybe it’s easier to understand if you see the site live: Figurentheaterszene | Intro

the contents of:

are contents of the user profile of the user

the setting is not perfect a coder with more kirby knowledge might have solved it a little smarter, but the site has been online for 2 years and can be traded by the members so far.