ExpressionEngine CMS
Open, Free, Amazing

Thread

This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.

The active forums are here.

A better language library

December 19, 2007 2:08pm

Subscribe [3]
  • #1 / Dec 19, 2007 2:08pm

    Negligence

    50 posts

    I’ve decided that I should probably start sharing the libraries I’ve created that I find very useful. So, I’ll start with my Language library. Here’s a few reasons why it’s better than the native version.

    - Developing multi-lingual sites, the prospect of doing $this->lang->line(); for hundreds of language strings was daunting. With this library, one call gets all your language strings, or individual ones if you like.
    - You can create a set of “common” language strings that you reuse throughout your application, so you aren’t repeating strings in different files.
    - You do not have to separate between different languages with folders. Instead, you put related language strings in a single file, and using arrays, you distinguish between the different language versions of a string.
    - You can switch between languages on-the-fly.

    <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
    
    /**
     * If you don't mind, keep this block of text up here if you use this library. Thanks!
     * 
     * Author: Scott Winfield
     * <a href="http://www.palidia.com">http://www.palidia.com</a> */
    
    class Lang
    {
         private $defaultLang = 'en';
         private $language = 'en';
         private $positions = array('en' => 0, 'fr' => 1); // Position of the language string within the array
         private $varPrefix = 'lang_';
         private $data;
         
         
         /* Get all the language strings from a file */
         public function getKeys ( $file, $language = null )
         {
             if (isset($language))
             {
                 $this->setLanguage($language);
             }    
    
             require(APPPATH . 'language/' . $file . '.php');
             
             $this->getLangStrings($lang);
             return $this->data;
         }
         
         
         /* Get all the commonly-used language strings */
         public function getCommonKeys()
         {
             require(APPPATH . 'language/Common.php');
             
             $this->getLangStrings($lang);
             return $this->data;
         }
         
         
         /* Get a specific key from a file */
         public function getKey ( $key, $file )
         {
             require(APPPATH . 'language/' . $file . '.php');
             return $this->getCorrectString($lang[$key]);
         }
         
         
         public function setLanguage ( $language )
         {
             $this->language = $language;
         }
         
         
         public function getLanguage()
         {
             return $this->language;
         }
         
         
         /* Walk through the $lang var and pull out the strings */
         private function getLangStrings ( $lang )
         {
              foreach ($lang AS $name => $strings)
             {
                 $this->data[$this->varPrefix . $name] = $this->getCorrectString($strings);
             }        
         }
         
         
         /* Get the correct, language-sensitive string */
         private function getCorrectString ( $strings )
         {
             // Make sure you've got a valid string in the current language
             if (isset($strings[$this->positions[$this->language]]))
             {
                 return $strings[$this->positions[$this->language]];    
             }
             
              // Otherwise, return the default language string         
             return $strings[$this->positions[$this->defaultLang]];
         }
    }
     
    ?>

    Usage:

    // Load the library
    $this->load->library('Lang');
    // Getting all language strings
    $strings = $this->lang->getKeys('filename', 'optional language');
    // Get common language strings
    $strings = $this->lang->getCommonKeys();
    // Change the current language
    $this->lang->setLanguage('en');


    And your language file would look like this (under application/language/file.php):

    $lang['email'] = array('English string', 'French String', 'Spanish String', 'etc');
    $lang['phone'] = array('Phone', 'Phone', 'etc.');

    Now you can have your translated strings side-by-side for easy editing and viewing. If you have any questions, let me know. Otherwise, enjoy 😊

  • #2 / Dec 20, 2007 3:01am

    imzyos

    79 posts

    - You do not have to separate between different languages with folders. Instead, you put related language strings in a single file, and using arrays, you distinguish between the different language versions of a string.

    this give’s order, and we dont need load a lot of configs just the files that we need

    - You can switch between languages on-the-fly.

    $this->lang->load(‘filename’, ‘language’);

  • #3 / Dec 20, 2007 7:47am

    esra

    485 posts

    imzyos is correct. Language switching can be handled using a cookie setting for the users current language. There should also be a user contribution on the wiki. You should be able to find sample code on the forums about how to create a reusable language selection view fragment for use in a template or master view.

    ——-
    The CI user_guide mentions a number of optional directories under application/ that can be created. These are scattered throughout the user guide and not mentioned in a single location. CI checks these if they exist. These include application/plugins/, application/helpers, and application/language. It would probably be more intuitive if those directories were included in the distribution with instructions for removing them if not needed.

    Language files can be stored in system/language or application/language. CI checks application/language first to scan for language files.

    If you’re using Matchbox or the older Modular Separation 2.4.x extensions for CI, a modules/modulename/language directory can exist for storing module-specific language files. In this case, I believe that the modules/modulename/language directories are scanned after application/language to look for files with the name you are attempting to load until a language file with that name is found, then system/language is scanned.

  • #4 / Dec 20, 2007 8:41am

    Negligence

    50 posts

    If you’ve ever had to develop multi-lingual applications before, and perform translations, you would come to appreciate having english, french, etc., language strings in a single file, instead of finding/replacing in two different files in two different directories.

    Second, the current Language library requires that you retrieve individual language strings individually. What happens when you’ve got fifty different strings you need to retrieve? This new library replaces fifty calls to line(), with one call to getKeys().

    As a side note, although its not included in the library, I set the language in the session. I just didn’t include that in the setLanguage() function.

  • #5 / Dec 20, 2007 9:52am

    imzyos

    79 posts

    yap, a i wrote an app, so spanish… and if i need other languaje just load from the languaje folder, is not necessarry have and array load ALL Languajes if you only gona show one per time…

  • #6 / Dec 20, 2007 10:25am

    Negligence

    50 posts

    Perhaps you misunderstood - it doesn’t load all the languages, it only loads the one you need. The major difference is that it loads all the language strings from a particular file at once, instead of one at a time.

  • #7 / Dec 20, 2007 10:59am

    imzyos

    79 posts

    And your language file would look like this (under application/language/file.php):

    $lang['email'] = array('English string', 'French String', 'Spanish String', 'etc');
    $lang['phone'] = array('Phone', 'Phone', 'etc.');

    Long array, using a cookie you could choose the correct languaje and not load ALL posibles Strings for example ‘yes’ according to you

    $lang['yes'] = array('Yes', 'We', 'si', '...');
  • #8 / Dec 20, 2007 11:20am

    Negligence

    50 posts

    I understand what you’re saying. Technically, it loads the data from the $lang array, but it only passes back what you need.

    It was a design decision because trying to maintain, update strings, and translate thousands of words/phrases for applications became a nightmare with files for the same language. This simplifies things tremendously.

    If this design choice is a serious concern to you, I’m surprised you use CI at all because of the many things it does that makes it more inefficient than it could be. The way the database class returns results, the Benchmark class being loaded by default, etc.. You might be surprised.

  • #9 / Dec 20, 2007 2:55pm

    esra

    485 posts

    If you’ve ever had to develop multi-lingual applications before, and perform translations, you would come to appreciate having english, french, etc., language strings in a single file, instead of finding/replacing in two different files in two different directories.

    The problem with this approach comes when you need to deal with multiple translators. We generally supply an English version of our language files and database tables to a language translation house which uses independent translators who then return their completed work for review cycles. By placing the strings for multiple languages in a single file, you either need to manually transfer the translations to one central language file (labor intensive) or need to incrementally pass the same file around between multiple translators (prone to mistakes and a slow process).

    Lastly, this approach is not very extensible in a modular sense because the files containing the arrays need to be manually edited each time a new language is added. Using the existing approach, one only needs to add a directory with a new set of language files for the desired locale.

  • #10 / Dec 20, 2007 3:10pm

    Negligence

    50 posts

    In my experience with translations, I have not sent off the actual PHP file containing the language strings. All the strings are put into Word, then sent off for translation. When it comes back in this format, it’s easy to do the copy/paste into a single file. Most translators I’ve worked with do not know anything about code, so we don’t give them a sight of it, however simply it may be.

    As for the modularity, the only reason why it isn’t modular (for you) is because you’re sending code to the translators. I’ve never heard of this being done, hence the reason why the library doesn’t account for that kind of situation.

  • #11 / Dec 20, 2007 4:51pm

    esra

    485 posts

    In my experience with translations, I have not sent off the actual PHP file containing the language strings. All the strings are put into Word, then sent off for translation. When it comes back in this format, it’s easy to do the copy/paste into a single file. Most translators I’ve worked with do not know anything about code, so we don’t give them a sight of it, however simply it may be.

    As for the modularity, the only reason why it isn’t modular (for you) is because you’re sending code to the translators. I’ve never heard of this being done, hence the reason why the library doesn’t account for that kind of situation.

    In any case, your approach should prove useful to many CodeIgniter users. If you are handling translations on your own as a developer, fine. But if you are not, my aguments may be valid.

    Sending translations out to professionals is pretty much standard for any software company or business who deals with language translations on a day-to-day basis, especially companies who target products to a global customer base. In the U.S and abroad, there are thousands of companies who handle this need. Most software houses or businesses sooner or later hire a part time or full time administrator to handle this sort of thing. If not, it takes a lot of time away from developers and is not very economical when you consider the hourly rates or salaries paid to a programmer versus an administrator.

    I usually bounce our translations on our sales representative for a specific locale. They are usually a good indicator as to whether a translation was successful or not.

    Generally, experienced translators who make a living in this field are a smart lot. They are accustomed to working with or converting the string handlers for numerous programming languages. Numerous approaches are also used within the same programming language to achieve the same goals. Many translators are also accustomed to working directly with database content. They have their own bag of tricks for placing language strings in a generic format used by their language translation software/machines. If not, they usually have access to someone who can place the strings into a format that their software can read. 

    Translations are generally very locale specific because they have to be. The Portuguese spoken and written in Portugal is in many cases different from the Portuguese spoken and written in Brazil. Over the years, the various dialects of a language tend to change within a given geographic locale. I believe that there are over 40 different dialects of the Spanish language and a larger number of Arabic dialects and most have become locale specific over the years. If I’m targeting Brazil as a potential software customer audience, you can bet that I’m going to request a translator who has experience writing translations for that specific locale. If the same product is being targeted at Portugal, a separate translator may be employed for that particular translation. Unless in a rare case, you find someone with spoken and written language skills for multiple locales.

    The default language for Language.php for my CodeIgniter builds has been changed to en_US for this reason, making it possible to support en_GB, en_AU, en_NZ, etc. or using the above example, pt_PT, pt_BZ, etc. This allows language translations to be fine tuned for specific locales. My language directories for system/language/ and application/language/ use the same directory naming syntax rather than language names. This approach is pretty typical and closely follows W3C i18n recommendations. You might note that Kohana took a similar approach in 2.0 as well as other i18n improvements (e.g., support for UTF-8/Unicode string handlers).

    It’s not modular because the approach is not modular and loosely coupled in an OOP sense.

.(JavaScript must be enabled to view this email address)

ExpressionEngine News!

#eecms, #events, #releases