// Use LanguageDictionary.nui // cLanguageDictionary class and translate_value function // The cLanguageDictionary class enables you to write multi lingual (web) applications that are able // to switch between languages while running. // In general, when a text is referenced in the source code it typically will look // like this: // // set psLabel to "ls.buttons.save" // "ls"=language symbol, "buttons" is the name of the dictionary and "save" is an id of the item in the dictionary // // procedure DoSomething // string lsLabel // get translate_value (psLabel(self)) to lsLabel // // This will set psLabel to something like "lv.23.2" meaning // // value of the 23rd dictionarys 2nd value (F.ex "Save"). If // // you want the program to run efficiently, you must do this: // if (gbLngUpdate) set psLabel to gsLngValue // ... // Use Language // Default language setup Use Base.nui // Item_Property command, Various macros (FOR_EX...), cArray, cSet and cStack classes (No User Interface) use array.dbu // Global boolean used to signal that an optimized value is // available (in global string gsLngValue): boolean gbLngUpdate // When gbLngUpdate is TRUE string gsLngValue will contain // an optimized value (an optimized value is one that is // quickly translated) string gsLngValue move FALSE to gbLngUpdate move "" to gsLngValue desktop_section // The oSupportedLanguages object determines what languages are supported in the // application at hand. The purpose of this is to compress the arrays that holds // language dependant values and to make sure that un-needed values aren't loaded. integer gi$CmprLngIdx integer gi$CmprLngIdxMax move 0 to gi$CmprLngIdx move 0 to gi$CmprLngIdxMax object oSupportedLanguages is a cArray // After the first oLanguageDictionaryList object has been declared, it is no longer // possible to add languages that should be supported. property integer pbStopForAddingLanguages public FALSE item_property_list item_property integer pbActive.i item_property integer piIndex.i end_item_property_list procedure initialize_array integer liRow for liRow from 0 to LNG_MAX set piIndex.i liRow to -1 loop end_procedure send initialize_array procedure DoAddLanguage integer liLanguage if (pbStopForAddingLanguages(self)) error 783 "Languages cannot be added" else begin ifnot (pbActive.i(self,liLanguage)) begin set piIndex.i liLanguage to gi$CmprLngIdxMax increment gi$CmprLngIdxMax set pbActive.i liLanguage to TRUE end end end_procedure // This may be used by a language selector or by a page where it's possible // to edit the values in a database. procedure callback_supported_languages integer lhMsg integer lhObj integer liMax liLng get row_count to liMax decrement liMax for liLng from 0 to liMax if (pbActive.i(self,liLng)) send lhMsg of lhObj liLng loop end_procedure end_object // oSupportedLanguages // This is the central object that holds references to all cLanguageDictionary objects // declared in the application. It is because of this object that the global functions // translate_value is able to find the correct dictionary to handle a given translation. object oLanguageDictionaryList is a cArray item_property_list item_property string psDictionaryId.i item_property integer phDictionary.i end_item_property_list function iFindRow.s string lsDictionaryId returns integer integer liRow liMax liRval get row_count to liMax move (lowercase(lsDictionaryId)) to lsDictionaryId decrement liMax for liRow from 0 to liMax if (psDictionaryId.i(self,liRow)=lsDictionaryId) function_return liRow loop function_return -1 // Not found end_function procedure add_dictionary_object integer lhDictionary integer liRow string lsDictionaryId get psDictionaryId of lhDictionary to lsDictionaryId if (lsDictionaryId<>"") begin get row_count to liRow set psDictionaryId.i liRow to (lowercase(lsDictionaryId)) set phDictionary.i liRow to lhDictionary end set pbStopForAddingLanguages of oSupportedLanguages to TRUE end_procedure function sTranslateValue string lsValue returns string integer liRow lhDictionary liSymbolId string lsDictionary lsSymbol move FALSE to gbLngUpdate if (left(lsValue,3)="ls.") begin // Value could be: "ls.buttons.save" // It's a "language symbol" and we must translate it into a language value move (replace("ls.",lsValue,"")) to lsValue // "buttons.save" move (left(lsValue,pos(".",lsValue)-1)) to lsDictionary // "buttons" get iFindRow.s lsDictionary to liRow if (liRow>=0) begin get phDictionary.i liRow to lhDictionary move (replace(lsDictionary+".",lsValue,"")) to lsSymbol // "save" get iSymbolToId of lhDictionary lsSymbol to liSymbolId // The number we're going to use when asking for this value in the future move TRUE to gbLngUpdate move ("lv."+string(liRow)+"."+string(liSymbolId)) to gsLngValue get sTranslateItem of lhDictionary liSymbolId to lsValue // Get actual return value end end else begin if (left(lsValue,3)="lv.") begin // Value is: "lv.23.3" (23rd dictionary, 3rd item) move (replace("lv.",lsValue,"")) to lsValue // "23.3" move (left(lsValue,pos(".",lsValue)-1)) to liRow // "23" get phDictionary.i liRow to lhDictionary move (replace(string(liRow)+".",lsValue,"")) to liSymbolId // "3" get sTranslateItem of lhDictionary liSymbolId to lsValue // Get actual return value end end function_return lsValue end_function end_object // oLanguageDictionaryList end_desktop_section function translate_value global string lsValue returns string get sTranslateValue of oLanguageDictionaryList lsValue to lsValue function_return lsValue end_function procedure add_supported_language global integer liLanguage send DoAddLanguage of oSupportedLanguages liLanguage end_procedure send add_supported_language LNG_DEFAULT procedure select_current_language global integer liLanguage move liLanguage to giLanguage get piIndex.i of oSupportedLanguages liLanguage to gi$CmprLngIdx end_procedure // Languages // ÚÄÄÄÄÄÄÄ // I³ no X No Non Nein No // t³ yes X Yes Oui Ja Si // e³ quick X Quick Huit Schnell Avanti // m³ // s³ X=Default, if piDefaultLanguage is not //  included in "compressed langauge" array class cLanguageDictionary is a cArray procedure construct_object forward send construct_object property string psDictionaryId public "" // Name of the dictionary, //> If a value returns blank, the default behavior is to try the default //> language (LNG_DEFAULT). property integer piDefaultLanguage public LNG_DEFAULT // -1: No default languages (=blank values are OK) // These are used internally to optimize the process of adding property string priv.PreviousSymbol public "" property integer priv.PreviousIndex public 0 end_procedure function row_count returns integer integer liMax get item_count to liMax move (liMax+gi$CmprLngIdxMax+1/(gi$CmprLngIdxMax+2)) to liMax // OK function_return liMax end_function // Translate symbol into a unique item id (row or recnum) function iSymbolToId string lsSymbol returns integer integer liSymbolId liMax liItem move (lowercase(lsSymbol)) to lsSymbol get row_count to liMax decrement liMax for liSymbolId from 0 to liMax move (gi$CmprLngIdxMax+2*liSymbolId) to liItem if (value(self,liItem)=lsSymbol) function_return liSymbolId // OK loop function_return -1 // Not found end_function function sTranslateItem integer liSymbolId returns string integer liCmprLngIdx string lsValue // First we try the straight way: get value (gi$CmprLngIdxMax+2*liSymbolId+gi$CmprLngIdx+2) to lsValue if (lsValue="") begin // This didn't give us a value to return // We'll therefore try to get a value using the default language of the application: get piIndex.i of oSupportedLanguages LNG_DEFAULT to liCmprLngIdx if (liCmprLngIdx>=0) get value (gi$CmprLngIdxMax+2*liSymbolId+liCmprLngIdx+2) to lsValue if (lsValue="") begin // This didn't give us a value either. // We will therefore now try to get the value of default language of the dectionary: if (piDefaultLanguage(self)>=0) begin get piIndex.i of oSupportedLanguages (piDefaultLanguage(self)) to liCmprLngIdx if (liCmprLngIdx>=0) get value (gi$CmprLngIdxMax+2*liSymbolId+liCmprLngIdx+2) to lsValue end if (lsValue="") begin // The default language of this LanguageDictionary is not part of the supported languages // As a last resort we will therefore try to get the value from the default column of the object get value (gi$CmprLngIdxMax+2*liSymbolId+1) to lsValue end end end function_return lsValue end_function function iSymbolToIdOrCreate string lsSymbol returns integer // Private integer liSymbolId liItem get iSymbolToId lsSymbol to liSymbolId if (liSymbolId=-1) begin get row_count to liSymbolId move (gi$CmprLngIdxMax+2*liSymbolId) to liItem set value item liItem to lsSymbol // set value (gi$CmprLngIdxMax+1*liSymbolId) to lsSymbol end function_return liSymbolId end_function procedure set language_value string lsSymbol integer liLanguage string lsValue integer liCmprLngIdx liSymbolId get piIndex.i of oSupportedLanguages liLanguage to liCmprLngIdx if (liCmprLngIdx>=0) begin // If language is supported by this application move (lowercase(lsSymbol)) to lsSymbol if (lsSymbol=priv.PreviousSymbol(self)) begin // It's the same symbol => we reuse its position get priv.PreviousIndex to liSymbolId end else begin get iSymbolToIdOrCreate lsSymbol to liSymbolId set priv.PreviousIndex to liSymbolId set priv.PreviousSymbol to lsSymbol end set value item (gi$CmprLngIdxMax+2*liSymbolId+liCmprLngIdx+2) to lsValue end else begin // Language is not supported by the application. // However, if the language passed is the default language of the // language dictionary, we'll put the value in the default column. if (liLanguage=piDefaultLanguage(self)) ; set value item (gi$CmprLngIdxMax+2*liSymbolId+1) to lsValue // OK end end_procedure procedure end_construct_object forward send end_construct_object send add_dictionary_object of oLanguageDictionaryList self // Register with global list of language dictionaries end_procedure end_class // cLanguageDictionary