Page 1 of 1

[SOLVED] Dynamic Multi-lingual

Posted: Tue Aug 29, 2017 1:23 am
by LANSAGuru
Multilingual variables get burned into a compiled program.
I have a use case where a set of menu's is loaded dynamically from a file.
The file will have menu option and a description, but I want the description to be multilingual value.
So I want to put the name of the multilingual variable into the file and use it at runtime.

So I would have

#label.caption := multilingual_value_of(#field from file)

Currently I need to add a case statement for each new menu option to extract the appropriate multilingual variable which is a not elegant.

Concurrently, this same capability would be interesting to use against repository fields.
e.g.
#lbl_Logged_Date_Time := #itlogd.FieldAttributeAsString( Description ) if the field itself (#ITLOGD in this example) were also set able at runtime dynamically, but I don't think that would be a as common a use case. Due to layout issues for responsive design, I had to use labels vs. the default labels for fields in some cases, and this was a way to use the repository values instead of hard coding them and preserving the inbuilt multi-lingual capabilities of the repository.

The difference here is I don't know ahead of time which menu item or multilingual variable will be read from the file.

Is this possible?

Edit:

I thought of this.
The file will contain the name of a field in the repository.
The repository field will contain the multilingual descriptions needed.
At runtime we create a new field object like so

Set_Ref Com(#Result) To(*CREATE_FROM #The_Field.Value.Trim)

Then we set the properties to suppress the input field and only show the description of the field.

This will work (I think), but a bit of a kludge. Hoping for something more elegant. I really want to use the power of multi-lingual variables here, but in a dynamic way.

Re: Dynamic Multi-lingual

Posted: Tue Aug 29, 2017 8:18 am
by MarkD
In VLF-ONE we use a technique like this:

We have singleton scope(*Application) system manager called #USystem and it has a PRIM_KCOL named uMtxtValues of Unicode strings that has getter and setter methods, like this:

Code: Select all

* -----------------------------------------------------------------------------------
* Keyed collection to store Multilingual text strings
Define_Com Class(#PRIM_KCOL<#Prim_dc.UnicodeString #VF_ELSYMNAME>) Name(#MultilingualTextValues) Style(Collection)
Define_Pty Name(uMTxtValues) Get(Get_MtxtValue) Set(Set_MtxtValue)
* -----------------------------------------------------------------------------------
Ptyroutine Name(Set_MtxtValue)
Define_Map For(*input) Class(#prim_dc.UnicodeString) Name(#MultilingualTextValue)
Define_Map For(*input) Class(#VF_ELSYMNAME) Name(#MtxtKey)
Define_Com Class(#prim_dc.UnicodeString) Name(#MultilingualTextValueReference) Reference(*DYNAMIC)
#MtxtKey := #MtxtKey.UpperCase
#MultilingualTextValueReference <= #MultilingualTextValues<#MtxtKey>
If (#MultilingualTextValueReference *Is *null)
Set_Ref Com(#MultilingualTextValueReference) To(*Create_as #prim_dc.UnicodeString)
#MultilingualTextValues<#MtxtKey> <= #MultilingualTextValueReference
Endif
#MultilingualTextValueReference.Value := #MultilingualTextValue.Value
Endroutine

* -----------------------------------------------------------------------------------
Ptyroutine Name(Get_MtxtValue)
Define_Map For(*OUTPUT) Class(#prim_dc.UnicodeString) Name(#MultilingualTextValue)
Define_Map For(*input) Class(#VF_ELSYMNAME) Name(#MtxtKey)
Define_Com Class(#prim_dc.UnicodeString) Name(#MultilingualTextValueReference) Reference(*DYNAMIC)
#MtxtKey := #MtxtKey.UpperCase
#MultilingualTextValueReference <= #MultilingualTextValues<#MtxtKey>
If (#MultilingualTextValueReference *IsNot *null)
#MultilingualTextValue := #MultilingualTextValueReference
Else
* Convert an MTXT reference. NOTE: This is recursive !!!!!
If (#MtxtKey.Substring( 1 5 ).UpperCase = 'MTXT=')
#MultilingualTextValue := #COM_OWNER.zInt_HandleMTXTMessage( #MultilingualTextValue )
Else
#MultilingualTextValue := "No MTXT=" + #MtxtKey
Endif
Endif
Endroutine
At start up time we run a snap in program named UF_OMULTI that loads up the dynamic MTxt collection like this:

Code: Select all

#uSystem.uMTxtValues<Top> := *Mtxtuf_Top
#uSystem.uMTxtValues<Bottom> := *Mtxtuf_Bottom
#uSystem.uMTxtValues<Maximize> := *MTXTUF_MAXIMIZE
#uSystem.uMTxtValues<Minimize> := *MTXTUF_Minimize
#uSystem.uMTxtValues<Restore> := *MTXTUF_Restore
All other code references the MTXTs indirectly by their assigned symbolic name, for example:

Code: Select all

#RestoreImage.Hint := #USystem.uMTxtValues<Restore>

#Button.Caption := #USystem.uMTxtValues<Maximize>
This has several advantages:
- If a customer changes any *MTXT’s value they just need to recompile UF_OMULTI
- If a customer is dealing in a language that we do not ship, say Portuguese, they can even just use literals into UF_OMULTI.

I think, but am not sure, that this model might fit your requirement because the source of the strings at load up time can be from anywhere.

Re: Dynamic Multi-lingual

Posted: Tue Aug 29, 2017 9:08 am
by MarkD
BTW - this bit of code:

* Convert an MTXT reference. NOTE: This is recursive !!!!!
If (#MtxtKey.Substring( 1 5 ).UpperCase = 'MTXT=') etc ............

is so that server side applications can send back multilingual messages.
The server sends MESSAGE("MTXT=RESTORE") and that gets converted to the <RESTORE> multilingual message.

Re: Dynamic Multi-lingual

Posted: Tue Aug 29, 2017 10:59 am
by Stewart Marshall
LANSAGuru wrote: Tue Aug 29, 2017 1:23 am I really want to use the power of multi-lingual variables here, but in a dynamic way.
Sadly, multilingual variables and field multilingual features aren't dynamic.

The simplest solution is to add a language key to the table. If for some reason you really don't want to change the table definition, leave the table as is for your default language, and add a second table for additional languages.

Your problems would be solved with a single IF/ELSE.

Re: Dynamic Multi-lingual

Posted: Wed Aug 30, 2017 12:33 am
by LANSAGuru
Thanks all for the responses.

Conclusions:

1. Dynamically getting the value of an arbitrary multi-lingual variable at run time is not possible.

2. An approach like the VLF is using will work to solve the problem.