4

When looking through the multistore language selector (in our theme) we see that the dropdown is populated as follows:

foreach ($this->getStores() as $_lang) {
    $select_stores[] = '<option '.$_selected_option.' value="'. $_lang->getCurrentUrl() .'">'. $this->htmlEscape($_lang->getName()) .'</option>';
}

The problem is that the (real) language is not the store name we give it and is fetched through '$_lang->getName()'

But rather the Locale set in the backend in storeconfig

$_language_code = substr(Mage::getStoreConfig('general/locale/code', $_lang->getId()),0,2);

I know how to fetch ths ID, but ....

Question: How can we now fetch the Locale full language name to populate the dropdown? (so German or Deutsch for Germany and English or Engels for English)

(And maybe cut off the the piece between brackets, so English (United States) becomes English)

1 Answer 1

5

Here is possible solution. Not the most elegant but it should work.
First you should get all the languages that appear in the backend in the locale config section.

$allLanguages = Mage::app()->getLocale()->getOptionLocales();

This will get you an array like this:

Array
(
    [0] => Array
        (
            [value] => af_ZA
            [label] => Afrikaans (South Africa)
        )

    [1] => Array
        (
            [value] => sq_AL
            [label] => Albanian (Albania)
        )

    ...
)

You can get the current locale code like you already do

$localeCode = Mage::getStoreConfig('general/locale/code', $_lang->getId());

Now all you have to do is to loop through all the languages and see if one matches your code.

$languageLabel = '';
foreach ($allLanguages as $language) {
    if ($language['value'] == $localeCode) {
        $languageLabel = $language['label'];
        break;
    }
}

If you want to lose the country name just do this.

$parts = explode('(', $languageLabel);
$languageLabel = trim($parts[0]);

Or you can use a regex that seams cleaner.

Of course you should wrap all this code in a method and just use that method.

[EDIT]
An other approach would be to get all the languages based on the language code only:

$languages = Zend_Locale::getTranslationList('language', Mage::app()->getLocale()->getLocaleCode());//replace with own locale.

this should return something like

[en] -> English
[fr] -> French

Then you have to get the lang code like this (you already do that):

$_languageCode = substr(Mage::getStoreConfig('general/locale/code', $_lang->getId()),0,2);

And just check

`if (isset($languages[$langCode]))`  

This seams cleaner but I'm not sure if it works correctly for all the values.
The first method seams safer because it uses the same options that you see in the backend.
Give either one of them a try.

[EDIT] Example of the final code from the question author (works like a charm)

    <!-- LANGUAGES BOF -->
<?php if(count($this->getStores())>1): ?>
<?php
$stores = array();
$_current = null;

$languages = Zend_Locale::getTranslationList('language', Mage::app()->getLocale()->getLocaleCode());

foreach ($this->getStores() as $_lang) {

    $_selected = $_selected_option = $_language_name = '';
    $_language_code = substr(Mage::getStoreConfig('general/locale/code', $_lang->getId()),0,2);
    if (isset($languages[$_language_code])) {$_language_name = $languages[$_language_code];} 
    $parts = explode('(', $_language_name);
    $_language_name = trim($parts[0]);

    if ( ($_lang->getId() == $this->getCurrentStoreId()) ) {
     $_current =  $_lang;
     $_current_lang = $_language_name;
     $_selected = ' class="selected"';
     $_selected_option = ' selected="selected"';
    }

    // $stores[] = '<li'. $_selected .'><a style="background-image:url(\''. $this->getSkinUrl('images/flags/'.$_lang->getCode().'.png') .'\');" href="'. $_lang->getCurrentUrl() .'">'. $this->htmlEscape($_lang->getName()) .'</a></li>';
    $stores[] = '<li'. $_selected .'><a style="background-image:url(\''. $this->getSkinUrl('images/flags/'.$_language_code.'.png') .'\');" href="'. $_lang->getCurrentUrl() .'">'. $this->htmlEscape($_language_name) .'</a></li>';
    $select_stores[] = '<option '.$_selected_option.' value="'. $_lang->getCurrentUrl() .'">'. $this->htmlEscape($_lang->getName()) .'</option>';
}

?>
<div class="header-switch language-switch">
    <span><?php echo $this->__('Your Language:') ?>
        <span class="current"><?php echo $this->htmlEscape($_current_lang); ?></span>
    </span>
    <div class="header-dropdown">
        <ul><?php echo implode('', $stores); ?></ul>
    </div>
</div>
10
  • Thanks Marius. Pfoe. I wonder how this impact performance (it is loaded every page load). I was also looking at some Zend standard that may help us framework.zend.com/manual/1.12/en/zend.locale.functions.html
    – snh_nl
    Nov 7, 2014 at 13:54
  • And on a different note. Don't you find it a little odd that the store selector (and flag backgrounds) use the StoreName instead of actual language/Locale (that the Locale option in backend would imply)
    – snh_nl
    Nov 7, 2014 at 13:55
  • Also I found that $country_name = Mage::getModel('directory/country')->loadByCode($_language_code)->getName(); works but it returns the country name
    – snh_nl
    Nov 7, 2014 at 14:02
  • First...this will not impact the performance very much. The values don't come from the db. They come from the ZF locale xml files. And to avoid any issues, just cache the block. You can also transform the big array to have a form like [code]=>'label'. this way you will parse it only once and just check if (isset($arr[$code])) instead of looping through it each time. I just wrote the basics in the answer, not the full solution. And no, it not not seam strange to me that the store name is used. What I don't like is that you cannot have different store labels for frontend and backend.
    – Marius
    Nov 7, 2014 at 14:06
  • Full comment: Also I found that $country_name = Mage::getModel('directory/country')->loadByCode($_language_code)->getName(); $_language_name = Mage::helper('core')->__($country_name); works but it returns the country name
    – snh_nl
    Nov 7, 2014 at 14:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.