LSL languageAPI
Jump to navigation
Jump to search
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_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<<