Virtual page from field, with translation

Hello,

In this site, there are some pages that contain a single text block, such as ‘privacy’ or ‘terms and conditions’. I’d rather have these texts in a single field, at site level, within a tab in the panel, than create a page for each of them, and have them next to main site sections.

So I turn to virtual pages. My reasoning is, I create a simple virtual page for ‘/privacy’ and within its ‘content’ I grab the text from $site->privacyText() or similar. But I also need translations, so perhaps something like:

return [
  'routes' => [
            [
                'pattern' => '(:any)/privacy',
                'action'  => function () {
                    return Page::factory([
                        'slug' => 'privacy',
                        'template' => 'privacy',
                        'translations' => [
                            'en' => [
                                'code' => 'en',
                                'content' => [
                                    'title' => 'Privacy',
                                    'text'  => site()->content('en')->privacy()
                                ]
                            ],
                            'es' => [
                                'code' => 'es',
                                'content' => [
                                    'title' => 'Privacidad',
                                    'text'  => site()->content('es')->privacy()
                                ]
                            ],
                            'ca' => [
                                'code' => 'ca',
                                'content' => [
                                    'title' => 'Privacitat',
                                    'text'  => site()->content('ca')->privacy()
                                ]
                            ],
                        ],
                    ]);
                }
            ]
        ]
];

…would this be correct? should I be using content() like that? or should I use translation()? Is there a simpler way ? Can I actually query a field within the content of a virtual page?

Does that fallback to default lang in case there is no such content in that lang? If not, how to?

Thank you

After trying it, the previous code does not seem to work as expected.

Specifically I can’t seem to be able to change language in this page, may be related to the (:any) in the route?

A bit lost.

My virtual page was wrong for multilang, this code works in config:

<?php 
    return [
        'languages' => true,
        'routes' => [
            [
                'pattern' => '(en|es|ca)/privacy',
                'action'  => function ($lang) {
                    $data = [
                        'slug' => 'privacy',
                        'template' => 'privacy',
                        'translations' => [
                            'en' => [
                                'code' => 'en',
                                'content' => [
                                    'title' => 'Privacy',
                                    'text'  => site()->content('en')->privacy()
                                ]
                            ],
                            'es' => [
                                'code' => 'es',
                                'content' => [
                                    'title' => 'Privacidad',
                                    'text'  => site()->content('es')->privacy()
                                ]
                            ],
                            'ca' => [
                                'code' => 'ca',
                                'content' => [
                                    'title' => 'Privacitat',
                                    'text'  => site()->content('ca')->privacy()
                                ]
                            ],
                        ],
                    ];

                    $page = Page::factory($data);

                    site()->visit($page, $lang);

                    return $page;
                }
            ]
        ]
    ];

Alternatively I can provide solely the ‘title’ field in the virtual page, then merely grab the field in the template like $site->privacy() as I will presumably get the field in the actual language.

Any simpler solution ?

Thanks

Must admit that I don’t really see an advantage in making these pages virtual.

Especially, because the route approach wouldn’t let you fetch the pages e.g. for a menu in the footer and you would have to hard-code those links.

Yes, I just encountered the link problem.

More than an advantage it is a preference, I want the user to be able to input both privacy and termsandconditions texts in their respective text fields, within a ‘meta’ tab, at site.yml.

I could work with a ‘meta’ page, and have both fields there, but they still need to be shown in separate pages.

Do you see any alternative to using virtual pages and hardcoding the link? (i’ve used: $site->url() . '/privacy')

thanks

You could register them with the pages extension, which would at least allow you to get them via the page() helper, e.g. page('privacy'):

You could then create a collection of meta pages…

(Unfortunately, this extension doesn’t make these virtual pages part of the site’s children), but still better than the routes. You would nevertheless of course have to pass the translations array.

1 Like