HOW TO: Multiple Form Projects Reading a Single SIB File

All announcements, questions and issues related to the TsiLang Components Suite.
Post Reply
mcone
Posts: 6
Joined: Thu Jul 24, 2003 8:13 pm
Contact:

HOW TO: Multiple Form Projects Reading a Single SIB File

Post by mcone »

Note: This topic was originally written July 25th, 2003. I made extensive changes to the advice given here on September 30th, 2003. The original advice is, as Serghei politely explained, was erroneous in some respects and unnecessarily complex.

My goal for this discussion is to share this information with others who are struggling with multiple-form projects and want to read all their data from a single SIL or SIB data file.


SECTION ONE

INITIAL COMPONENT SETUP

Many of the steps that I will be describing to you in this section can be automated by the TsiLang Expert. It helped me to step through them manually the first time in order to learn how these components work. So this is how I will approach the steps in this topic. Later in this dicussion we will approach and examine the Expert, which is quite a powerful tool. It just takes a little getting used to. Once you understand what it does, you will probably find yourself relying on it to automate a lot of conversion tasks.


STEP 1
Drop a TsiLangRT and TsiLangDispatcher on a master form. (Mine is on form_main.)

About TsiLangRT: This is a language component that controls setting the language text in each component and control, etc. at run time. It will also allow your users to modify the languages at run time if you want them to. I don't want that capability now. But I may in the future, so I'm using TsiLangRT just in case I change my mind.

About TsiLangDispatcher: This is the component with the glasses in the icon image. The purpose of the Language Dispatcher is to create one central location for controlling the Language Components used
in each forms. There should only be one Language Dispatcher in a project.

The dispatcher controls which language is active from one location. Set the dispatcher to ActiveLanguage 2, for example, and all the language components (TsiLangRT) in all the forms change languages.

As you will see, I chose to put my dispatcher in the main form. It does not have to be placed there. You can put it in any single form in the project. You will see below how to reference the dispatcher from any other form in the project.

STEP 2
Using the Delphi Object Inspector, set siLangRT's LangDispatcher property to to siLangDispatcher(or whatever you've named it.) This is a pointer to the dispatcher component object.

STEP 3
Set siLangRT's LoadOnCreate property to TRUE. No code will be necessary to load the language data file.

STEP 4
Select the dispatcher component on the screen, then move to the Object Inspector. In the Language property, enter the main (first) language name. Mine says "English'.

STEP 5
In the LangNames stringlist, set a couple of standard languages starting with the main language first. English, German, Spanish, French, Swahili - whatever you want. (This can be added to by the translator in the SILEditor program later - by you or the translator, or even the end-user.) Mine says English and German for now.

STEP 6
In the FileName property, set a relative path to the location of the language file that you will always use. For this program, my entry reads ".\language\fiftranslator.sib". Those of you familar with the DOS way of indicating paths will recognize the dot-slash way of indicating "the current directory or folder". This will give us the flexibility that we need in allowing the user to install the software in any folder selected during program installation without fixing the path to an absolute location relative to the root of a drive. What I did fix is the location of the language folder relative to the folder in which the installation program put my program.

(Note: The "SIB" extension is the default extension that Siticov and Serghei used to indicate a BINARY file. Binary files are compressed and load much faster compared to SIL files. SIL files are text files that represent the same data, but in a readable format.)

STEP 7
Now display one of the other forms in the project. Drop a siLangRT component in that form.

STEP 8
Be sure the form has the the main form's unit name in the uses list after the "implementation" keyword.

Code: Select all

implementation

{$R *.DFM}

uses
  FormMain; 
STEP 9
Select the siLangRT and then in the Object Inspector, find the LangDispatcher property. Choose the main form's siLangDispatcher in the pull-down box. (Mine says "Form_Main.siLangDispatcher") It should be the only choice in the pull-down list. (Just like in the TsiLangRT in the main form, this is the pointer to the dispatcher object in the main form that controls which language is active.) If it is not there, then you will need to check to be sure that you performed step 8 properly.

STEP 10
While still in the Object Inspector, set the LoadOnCreate to TRUE.



Note About duplicating these steps with the EXPERT
  • - The EXPERT feature of the TsiLang Component Suite can automatically insert the TsiLangRT component in every form that must be translated. We just performed a manual insertion in two forms in the project.

    - The EXPERT will NOT insert the TsiLangDispatcher component and set it up for you in the single form into which it is dropped. You must put the dispatcher component on a form of your choosing manually.

    - The EXPERT will NOT set the TsiLangRT property values of LangDispatcher and LoadOnCreate for you.

    - The EXPERT will NOT automatically add the form in which the dispatcher is placed in all the other form's USEs clause under implementation. You must do that manually.
SECTION TWO

CREATING THE SIL or SIB DATA FILE

We can run the program now, but our goal is to reference a language data file when the program loads. So you will need to create SIL or SIB file and place it in the ".\language" folder (or whatever you've named it). You can create any folder anywhere, and use any filename for the language file. The goal in this section is to create the language data file that you have indicated in the dispatcher's FileName property on the main form. These are the assumptions I will make for the way I am using the component. (Of course, you can modify this by adding further flexibility to your code.)
  • - My language file will be always be located in the "language" folder under the main executable's folder.
    - This language data filename will always be "FIFTranslator.sib".
    - FIFTranslator.sib will contain information for all languages.
    - FIFTranslator.sib will contain data for all the forms for the entire project.
This language data file can be populated with translation data and then created by using the TsiLang Expert feature. You will find this in the Tools menu of your Delphi IDE. (The short-cut says "Ctl-L", but that does not work in my Delphi 7).

The Expert is very powerful:
  • - It automatically finds all the forms in your project.
    - You can translate one at a time, or all of them using multiple-line selection in the grid.
    - You can even move the strings used in your code into a form's TsiLangRT component Strings property automatically. This allows for translation of what were fixed strings inside your code.
    - You can even convert your constants (under the const section in a pas file) this way.
    - Then, when you are finished with the initial translation, you can save all of this data from all of the forms into the single language data file.
In the Expert grid, the forms with the red check-mark (if you see any) have already been translated at least once. This information is stored internally (I think in the DFM file). This is a good starting point in case the SIB data file is not with your project by mistake. However, we want to be sure that the SIB file takes over the translation completely, so after all the forms are translated, we will save the translation for all the forms in one SIB file.

STEP 1
In the Tools/Options menu, choose the type of language component to use as default: I chose TsiLangRT. This is the only item I changed in the initial setup of the Expert.

STEP 2
Now select the form(s) to translate. I recommend that you start by double-clicking on one form to translate it alone. The Expert will load the form.

If the TsiLangRT component isn't already in the form being translated, then the Expert will insert it for you automatically. If this happens, be sure to manually set the two properties that must be set manually in this component when you are finished in the Expert (later) (See the end of SECTION 1).

If you want to trust Expert to do all the forms at one time, select multiple forms (Ctrl-A) in the Expert grid and press the Translate toolbar button in the upper left. If you select mulitple forms in this list and press Translate, be ready for a lot of activity. The expert will load all your forms and translate them.

STEP 3
After the initial translation is complete, I use the File>Save/Load Translation> Save Project to save one large SIB file with the name of your choosing. You can save the file as SIL or SIB file type. (Remember, the SIL filetype is like a text INI file and is less compact and effecient than the SIB type.) This is the default file-type in the save as file dialog. If you want, you can save it as a SIB file, by choosing the SIB Save as type in the dialog. (Once again, SIB files are smaller and load a lot faster than SIL files. You just can't read SIB file in a text editor like you can a SIL file.)

I used the standard delimiter that the program suggests ("~!@#$"). It seems to work better than trying to assign one myself.


SECTION THREE

TEST THE PROGRAM

Now test your program by changing something in the SIB file using the SILEditor (while your program is NOT running).

SILEditor: The SILEditor.exe program can be downloaded from the SICOMPONENTS site. It is a stand-alone program that does not appear to require any extra support files to run. This file can be distributed with your program. I put SILEditor.exe in the language folder next to the FIFTranslator.sib file since it's purpose is to load and edit either SIB or SIL files.

Inside SILEditor you will need to open the SIB file. The first language will appear in the first column, the second language in column two, etc. For the newer SILEditor program, you need to select one of the expandable sections on the left that is organized by Pascal units (like TForm_Main).

I recommend that you change one of the words in the main language section. For example, if you have a File menu, then you rename the word "File" to something like "Hi".

Save the changes back to the SIB file, then run your executable program, and you should see "Hi" where "File" used to be. This is because your TsiLangRT components have LoadOnCreate set to true, and they all reference the same dispatcher component with the same SIB filename.

Note: If you do not see a change in the caption or text in your form, then check the path and filename for the SIB file you've created. Also, be sure that you actually saved the SIB file from the SILEditor before you ran your program.



SECTION FOUR

SAVE AND RECALL THE STATE

You can save the language state using the INI file standard (as an integer). Or you can save it to the Registry if that's more convenient for you. This is an INI example:

Code: Select all

    WriteInteger (Const_LanguageSection, Const_LanguageNumber, siLangDispatcher.ActiveLanguage);
Then, when you load the value from INI (or registry, etc.), just use code like this:

Code: Select all

    siLangDispatcher.ActiveLanguage := ReadInteger(Const_LanguageSection, Const_LanguageNumber, 1);
This will automatically set the ActiveLanguage in all the forms through the Language Dispatcher component.


SECTION FIVE

CHANGING THE LANGUAGE STATE WHILE RUNNING

I have a form with a combobox component and an OK button for changing languages. Call the form from your main form after propagating the language names (stringlist) into the ComboBox stringlist, then setting the correct ItemIndex in the ComboBox. (Remember that the ActiveLanguage is 1-based - so be sure to subtract one from the ActiveLanguage when assigning ItemIndex)

This is how to propagate (assign) the ComboBox with the available languages in order to make a selection for the ActiveLanguage:

Code: Select all

  Form_LanguageSetup.ComboBox_Languages.Items.Assign(siLangDispatcher.LangNames);
  Form_LanguageSetup.ComboBox_Languages.ItemIndex := siLangDispatcher.ActiveLanguage-1;
  Form_LanguageSetup.ShowModal;
  siLangDispatcher.ActiveLanguage := Form_LanguageSetup.ComboBox_Languages.ItemIndex + 1;
When the user exists the modal form, set the ActiveLanguage value in the TsiLangDispatcher, and the text items on your screen will change automatically. (And all TsiLangRT components that are linked to the dispatcher will change their language too.)


SECTION SIX

IGNORING AND EXCLUDING TRANSLATIONS

Be sure to read the PDF about ignoring and excluding translations. Some items you certainly don't want translated - and you don't want others translating them for you. (Also there is some helpful discussion about that in the forum.)


SECTION SEVEN

INTERNAL Object Names (and RENAMING)
Object naming becomes important with this translator because your end-user (or at least your translator) will see your object names. For example he/she may see Label15 in the list, when it would probably be better to display Label_OptionSetup (or at least something more descriptive/professional). This is my least favorite task of the whole translation project - resetting our component names. From now on, we plan on paying better attention to our object names at creation time.

I hope this helps other users. The struggle is certainly worth it as this is a decent/reliable component (especially for the price!).
Last edited by mcone on Tue Sep 30, 2003 3:35 pm, edited 17 times in total.
Mike Cone
Advanced Tubular Technologies, Inc.
gaivans
Posts: 71
Joined: Fri Nov 29, 2002 4:10 pm

Post by gaivans »

Mike, thank your for your post. You have written a whole article and I think it is valuable contribution to this forum. I just would like to add some remarks and corrections, because I am afraid novices would search TsiLangRTLinked on their IDE palette for a long time :)

I guess you meant TsiLangRT - this component is especially designed for working with external .SIL/.SIB files, although there is possibility to load/save translations in run-time from/to any other types of TsiLang components. However if you wish to give your end-user the possibilty edit translations in run-time only TsiLangRT or TsiLangRTSE should be used.

With respect to CommonContainer property - this property is implemented only for TsiLangLinked component. The TsiLangLinked components do not store translations for Locales and DlgsCaptions but take them from the CommonContainer (a TsiLang component of type other than TsiLangLinked). Extraction of Locales and DlgsCaptions from CommonContainer is performed in the inherited method "Loaded" which is called only ONCE after the component's owner is created and loaded. Therefore, if you in an arbitrary moment of run-time call LoadAllFromFile then Locales and DlgsCaptions are not updated automatically. To force the update as a workaround you can call Loaded method of TsiLangLinked component.

Nevertheless, if you store all translations in an external .sil file I would not recommend mixing TsiLangRT and TsiLangLinked components in one project but use only TsiLangRTs. This will increase a little size of the .sil file due to duplicated Locales and DlgsCaptions but working with TsiLangRT will be much easier. In fact, you can just set siLangDispatcher.FileName = <THE SIL FILE>, link all TsiLangRT components to the dispatcher, and set property LoadOnCreate = True for all TsiLangRT components. Then no code required to load or update translations in run-time.
Best regards,
Serghei Gaivan
mcone
Posts: 6
Joined: Thu Jul 24, 2003 8:13 pm
Contact:

Post by mcone »

Serghei,

I was really hoping that you would find the weaknesses in my methods - and you did. Thank you.

My plan now is to continue with the same project, but without TsiLangLinked component according to your recommendation. This is only a smaller project. The real test will be when I implement your components in a project that is MUCH larger. It is critical to us that I get a good understanding of how to use your component properly before implementing the large project.

By the way, what I meant was "TsiLangLinked". The names of the components are so similar that I forgot to take the "RT" out. I edited the first post so that the component names are now correct. (I think that I found all of them.)

After I test your suggestions, I plan to come back and edit the first post so that new users will read a revised, and better, explanation of how to best use your components for this type of application.

Regards,
Mike
Post Reply