Difference between revisions of "LSL languageAPI"

From Second Life Wiki
Jump to navigation Jump to search
(New page: {{LSL Header}} <lsl> // LSL_languageAPI // License Info - LGPL // Version 0.20 // Author: Gypsy Paz //============== // CONFIG //============== integer autoLoad = FALSE; // l...)
 
m (Replaced old <LSL> block with <source lang="lsl2">, <pre> formatting for notecard contents)
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{LSL Header}}
{{LSL Header}}


This is an API that will handle chat messages and HUD menus in multiple languages based on language files in notecards.
Included are two LSL files, the API itself, a simple example usage script and two language files ( English and French )


<lsl>
todo: floating text support is not yet included in this script.
 
 
 
<source lang="lsl2">
// LSL_languageAPI
// LSL_languageAPI
// License Info - LGPL
// License: LGPL
// Version 0.20
// Version: 0.20
// Author: Gypsy Paz
// Author: Gypsy Paz


Line 69: Line 75:
     string val;
     string val;
     integer i = llListFindList(langIndex,[index]);
     integer i = llListFindList(langIndex,[index]);
     if ( i != -1 ){
     if ( i != ERR_GENERIC ){
         return parse(llList2String(langData,i),id);
         return parse(llList2String(langData,i),id);
     }
     }
Line 82: Line 88:
     integer i;
     integer i;
     i = llSubStringIndex(val,"<<memory>>");
     i = llSubStringIndex(val,"<<memory>>");
     if ( i != -1 ){
     if ( i != ERR_GENERIC ){
         val = llDeleteSubString(val,i,llStringLength("<<memory>>")-1);
         val = llDeleteSubString(val,i,llStringLength("<<memory>>")-1);
         val = llInsertString(val,i,(string)llGetFreeMemory());
         val = llInsertString(val,i,(string)llGetFreeMemory());
     }
     }
     i = llSubStringIndex(val,"<<key2name>>");
     i = llSubStringIndex(val,"<<key2name>>");
     if ( i != -1 ){
     if ( i != ERR_GENERIC ){
         val = llDeleteSubString(val,i,i+llStringLength("<<key2name>>"));
         val = llDeleteSubString(val,i,i+llStringLength("<<key2name>>"));
         val = llInsertString(val,i,llKey2Name((key)id));
         val = llInsertString(val,i,llKey2Name((key)id));
Line 111: Line 117:


         if ( cmd == "!PRINT" ){
         if ( cmd == "!PRINT" ){
             llSay(0,parse(val,""));
             llSay(PUBLIC_CHANNEL,parse(val,""));
         }
         }
         else if ( cmd == "!SET_LANG" ){
         else if ( cmd == "!SET_LANG" ){
Line 118: Line 124:
         else{
         else{
             integer i = llListFindList(langIndex,[cmd]);
             integer i = llListFindList(langIndex,[cmd]);
             if ( i == -1 ) return;          //<<<<<<<<<<<<<< this will silently fail missing indexes
             if ( i == ERR_GENERIC ) return;          //<<<<<<<<<<<<<< this will silently fail missing indexes
             langData = llListReplaceList(langData,[val],i,i);
             langData = llListReplaceList(langData,[val],i,i);
         }
         }
Line 136: Line 142:
     integer i;
     integer i;
     for ( i=0; i<llGetListLength(langIndex); i++ ){
     for ( i=0; i<llGetListLength(langIndex); i++ ){
         llSay(0,llList2String(langIndex,i)+" | "+llList2String(langData,i));
         llSay(PUBLIC_CHANNEL,llList2String(langIndex,i)+" | "+llList2String(langData,i));
     }
     }
}
}
Line 164: Line 170:
             }
             }
             if ( llGetInventoryType(curLangFile) != INVENTORY_NOTECARD ){
             if ( llGetInventoryType(curLangFile) != INVENTORY_NOTECARD ){
                 llSay(0,"Error, Language File Doesn't Exist");
                 llSay(PUBLIC_CHANNEL,"Error, Language File Doesn't Exist");
                 return;
                 return;
             }
             }
Line 180: Line 186:
         }
         }
         else if ( num == langGetCode("WHISPER") ){    // Whisper
         else if ( num == langGetCode("WHISPER") ){    // Whisper
             llWhisper(0,translate(msg,id));
             llWhisper(PUBLIC_CHANNEL,translate(msg,id));
         }
         }
         else if ( num == langGetCode("SAY") ){    // Say
         else if ( num == langGetCode("SAY") ){    // Say
             llSay(0,translate(msg,id));
             llSay(PUBLIC_CHANNEL,translate(msg,id));
         }
         }
         else if ( num == langGetCode("SHOUT") ){    // Shout
         else if ( num == langGetCode("SHOUT") ){    // Shout
             llShout(0,translate(msg,id));
             llShout(PUBLIC_CHANNEL,translate(msg,id));
         }
         }
         else if ( num == langGetCode("OSAY") ){    // OwnerSay
         else if ( num == langGetCode("OSAY") ){    // OwnerSay
Line 212: Line 218:
state menu{
state menu{
     state_entry(){
     state_entry(){
         menuChannel = 0;
         menuChannel = PUBLIC_CHANNEL;
         while(menuChannel == 0 ){
         while(menuChannel == PUBLIC_CHANNEL ){
             menuChannel = (integer)llRound(llFrand(5)*10000000);
             menuChannel = (integer)llRound(llFrand(5)*10000000);
         }
         }
Line 222: Line 228:
      
      
     listen(integer channel, string name, key id, string msg){
     listen(integer channel, string name, key id, string msg){
         llSetTimerEvent(0);
         llSetTimerEvent(0.0);
         integer i = llListFindList(langData,[msg]);
         integer i = llListFindList(langData,[msg]);
         if ( i != -1 ){
         if ( i != ERR_GENERIC ){
             llMessageLinked(LINK_THIS,langGetCode("MENU_R"),llList2String(langIndex,i),id);
             llMessageLinked(LINK_THIS,langGetCode("MENU_R"),llList2String(langIndex,i),id);
         }
         }
Line 238: Line 244:
      
      
     timer(){
     timer(){
         llSetTimerEvent(0);
         llSetTimerEvent(0.0);
         llMessageLinked(LINK_THIS,langGetCode("MENU_R"),">>>timeout<<<", menuUser);
         llMessageLinked(LINK_THIS,langGetCode("MENU_R"),">>>timeout<<<", menuUser);
         state default;
         state default;
Line 245: Line 251:
     link_message(integer sender, integer num, string str, key id){
     link_message(integer sender, integer num, string str, key id){
         if ( num == langGetCode("MENU_C") ){
         if ( num == langGetCode("MENU_C") ){
             llSetTimerEvent(0);
             llSetTimerEvent(0.0);
             state default;
             state default;
         }
         }
Line 251: Line 257:
      
      
     state_exit(){
     state_exit(){
         llSetTimerEvent(0);
         llSetTimerEvent(0.0);
     }
     }
}
}
Line 259: Line 265:
         if ( llGetInventoryType(curLangFile) == INVENTORY_NOTECARD ){
         if ( llGetInventoryType(curLangFile) == INVENTORY_NOTECARD ){
             request = llGetNumberOfNotecardLines(curLangFile);
             request = llGetNumberOfNotecardLines(curLangFile);
             llSetTimerEvent(5);
             llSetTimerEvent(5.0);
         }
         }
         else{
         else{
Line 268: Line 274:
     dataserver(key query_id, string data){
     dataserver(key query_id, string data){
         if (query_id == request){
         if (query_id == request){
             llSetTimerEvent(0);
             llSetTimerEvent(0.0);
             lines = (integer)data;
             lines = (integer)data;
             state read;
             state read;
Line 284: Line 290:
         line = 0;
         line = 0;
         request = llGetNotecardLine(curLangFile, line);
         request = llGetNotecardLine(curLangFile, line);
         llSetTimerEvent(5);
         llSetTimerEvent(5.0);
     }
     }
      
      
     dataserver(key query_id, string data){
     dataserver(key query_id, string data){
         if (query_id == request){
         if (query_id == request){
             llSetTimerEvent(0);
             llSetTimerEvent(0.0);
             processData(data);
             processData(data);
             line++;
             line++;
Line 310: Line 316:
state timeout{
state timeout{
     state_entry(){
     state_entry(){
         llSetTimerEvent(0);
         llSetTimerEvent(0.0);
         llSay(0,"Error, reading the language file timed out");
         llSay(PUBLIC_CHANNEL,"Error, reading the language file timed out");
         llMessageLinked(LINK_THIS,51,"error","timeout");
         llMessageLinked(LINK_THIS,51,"error","timeout");
         state default;
         state default;
Line 317: Line 323:


}
}
</lsl>
</source>






<lsl>
<source lang="lsl2">




Line 465: Line 471:
      
      
}
}
</lsl>
</source>








<lsl>
<pre>
Instructions go up here
Instructions go up here


Line 498: Line 504:


>>>STOP<<<
>>>STOP<<<
</lsl>
</pre>






<lsl>
<pre>
Mettez vos instructions ici
Mettez vos instructions ici


Line 528: Line 534:


>>>STOP<<
>>>STOP<<
</lsl>
</pre>

Latest revision as of 18:56, 24 January 2015

This is an API that will handle chat messages and HUD menus in multiple languages based on language files in notecards. Included are two LSL files, the API itself, a simple example usage script and two language files ( English and French )

todo: floating text support is not yet included in this script.


// LSL_languageAPI
// License: LGPL
// Version: 0.20
// Author: Gypsy Paz


//==============
//    CONFIG    
//==============
integer autoLoad = FALSE;    // load the first notecard on CHANGED_INVENTORY
float menuTimeout = 10;     // Set the blue menu time out ( in seconds )



//================================================================================================
//      LINK CODES:        
//================================================================================================
list langLinkCodes = [
    "INIT",     0x88000,     //Initialize
    "INIT_R",   0x88001,     //Confirm Initialized
    "LOAD",     0x88002,     //Load Language            lang file name (blank loads first one)
    "LOAD_R",   0x88003,     //Confirm Lanugage Loaded
    "MENU",     0x88004,     //langMenu                  caption|button1|button2|etc...    avkey
    "MENU_R",   0x88005,     //langMenu Response         button    uuid
    "MENU_C",   0x88006,     //Close the menu (turn off the listener)
    "WHISPER",  0x88007,     //langWhisper               message    uuid
    "SAY",      0x88008,     //langSay                   message uuid
    "SHOUT",    0x88009,     //langShout                 message uuid
    "OSAY",     0x8800A,     //langOwnerSay              message uuid
    "IM",       0x8800B,     //langIM                    message|avkey    uuid
    "FTEXT",    0x8800C,     //floating text             message color alpha
    "DUMP",     0x8800D,     //dump lang from memory to chat (for debugging)
    "ERROR",    0x8800E      // return an error message ( not sure how I'll handle this yet
];


//================================================================================================
//      LANGUAGE FUNCTIONS:
//================================================================================================
integer langGetCode(string langCode){
    integer i = llListFindList(langLinkCodes, [langCode]);
    return llList2Integer(langLinkCodes, i+1);
}


// Language Vars
string Language;
list langData;
list langIndex;
string curLangFile;

// llDialog Vars
string  menuCaption;
list    menuButtons;
key     menuUser;
integer menuChannel;
integer menuListener;

// Data Server Vars
integer lines;
integer line;
key request = NULL_KEY;

string translate(string index, string id){
    string val;
    integer i = llListFindList(langIndex,[index]);
    if ( i != ERR_GENERIC ){
        return parse(llList2String(langData,i),id);
    }
    else{
        return ">>>error<<<";
    }
}
        

string parse(string val, string id){
    // Memory
    integer i;
    i = llSubStringIndex(val,"<<memory>>");
    if ( i != ERR_GENERIC ){
        val = llDeleteSubString(val,i,llStringLength("<<memory>>")-1);
        val = llInsertString(val,i,(string)llGetFreeMemory());
    }
    i = llSubStringIndex(val,"<<key2name>>");
    if ( i != ERR_GENERIC ){
        val = llDeleteSubString(val,i,i+llStringLength("<<key2name>>"));
        val = llInsertString(val,i,llKey2Name((key)id));
    }
    return val;
}


integer processing = FALSE;
processData(string data){
    if ( processing ){
        if ( data == ">>>STOP<<<" ){
            processing = FALSE;
            return;
        }
        string prefix = llGetSubString(data,0,1);
        if ( ( prefix == "//" ) || ( llStringLength(data) == 0 ) ){
            return;
        }
        list s = llParseString2List(data,["|"],[]);
        string cmd = llStringTrim(llList2String(s,0),STRING_TRIM);
        string val = llStringTrim(llList2String(s,1),STRING_TRIM);

        if ( cmd == "!PRINT" ){
            llSay(PUBLIC_CHANNEL,parse(val,""));
        }
        else if ( cmd == "!SET_LANG" ){
            Language = val;
        }
        else{
            integer i = llListFindList(langIndex,[cmd]);
            if ( i == ERR_GENERIC ) return;          //<<<<<<<<<<<<<< this will silently fail missing indexes
            langData = llListReplaceList(langData,[val],i,i);
        }

            
        
        
        
    }
    else if ( data == ">>>START<<<" ){
        processing = TRUE;
    }
}


dumpData(){
    integer i;
    for ( i=0; i<llGetListLength(langIndex); i++ ){
        llSay(PUBLIC_CHANNEL,llList2String(langIndex,i)+" | "+llList2String(langData,i));
    }
}



default{
    link_message(integer sender, integer num, string msg, key id){
        list s;
        integer i;
        if ( num == langGetCode("INIT") ){        //Initialize
            curLangFile = "";
            Language = "";
            langIndex = llParseString2List(msg,["|"],[]);
            langData = [];
            for ( i = 0; i < llGetListLength(langIndex); i++ ){
                langData += ["..."];
            }
            llMessageLinked(LINK_THIS,langGetCode("INIT_R"),"ok"," ");
        }
        else if ( num == langGetCode("LOAD") ){    // Load Language
            if ( llStringLength(msg) == 0 ){
                curLangFile = llGetInventoryName(INVENTORY_NOTECARD,0);
            }
            else{
                curLangFile = msg;
            }
            if ( llGetInventoryType(curLangFile) != INVENTORY_NOTECARD ){
                llSay(PUBLIC_CHANNEL,"Error, Language File Doesn't Exist");
                return;
            }
            state prep;
        }
        else if ( num == langGetCode("MENU") ){    // llDialog
            s = llParseString2List(msg,["|"],[]);
            menuCaption = translate(llList2String(s,0),"");
            menuButtons = [];
            for ( i=1; i<llGetListLength(s); i++ ){
                menuButtons += translate(llList2String(s,i),"");
            }
            menuUser    = id;
            state menu;
        }
        else if ( num == langGetCode("WHISPER") ){    // Whisper
            llWhisper(PUBLIC_CHANNEL,translate(msg,id));
        }
        else if ( num == langGetCode("SAY") ){    // Say
            llSay(PUBLIC_CHANNEL,translate(msg,id));
        }
        else if ( num == langGetCode("SHOUT") ){    // Shout
            llShout(PUBLIC_CHANNEL,translate(msg,id));
        }
        else if ( num == langGetCode("OSAY") ){    // OwnerSay
            llOwnerSay(translate(msg,id));
        }
        else if ( num == langGetCode("IM") ){    // Instant Message
            s = llParseString2List(msg,["|"],[]);
            llInstantMessage(llList2Key(s,1),translate(llList2String(s,0),id));        
        }
        else if ( num == langGetCode("DUMP") ){
            dumpData();
        }
    }
    
    changed(integer change){
        if ( change & CHANGED_INVENTORY ){
            
        }
    }
                    
}



state menu{
    state_entry(){
        menuChannel = PUBLIC_CHANNEL;
        while(menuChannel == PUBLIC_CHANNEL ){
            menuChannel = (integer)llRound(llFrand(5)*10000000);
        }
        llDialog(menuUser,menuCaption,menuButtons,menuChannel);
        llSetTimerEvent(menuTimeout);
        menuListener = llListen(menuChannel, "", menuUser, "");       
    }
    
    listen(integer channel, string name, key id, string msg){
        llSetTimerEvent(0.0);
        integer i = llListFindList(langData,[msg]);
        if ( i != ERR_GENERIC ){
            llMessageLinked(LINK_THIS,langGetCode("MENU_R"),llList2String(langIndex,i),id);
        }
        else{
            llMessageLinked(LINK_THIS,langGetCode("MENU_R"),">>>error<<<",id);
        }
        state default;
    }




    
    timer(){
        llSetTimerEvent(0.0);
        llMessageLinked(LINK_THIS,langGetCode("MENU_R"),">>>timeout<<<", menuUser);
        state default;
    }
    
    link_message(integer sender, integer num, string str, key id){
        if ( num == langGetCode("MENU_C") ){
            llSetTimerEvent(0.0);
            state default;
        }
    }
    
    state_exit(){
        llSetTimerEvent(0.0);
    }
}

state prep{
    state_entry(){
        if ( llGetInventoryType(curLangFile) == INVENTORY_NOTECARD ){
            request = llGetNumberOfNotecardLines(curLangFile);
            llSetTimerEvent(5.0);
        }
        else{
            llOwnerSay("Error, Language File Does Not Exist");
        }
    }
    
    dataserver(key query_id, string data){
        if (query_id == request){
            llSetTimerEvent(0.0);
            lines = (integer)data;
            state read;
        }
    }
    
    timer(){
        state timeout;
    }
}


state read{
    state_entry(){
        line = 0;
        request = llGetNotecardLine(curLangFile, line);
        llSetTimerEvent(5.0);
    }
    
    dataserver(key query_id, string data){
        if (query_id == request){
            llSetTimerEvent(0.0);
            processData(data);
            line++;
            if ( line <= lines ){
                request = llGetNotecardLine(curLangFile, line);
                llSetTimerEvent(5);
            }
            else{
                state default;
            }
        }
    }
    
    timer(){
        state timeout;
    }
}


state timeout{
    state_entry(){
        llSetTimerEvent(0.0);
        llSay(PUBLIC_CHANNEL,"Error, reading the language file timed out");
        llMessageLinked(LINK_THIS,51,"error","timeout");
        state default;
    }

}


//================================================================================================
//   LANGUAGE API:
//------------------------------------------------------------------------------------------------

//================================================================================================
string langName;
list langIndex = [
    "HELLO_WORLD",
    "HELLO_AVATAR",
    "OBJECT_NAME",
    "OWNED_BY",
    "CAPTION",
    "BUTTON_1",
    "BUTTON_2",
    "BUTTON_3",
    "BUTTON_4",
    "BUTTON_5",
    "BUTTON_6"
];

//================================================================================================
//      LINK CODES:        
//================================================================================================
list langLinkCodes = [
    "INIT",     0x88000,     //Initialize
    "INIT_R",   0x88001,     //Confirm Initialized
    "LOAD",     0x88002,     //Load Language            lang file name (blank loads first one)
    "LOAD_R",   0x88003,     //Confirm Lanugage Loaded
    "MENU",     0x88004,     //langMenu                  caption|button1|button2|etc...    avkey
    "MENU_R",   0x88005,     //langMenu Response         button    uuid
    "MENU_C",   0x88006,     //Close the menu (turn off the listener)
    "WHISPER",  0x88007,     //langWhisper               message    uuid
    "SAY",      0x88008,     //langSay                   message uuid
    "SHOUT",    0x88009,     //langShout                 message uuid
    "OSAY",     0x8800A,     //langOwnerSay              message uuid
    "IM",       0x8800B,     //langIM                    message|avkey    uuid
    "FTEXT",    0x8800C,     //floating text             message color alpha
    "DUMP",     0x8800D,     //dump lang from memory to chat (for debugging)
    "ERROR",    0x8800E      // return an error message ( not sure how I'll handle this yet
];


//================================================================================================
//      LANGUAGE FUNCTIONS:
//================================================================================================
integer langGetCode(string langCode){
    integer i = llListFindList(langLinkCodes, [langCode]);
    return llList2Integer(langLinkCodes, i+1);
}

langInit(){
    llMessageLinked(LINK_THIS,langGetCode("INIT"),llDumpList2String(langIndex,"|")," ");
}

langLoad(string notecard){
    langName = "";
    llMessageLinked(LINK_THIS,langGetCode("LOAD"),notecard, " ");
}

langWhisper(string msg, key id){
    llMessageLinked(LINK_THIS,langGetCode("WHISPER"),msg,id);
}

langSay(string msg, key id){
    llMessageLinked(LINK_THIS,langGetCode("SAY"),msg,id);
}

langShout(string msg, key id){
    llMessageLinked(LINK_THIS,langGetCode("SHOUT"),msg,id);
}

langMenu(string caption, list buttons, key id){
    llMessageLinked(LINK_THIS,langGetCode("MENU"),caption+"|"+llDumpList2String(buttons,"|"),id);
}






default{
    state_entry(){
        langInit();
    }
    
    link_message(integer sender, integer num, string msg, key id){
        // Language is initialized
        if ( num == langGetCode("INIT_R") ){
            if ( msg == "ok" ){
                // load the default language (first notecard)
                langLoad("");
            }
            else if ( msg == "error" ){
                // something went wrong
                llOwnerSay((string)id);
            }
        }
        
        // Language is loaded
        else if ( num == langGetCode("LOAD_R") ){
            if ( msg == "ok" ){
                // load the default language (first notecard)
                langName = (string)id;
            }
            else if ( msg == "error" ){
                // something went wrong
                llOwnerSay((string)id);
            }
llMessageLinked(LINK_THIS,langGetCode("DUMP"),"dump data"," ");
        }
        
        // Blue Menu Response
        else if ( num == langGetCode("MENU_R") ){
            if ( msg == "BUTTON_1" ){
                langSay("HELLO_AVATAR", id);
            }
            else if ( msg == "BUTTON_2" ){
                langSay("OBJECT_NAME", llGetKey());            
            }
            else if ( msg == "BUTTON_3" ){
                langSay("OWNED_BY", llGetOwner());            
            }
            else if ( msg == "BUTTON_4" ){
                llMessageLinked(LINK_THIS,langGetCode("DUMP"),"dump"," ");
            }
            else if ( msg == "BUTTON_5" ){
                langLoad("language - ENGLISH");
            }
            else if ( msg == "BUTTON_6" ){
                langLoad("language - FRENCH");
            }
        }
    }
    
    touch_start(integer n){
        langMenu("CAPTION", ["BUTTON_1", "BUTTON_2", "BUTTON_3", "BUTTON_4", "BUTTON_5", "BUTTON_6"], llDetectedKey(0)); 

    }
    
}



Instructions go up here



>>>START<<<
// start processing the notecard
!SET_LANG   |  Engilish
!PRINT | Loading Language File...

HELLO_WORLD | Hello, I'm a multi-lingual api
HELLO_AVATAR | Hello <<key2name>>
OBJECT_NAME | I am a <<key2name>>
OWNED_BY | I belong to <<key2name>>
CAPTION | Language API Sample, choose your option
BUTTON_1 | Avatar
BUTTON_2 | Object
BUTTON_3 | Owner
BUTTON_4 | Dump
BUTTON_5 | ENGLISH
BUTTON_6 | FRENCH



!PRINT | Language file loaded.
!PRINT | <<memory>> bytes free

>>>STOP<<<


Mettez vos instructions ici



>>>START<<<
// commencez à traiter le notecard
!SET_LANG   |  Francais
!PRINT | Chargement du Dossier de Langue...

HELLO_WORLD | Bonjour, je suis api multilingue
HELLO_AVATAR | Bonjour <<key2name>>
OBJECT_NAME | Je suis <<key2name>>
OWNED_BY | J'appartiens à <<key2name>>
CAPTION | L'Échantillon d'API de langue, choisissez votre option
BUTTON_1 | Avatar
BUTTON_2 | Objet
BUTTON_3 | Propriétaire
BUTTON_4 | Décharge publique



!PRINT | Le dossier de langue a chargé.
!PRINT | octets de <<memory>> libres

>>>STOP<<