Difference between revisions of "LSL languageAPI"
(MultiLingual API to handle script output from notecard based language files) |
Kireji Haiku (talk | contribs) m (-1 >> ERR_GENERIC and 0 >> PUBLIC_CHANNEL) |
||
Line 75: | Line 75: | ||
string val; | string val; | ||
integer i = llListFindList(langIndex,[index]); | integer i = llListFindList(langIndex,[index]); | ||
if ( i != | if ( i != ERR_GENERIC ){ | ||
return parse(llList2String(langData,i),id); | return parse(llList2String(langData,i),id); | ||
} | } | ||
Line 88: | Line 88: | ||
integer i; | integer i; | ||
i = llSubStringIndex(val,"<<memory>>"); | i = llSubStringIndex(val,"<<memory>>"); | ||
if ( i != | 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 != | 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 117: | Line 117: | ||
if ( cmd == "!PRINT" ){ | if ( cmd == "!PRINT" ){ | ||
llSay( | llSay(PUBLIC_CHANNEL,parse(val,"")); | ||
} | } | ||
else if ( cmd == "!SET_LANG" ){ | else if ( cmd == "!SET_LANG" ){ | ||
Line 124: | Line 124: | ||
else{ | else{ | ||
integer i = llListFindList(langIndex,[cmd]); | integer i = llListFindList(langIndex,[cmd]); | ||
if ( i == | if ( i == ERR_GENERIC ) return; //<<<<<<<<<<<<<< this will silently fail missing indexes | ||
langData = llListReplaceList(langData,[val],i,i); | langData = llListReplaceList(langData,[val],i,i); | ||
} | } | ||
Line 142: | Line 142: | ||
integer i; | integer i; | ||
for ( i=0; i<llGetListLength(langIndex); i++ ){ | for ( i=0; i<llGetListLength(langIndex); i++ ){ | ||
llSay( | llSay(PUBLIC_CHANNEL,llList2String(langIndex,i)+" | "+llList2String(langData,i)); | ||
} | } | ||
} | } | ||
Line 170: | Line 170: | ||
} | } | ||
if ( llGetInventoryType(curLangFile) != INVENTORY_NOTECARD ){ | if ( llGetInventoryType(curLangFile) != INVENTORY_NOTECARD ){ | ||
llSay( | llSay(PUBLIC_CHANNEL,"Error, Language File Doesn't Exist"); | ||
return; | return; | ||
} | } | ||
Line 186: | Line 186: | ||
} | } | ||
else if ( num == langGetCode("WHISPER") ){ // Whisper | else if ( num == langGetCode("WHISPER") ){ // Whisper | ||
llWhisper( | llWhisper(PUBLIC_CHANNEL,translate(msg,id)); | ||
} | } | ||
else if ( num == langGetCode("SAY") ){ // Say | else if ( num == langGetCode("SAY") ){ // Say | ||
llSay( | llSay(PUBLIC_CHANNEL,translate(msg,id)); | ||
} | } | ||
else if ( num == langGetCode("SHOUT") ){ // Shout | else if ( num == langGetCode("SHOUT") ){ // Shout | ||
llShout( | llShout(PUBLIC_CHANNEL,translate(msg,id)); | ||
} | } | ||
else if ( num == langGetCode("OSAY") ){ // OwnerSay | else if ( num == langGetCode("OSAY") ){ // OwnerSay | ||
Line 218: | Line 218: | ||
state menu{ | state menu{ | ||
state_entry(){ | state_entry(){ | ||
menuChannel = | menuChannel = PUBLIC_CHANNEL; | ||
while(menuChannel == | while(menuChannel == PUBLIC_CHANNEL ){ | ||
menuChannel = (integer)llRound(llFrand(5)*10000000); | menuChannel = (integer)llRound(llFrand(5)*10000000); | ||
} | } | ||
Line 228: | 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 != | 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 244: | 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 251: | 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 257: | Line 257: | ||
state_exit(){ | state_exit(){ | ||
llSetTimerEvent(0); | llSetTimerEvent(0.0); | ||
} | } | ||
} | } | ||
Line 265: | 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 274: | 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 290: | 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 316: | Line 316: | ||
state timeout{ | state timeout{ | ||
state_entry(){ | state_entry(){ | ||
llSetTimerEvent(0); | llSetTimerEvent(0.0); | ||
llSay( | 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; |
Revision as of 02:21, 8 October 2013
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
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> // 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; }
} </lsl>
<lsl>
//================================================================================================ // 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));
}
} </lsl>
<lsl>
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<<< </lsl>
<lsl> 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<< </lsl>