SitePoint Sponsor

User Tag List

Page 1 of 3 123 LastLast
Results 1 to 25 of 51
  1. #1
    SitePoint Member
    Join Date
    May 2005
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Good Practice OOP & Multiply Languages?

    This problem has been niggling at me for months now. I'm working on quite a large project which will need to be able to output in different languages.

    What i was going to do was have a language factory class which included the correct language file, this would have many defines statements in there like define("_LOGIN_","Login"); then throughout my classes where ever i needed the text login i could just do _LOGIN_


    my problem is this dosnt feel very OOP and doesnt feel like its good practice either. Any suggestions or comments on this?

  2. #2
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hrm well I prefer to have language objects for different parts of a website, like this:

    PHP Code:
    <?php
    /**
     * Author: Tim Koschützki
     * Date Started: April 16th, 2005
    */
    class IssueLang {
        public static 
    $insertSuccessHeading 'Success!';
        public static 
    $insertSuccessText 'Issue successfully inserted!';
        public static 
    $insertFailureHeading 'Failure!';
        public static 
    $insertFailureText 'An error occured while inserting the issue!';
        
        public static 
    $editSuccessHeading 'Success!';
        public static 
    $editSuccessText 'Issue successfully edited!';
        public static 
    $editFailureHeading 'Failure!';
        public static 
    $editFailureText 'An error occured while editing the issue!';
        
        public static 
    $deleteSuccessHeading 'Success!';
        public static 
    $deleteSuccessText 'Issue successfully deleteed!';
        public static 
    $deleteFailureHeading 'Failure!';
        public static 
    $deleteFailureText 'An error occured while deleting the issue!';
    }

    ?>
    See that those attributes are static, so they can be accessed like global variables (or global constants). This is not much different from what you have there, except that it allows to get stuff from languages other than the current one. Your constant-approach simply overrides constants and thus you could never use contents from another language pack than the current one.

    I might extend my language functionality later on, once I need importing/exporting of language packs as well as dynamic change of the language. A LanguageHandler class would be good here which provides all those operations.

    Hope this helped you a bit.

  3. #3
    SitePoint Member
    Join Date
    May 2005
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    cheers.

    I had contemplated a simular way but not using statics i was thinkin more of a base class to pull everything off but then i writ the idea off since unless u were including all the languages in once class it wouldnt work.

    Using your method u could also pass configuration values around like that, might have to give them some thought.

  4. #4
    If it aint Dutch it aint much Kilroy's Avatar
    Join Date
    Oct 2003
    Location
    The Netherlands
    Posts
    406
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would say include a language file similar to this:

    PHP Code:
    <?php

    // language file for errors

    $error['database_error'] = 'A database error occurred!';

    ?>

  5. #5
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah well either passing a language file around that simply has an array in procedural code or going static class attribute way - both have the same advantages and disadvantages.

    For a fact language-specific stuff is read-only and thus there is no point in passing language objects around. However, once your system relies on remote language packs you should refactor the code into language objects, which can then be passed around to the remote client in a transaction.

    My static class attribute approach is closer to this OOP-puristic way and thus could be more easily refactored. But I emphasize that both ways described in this thread simply have the same advantages and pitfalls.

  6. #6
    If it aint Dutch it aint much Kilroy's Avatar
    Join Date
    Oct 2003
    Location
    The Netherlands
    Posts
    406
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What I haven't mentioned is that I load these variables so that I can call them through class, like this:

    PHP Code:
    $lang->error['database_error'
    where $lang is a class and $error is a class member

  7. #7
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's another idea (which I myself just recently discovered): http://www.php.net/parse_ini_file

  8. #8
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If your considering ini files, why not go the whole way, and use gettext.

  9. #9
    SitePoint Member
    Join Date
    May 2005
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    i like the ini file idea but i think the static class idea seams best so far. If you used an ini file it could be read in the users browser unless u pretected the directory, where as users never see php and like the guy said the static class idea it much closer to being pure OO.

  10. #10
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    where as users never see php
    Unless of course your server has a fault, PHP is sent as plain text as well I think the holy grail of 'pure OO' may be clouding your judgement?

    This is the sense I get. I program with OO 99.9 percent of the time and swear by it, but in saying that I make use of a lot of XML for configuration, and I still manage to use Object Oriented Programming methodologies with ease.

    So, what I'm saying is that just because you read off a file, it need not hinder you. Another thing is I have a problem with the over use of STATIC, not sure why at the moment, but I just get a bad feeling about it...

  11. #11
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is the code of a class that I am using for implementing internationalization in several of my projects.

    PHP Code:
    //==================== START OF CLASS =========================//
    // CLASS: i18n                                                //
    //=============================================================//
    class i18n{
        private 
    $language;
        private 
    $languages;
        private 
    $message;
        
    //==================== START OF METHOD ========================//
        // METHOD: i18n                                             //
        //=============================================================//
        
    function i18n($language="US"){
            
    $this->language $language;
            
    $this->languages = array();
        }    
        
    //=============================================================//
        // METHOD: i18n                                             //
        //====================== END OF METHOD ========================//
     
        //==================== START OF METHOD ========================//
        // METHOD: add_msg                                            //
        //=============================================================//
        
    function add_msg($language$key$message){
            if(!
    $this->languages[$language])$this->languages[$language];
            
    $this->languages[$language][$key]=$message;     
        }    
        
    //=============================================================//
        // METHOD: add_msg                                            //
        //====================== END OF METHOD ========================//
     
        //==================== START OF METHOD ========================//
        // METHOD: get_msg                                            //
        //=============================================================//
        
    function get_msg($language$key){
            if(
    $this->languages[$language][$key]=="")return $this->languages[$this->language][$key];
            return 
    $this->languages[$language][$key];
        }
        
    //=============================================================//
        // METHOD: get_msg                                            //
        //====================== END OF METHOD ========================//
    }
    //=============================================================//
    // CLASS: i18n                                                //
    //====================== END OF CLASS =========================// 
    It is indeed very easy to implement like this:

    PHP Code:
     $i18n = new i18n(); 
     
    $i18n->add_msg("US""father""father");
    $i18n->add_msg("GE""father""Vater");
     
    $lang "GE";
     
    echo 
    $i18n->get_msg($lang"father"); 
    I didn't make it static because static functions, take too much memory space.

    Of course the $lang variable is selected by the user

    I'm thinking about extending this class so that it converts all the non-ASCII characters to their Unicode representational format. For example the Cyrillic character A is represented like &#1041.

    Hope that helps

  12. #12
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm thinking about extending this class so that it converts all the non-ASCII characters to their Unicode representational format. For example the Cyrillic character A is represented like &#1041.
    I would welcome this, could you please keep us upto date with your progess? Also, you mention about STATIC taking a lot more memory, do you have any documentation of where this is stated?

    Just to back up my feelings about the mis-use of STATIC if for nothing else, thanks.

  13. #13
    SitePoint Evangelist ghurtado's Avatar
    Join Date
    Sep 2003
    Location
    Wixom, Michigan
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Since we are on the issue of internationalization, and shortly I will have to develop a multilingual project: heres my twist. All of the solutions outlined above deal with the translation of "hard coded" strings, ie: those that live in your code (error messages, interface elements, etc...). How do you guys handle the translation of items from a DB? More specifically, what if the DB supporting a specific application wasn't developed with I18N in mind? What solutions do you think would be viable for this situation? (think of a product catalog that must provide, say, German and English descriptions of its products)
    Garcia

  14. #14
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    May be you are right about the STATIC. Taking into account that this class is to be used, it needs to be declared, thus taking its place in the memory, while making the methods static saves writing.

    About the Unicode representation, right now I'm using JavaScript to make it, and it takes time.

    I have been looking for the JavaScript functions charCodeAt() and fromCharCode() in PHP, but have found only for ASCII characters.

    I keep looking...

  15. #15
    Mlle. Ledoyen silver trophy seanf's Avatar
    Join Date
    Jan 2001
    Location
    UK
    Posts
    7,168
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Russeh
    If you used an ini file it could be read in the users browser unless u pretected the directory ....
    Not if you give the file a .php extension, such as english.ini.php, and make sure it dies if called. This is how I use it:

    Code:
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; <?php die ( 'Language file' ); /* Do *NOT* remove this line */ ?>
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; General form phrases
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    form.general.submit = "Submit"
    form.general.reset = "Reset"
    form.general.errors.occurred = "The following error(s) occurred"
    form.general.errors.complete.all = "Please complete all required fields"
    I then use a language object with a getPhrase method:

    PHP Code:
    <?php

        
    echo $language->getPhrase 'form.general.errors.complete.all' );

    ?>
    Sean
    Harry Potter

    -- You lived inside my world so softly
    -- Protected only by the kindness of your nature

  16. #16
    SitePoint Member
    Join Date
    May 2005
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very helpful some good techniques there, I think your right Dr Livingston pure OO is clouding my judgment quite a bit.

  17. #17
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Russeh
    like the guy said the static class idea it much closer to being pure OO.
    You couldn't be more mistaken. "Pure" OO calls for good encapsulation and information hiding; having a bunch of public attributes definitely misses the point here.

    I would suggest something along the lines of:

    PHP Code:

    class Phrasebook
    {

        private 
    $phrasebook;

        public 
    __construct($ini_file)
        {
            
    $this->phrasebook parse_ini_file($ini_file);
        }


    And then add the __get() to dynamically pull the phrases out of the phrasebook.

  18. #18
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ghurtado
    How do you guys handle the translation of items from a DB?
    My solution here (sorry, I'm in the hurry a bit) involves a separate table with entries, and two more, one with "virtual columns" and another with languages, and an I18n class which dynamically yoins any virtual columns with the actual ones on select (it also handles inserts, updates and deletes) and returns the whole record. A bit complicated, but works like charm.

  19. #19
    SitePoint Member
    Join Date
    May 2005
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    the problem with that is i'd have to pass the phonebook or language var to every class. for example ive got error messages in my database classes for outputing and logging, using your method would mean having to passing a language object to it which just seems wrong imo.

  20. #20
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Russeh
    the problem with that is i'd have to pass the phonebook or language var to every class. for example ive got error messages in my database classes for outputing and logging, using your method would mean having to passing a language object to it which just seems wrong imo.
    Are you replying to me?

    Anyway, I'll respond: make Language a singleton class and you're off the hook.

  21. #21
    SitePoint Evangelist ghurtado's Avatar
    Join Date
    Sep 2003
    Location
    Wixom, Michigan
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by BerislavLopac
    My solution here (sorry, I'm in the hurry a bit) involves a separate table with entries, and two more, one with "virtual columns" and another with languages, and an I18n class which dynamically yoins any virtual columns with the actual ones on select (it also handles inserts, updates and deletes) and returns the whole record. A bit complicated, but works like charm.
    If you could provide an example of either your schema or a sample query on how you handle this, it would help me see what you are doing a little bit better. Thanks for the insight, seems a little bit along the lines of what I was thinking of doing, since adding a new table for each language, or even language specific columns to already existing entities wouldn't scale very well.
    Garcia

  22. #22
    SitePoint Wizard
    Join Date
    May 2003
    Location
    Berlin, Germany
    Posts
    1,829
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    BerislavLopac: You store language specific stuff in a Database? Why?

  23. #23
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A bit complicated, but works like charm.
    Thumbs up for the KISS principle.

  24. #24
    SitePoint Evangelist ghurtado's Avatar
    Join Date
    Sep 2003
    Location
    Wixom, Michigan
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DarkAngelBGE
    BerislavLopac: You store language specific stuff in a Database? Why?
    I would assume that he does it because the entities to be internationalized are already in the database. If I have a table with product names and I need to retrieve them in several different languages, it makes a lot more sense for me to have the alternative languages in the Database as well instead of relying on external files that would have to somehow be combined with the DB anyway.
    Garcia

  25. #25
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ghurtado
    I would assume that he does it because the entities to be internationalized are already in the database. If I have a table with product names and I need to retrieve them in several different languages, it makes a lot more sense for me to have the alternative languages in the Database as well instead of relying on external files that would have to somehow be combined with the DB anyway.
    I saw some of this in the Prado PetStore example database schema, where each catalog item had multiple rows depending on the language identifer.

    http://www.xisc.com/wiki/index.php/P...e#Architecture
    http://www.xisc.com/wiki/index.php/P...Implementation
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •