Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
SOLVED Dynamic (fake) pages and $language
#1
Hi Guys & Dolls,

I'm writing a plugin that creates dynamic pages on a multi-lingual frontend, so pages that are not on the "Pages"-page (lot of pages there Big Grin). The menu is also dynamically created by the plugin.

First some code snippets to show you what I mean:

In the top section of the plugin:
PHP Code:
# add in this plugin's language file
i18n_merge('my_plugin') || i18n_merge('my_plugin''en_US'); 

Filters added:
PHP Code:
add_filter('menuitems''my_menuitems');
add_filter('data_index''my_data_index'); 

Function my_menuitems:
This adds a new (dynamic) menuitem.
PHP Code:
function my_menuitems($menu) {

    global 
$SITEURL;

    if ((isset(
$_GET['id'])) &&($_GET['id'] === 'my_plugin')) {
        
$menu .= '<li class="index current active"><a href="' $SITEURL 'index.php?id=my_plugin" title="' i18n_r('my_plugin/MEN_FAKE') . '">' i18n_r('my_plugin/MEN_FAKE') . '</a></li>';
    } else {
        
$menu .= '<li class="index"><a href="' $SITEURL 'index.php?id=my_plugin" title="' i18n_r('my_plugin/MEN_FAKE') . '">' i18n_r('my_plugin/MEN_FAKE') . '</a></li>';
    }
    
    return 
$menu;


Function my_data_index:
This adds the actual dynamic page.
PHP Code:
function my_data_index($data_index) {
    
    
$data_index = new SimpleXmlElement('<?xml version="1.0" encoding="UTF-8"?>' "\n" '<item></item>');
    
$data_index->addChild('title'i18n_r('my_plugin/MEN_FAKE'));
    
$data_index->addChild('menu'i18n_r('my_plugin/MEN_FAKE'));
    
$data_index->addChild('pubDate''');
    
$data_index->addChild('meta''');
    
$data_index->addChild('metad''');
    
$data_index->addChild('url''my_plugin');
    
$data_index->addChild('content'i18n_r('my_plugin/CONTENT'));
    
$data_index->addChild('parent''');
    
$data_index->addChild('template''');
    
$data_index->addChild('private''');    

    return 
$data_index;


This all works like a charm... as long as the language isn't changed Sad

After some digging around, I found a couple of things:
  • Fontend language code is language only, meaning not "en_US" but solely "en" (fr, de, ...)
  • The current language is in the global variable $language
Now here is the problem: that global variable $language is empty in those functions, so I added the following at the top of those functions:

PHP Code:
    global $language;
    if (isset(
$_COOKIE['language'])) {
        
$language $_COOKIE['language'];
        
i18n_merge('my_plugin'$language);
    } else {
        
i18n_merge('my_plugin''en');
    } 

And i disabled this at the top of the plugin:
PHP Code:
# add in this plugin's language file
//i18n_merge('my_plugin') || i18n_merge('my_plugin', 'en_US'); 

But it isn't working as (I) expected...
  • The menu is translated ok
  • The dynamic page is translated ok
  • In "header.inc.php" $language is still "en"
Somewhere in the I18N docs there is briefly mentioned that a plugin should add i18n_init() at the top, but doing this gives some unexpected results, it messes up the translation of the static pages and their components.

Sorry for this long post, but could someone shine his or her light on this, I'm strugling with this for days now and there is not much info on this available.

Thanks,
Fripsy.
Reply
#2
Well, just got a little further with this:

I re-enabled this:
PHP Code:
# add in this plugin's language file
i18n_merge('my_plugin') || i18n_merge('my_plugin''en_US'); 

Then I deleted all frontend translations from "en_US", so they only exist in "en", "fr", ...

After 2 refreshes the translation is ok.

These problems still remain:
  • The $language variable still isn't updated in "header.inc.php"
  • When I force $language to the new language, parts of the site already did their translation, hence the 2 refreshes
Reply
#3
Finally I got this sorted out ! Smile
I post the solution here in case anyone is strugling with something similar.

Problem:
Display the correct language for pages created by a plugin through the "data-index", "indexid" and "menuitems" filters.

First, make sure you have seperate translation files for front- and backend.
  • Backend: en_US.php, fr_FR.php, de_DE.php, ...
  • Frontend: en.php, fr.php, de.php, ...
In the top of "my_plugin.php":
PHP Code:
add_filter('menuitems''my_menuitems');
add_filter('indexid''my_indexid');
add_filter('data_index''my_data_index'); 

In the "my_menuitems"-filter function:
PHP Code:
function my_menuitems($menu) {
    global 
$language;

    if (isset(
$_COOKIE['language'])) {
        
i18n_merge('GSDownloads'$language);
    } else {
        
i18n_merge('GSDownloads''en');  // set default language
    
}

    if ((isset(
$_GET['id'])) && ($_GET['id'] === 'my_plugin')) {
        
$menu .= '<li class="index current active"><a href="' $SITEURL 'index.php?id=my_plugin" title="' i18n_r('my_plugin/MENU') . '">' i18n_r('my_plugin/MENU') . '</a></li>';
    } else {
        
$menu .= '<li class="index"><a href="' $SITEURL 'index.php?id=my_plugin" title="' i18n_r('my_plugin/MENU') . '">' i18n_r('my_plugin/MENU') . '</a></li>';
    }
    return 
$menu;


In the "my_indexid"-filter funtion:
PHP Code:
    global $my_plugin_id;  // store id to use later in the "data-index" function

    
if ($id === 'my_plugin') {
        
$my_plugin_id$id;
    } else {
        
$my_plugin_id'';
    }
    return 
$id;


In the "data-index"-filter function:
PHP Code:
function GSDDataIndex($data_index) {
    
    global 
$my_plugin_id$language;
    
    if (
$my_plugin_id === 'my_plugin') {

        
i18n_init();
        if (isset(
$_GET[I18N_SET_LANGUAGE_PARAM])) {
            
$language $_GET[I18N_SET_LANGUAGE_PARAM];
            
i18n_merge('my_plugin'$language);
        } else {
            if (isset(
$_COOKIE[I18N_LANGUAGE_COOKIE])) {
                
$language $_COOKIE[I18N_LANGUAGE_COOKIE];
                
i18n_merge('my_plugin'$language);
            } else {
                
i18n_merge('my_plugin''en');
            }
        }

        
$data_index = new SimpleXmlElement('<?xml version="1.0" encoding="UTF-8"?>' "\n" '<item></item>');
        
$data_index->addChild('title'i18n_r('my_plugin/TITLE'));
        
$data_index->addChild('menu'i18n_r('my_plugin/MENU'));
        
$data_index->addChild('pubDate''');
        
$data_index->addChild('meta''');
        
$data_index->addChild('metad''');
        
$data_index->addChild('url''my_plugin');
        
$data_index->addChild('content'i18n_r('my_plugin/CONTENT'));
        
$data_index->addChild('parent''');
        
$data_index->addChild('template''');
        
$data_index->addChild('private''');    
    }

    return 
$data_index;


VoilĂ , that's all folks ! Big Grin

It took me a while to figure this out, I hope it will be of some use to someone.

Cheers,
Fripsy.
Reply
#4
Yeah all pretty basic, you have to use globals for everything in GS so you should have a firm understanding of php scopes.

I am also a little confused on i18n plugin front end languages, there are experts in here though.

glad someone is using the new hooks i made for this very reason.
let me know how it works out, and if we need to add anything else.

3.4 has a few more hooks, but these should let you do anything with page related stuff

also you should always do some kind of security filtering on language filenames since they almost always come from the user $_GET, and can be used to include files via directory traversal. I am not sure i18nmerge does this for you
NEW: SA Admin Toolbar Plugin | View All My Plugins
- Shawn A aka Tablatronix
Reply
#5
also you should probably use
global $id instead of isset($_GET['id'])
since $id could be filtered by index filter
and $_GET['id'] wont
NEW: SA Admin Toolbar Plugin | View All My Plugins
- Shawn A aka Tablatronix
Reply
#6
(2014-11-28, 01:06:22)shawn_a Wrote: also you should probably use
global $id instead of isset($_GET['id'])
since $id could be filtered by index filter
and $_GET['id'] wont

Didn't know $id was a global variable, I did change the $_GET['id'] to the global $id just now and it's working like a charm!

Thanks !
Reply




Users browsing this thread: 1 Guest(s)