Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium


Using too much resources

Posted on 2011-09-15
Medium Priority
Last Modified: 2012-05-12
Good day

I've got a VB6 application for English users, now I want to translate it to a different language.
I want to create a variable for each English word or sentence used in my application eg:

Public Const Lang_Search As String = "Search"
Public Const Lang_Open As String = "Open"

All this variable I put in a module called mod_English.bas
And for any other language I just create a new module and change the variable's string values.

But I have a couple of thousand words / sentences in my software that must be translated.

I assume this method will take up a lot of resources, because all the variables will be stored in memory.

Is there a better way of doing this that is more resource friendly?

Question by:koossa
LVL 37

Expert Comment

by:Neil Russell
ID: 36541943
Stop what your doing and go here and read.....


Author Comment

ID: 36542037
Thank you Neilsr

Don't know if I'm understanding it correctly, but this link is for translation with the Unicode / ANSI character problem.  

But in my case the 2 languages that I want to use is using only standard alpha numeric characters, I just want to find a way to do the translation without using public constants, because public constants will use way too much memory if you have a couple of thousand of them?

Please let me know if I'm missing something?
LVL 14

Expert Comment

by:Brook Braswell
ID: 36542255
Here is a different idea....

Are you using a database for your application ?
Create a Table - call it LangTag or whatever you prefer....
pKey   bigint
BaseLang  long varchar   - Holds the values you want to look up, the words or phrases in your app
Eng - add any number of additional language columns for what you want to translate into...

BaseLang might hold the value "Username"
Eng would be where you hold a different way to say it such as "USER" or "End User"
Spn would hold the Spanish equivalent
Frn would hold the French equivalent

Give the logged in user a default language to interpret - based on your field name:

Global var MyLang as string
'  User Pierre might have
MyLang = "Frn"
' User Jose might have
MyLang = "Spn"
' Default users would have
MyLang = "Eng"

Dim SQL as string

SQL = "Select " & myLang & " from LangTag where BaseLang = " & InterPretValue

Index your table with BaseLang

Build a routine that you pass the Form Object to
Cycle through each of the objects you wish to interpret

To Speed things up:
Create a Public ( or Global depending on your needs ) recordset
gather all the LangTag table when you app opens with the values of the users language...
Make one read to your database then just get data from the "ClientSide" Recordset...

I have an example of this written in VB6 if you need.

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.


Author Comment

ID: 36542288
Thank you Brook.

I'm gone compile a different applications for each language, so it don't need to dynamically change the language.

If I "make one read" and get all the data from the database, it will still be stored in memory, so am I correct that this would use the same amount of memory than public constants in a module, because it is still stored in memory?

The other thing is, if I want to insert for example 10 language dependent values in the database, it must do 10 look-ups in the recordset, would this not slowdown my application dramatically?
LVL 14

Expert Comment

by:Brook Braswell
ID: 36542437
Are you going to be only looking up one language at a time or will your application show values of more than one language.
If you only get the two fields in your recordset  BaseLang and users language "Select baselang, Eng from"
I do believe that the recordset will actually take up less memory than variables ( PLUS ) you only have to update your database should a value change or more interpretations are required.

If that still does not free up enough resources then you could just make a procedure to interpret the values and read from your table one row at a time when you need the row...
' your label here would be your base lang at form design - unless you interpret more than once this would work fine - otherwise use the TAG property of your label to hold what you want interpreted

' this process is slower than loading the table but frees up more memory
lblME.Caption = InterpretME(lblME.Caption)

Public Function InterpretME(byval sPhrase as string) as string
   SQL = "SELECT " & gsUserLang & " FROM LANGTAG WHERE BASELANG = '" & sPhrase & "' "
   ' open your recordset and return your data...
   InterpretME = RS.fields(0).value

End Function

Author Comment

ID: 36542686
Thank you very much!!

Yes, only 1 language at a time

Can't I do something like this or anything similar:
Private Const m_LookupLang As String = "|Lang_Search|Lang_Test|Lang_go|Lang_exit|Lang_Monday|Lang_Tuesday|"
Private Const m_ActiveLang As String = "|Search|Test|go|exit|Monday|Tuesday|"

Public Function InterpretME(ByVal sPhrase As String) As String
  Dim lPos As Long
  Dim lIndex As Long
  Dim sItems() As String
  lIndex = InStr(1, m_LookupLang, "|" & sPhrase & "|")
  If lIndex > 0 Then
    sItems = Split(Mid(m_LookupLang, 1, lIndex), "|")
    lPos = UBound(sItems)
    sItems = Split(m_ActiveLang, "|")
    InterpretME = sItems(lPos)
  End If
End Function

Open in new window

LVL 14

Accepted Solution

VBClassicGuy earned 2000 total points
ID: 36543157
I have been doing this for seventeen years, using a method my boss suggested. Being that old, the method may not be "modern", but it works FAST and doesn't take up any resources. First, I have a master lexicon file that contains al text the program displays, in three different languages. Here is a snippet of the file:

   1 #### Master Lexicon File 03-18-94 Copyright (c) 1994 My Company, Inc. #####
   2 ########### 1-English, 2-Spanish, 3-French  (* in col 5 = not used) #########
   3 &Setup
   3 &Configuracion
   3 &Configuration
   4 Configure Plant &Location
   4 Configuracion de la Planta &Localidad
   4 Configurer Endroit de &Usine
   5 Configure &Groups
   5 Configuracion de &Grupos
   5 Configurer &Groupes
   6 Configure Supply I&nventory Data
   6 Configuracion de Datos de &Inventario de Suministros
   6 Configurer Donnees de Inventaire de &Fourniture
   7 Configure Plant &Utility Data
   7 Configuracion de &Datos de Servicios de Planta
   7 Configurer Donnees de Utilite de U&sine
   8 Configure &Classification
   8 Configuracion de &Clasificacion
   8 Configurer &Classification
   9 E&xit
   9 S&alir
   9 S&ortir
  10 &Group
  10 &Grupo
  10 &Groupe

I edit this file to add new entries when needed. Right now it has 2110 entries (actually three times that, 2110 times three languages). Anyway, I have a utility I wrote that, after editing, creates three specialized lexicon files, such as Pnet_ENG.lex, Pnet_ESP.lex, and Pnet_FRA.lex. These individual lexicon files contain only the strings for that language. There is a user-selectable variable that sets the language, so I know which file to pull from. Then everywhere I use text, instead of saying:

lblWarning.Text = "Warning"

I use:

lblWarning.Text = Lang$(540)   'XL "Warning"

The XL comment stands for "translation", and reminds me in the program what text I'm using.

Here is the Lang$ routine:

Function Lang$(offset&)
   Rem *** lex$ is a global that holds either "ENG", "ESP", or "FRA" ***
   a$ = String$(80, 32)
   Call CRFO(AppPath$() & "\Lexicon\Pnet_" & lex$ & ".lex", "b", h%, 0)
   Get h%, 80 * offset& - 79, a$
   Close h%
   Lang$ = RTrim$(a$)
End Function

As you can see, the utility I use outputs the individual lexicon files with 80 characters per line. This enables me to use binary mode to access the file for speed.

The CRFO routine is just a fancy file open routine, and can easily be replaced with:

Open AppPath$() & "\Lexicon\Pnet_" & lex$ & ".lex" For Binary As h%

The whole thing looks like it would be slow, but is very, very fast and holds nothing in memory. Of course I don't have all th ecode listed here, like the utility to output the master lexicon into the three individual ones, but all this may give you some ideas.
LVL 14

Expert Comment

by:Brook Braswell
ID: 36543566
Just to keep you from having to rebuild each time you change or modify your lang you could read it at once, build your string and close the recordset...

Public m_LookupLang As String ' = "|Lang_Search|Lang_Test|Lang_go|Lang_exit|Lang_Monday|Lang_Tuesday|"
Public m_ActiveLang As String ' = "|Search|Test|go|exit|Monday|Tuesday|"

Public Sub InitLang()
           dim RS as new adodb.RecordSet
           dim SQL as string
           RS.OPEN SQL, YOURCONN, adOpenStatic, adLockReadOnly
           m_LookUpLang = "|"
           m_ActiveLang = "|"
           DO WHILE NOT RS.EOF
              m_LookUpLang = m_LookUpLang & RS!BASELANG & "|"
              m_ActiveLang = m_ActiveLang & RS!ALT_LANG & "|"
           SET RS = NOTHING
End Sub

Public Function InterpretME(ByVal sPhrase As String) As String
  Dim lPos As Long
  Dim lIndex As Long
  Dim sItems() As String
  lIndex = InStr(1, m_LookupLang, "|" & sPhrase & "|")
  If lIndex > 0 Then
    sItems = Split(Mid(m_LookupLang, 1, lIndex), "|")
    lPos = UBound(sItems)
    sItems = Split(m_ActiveLang, "|")
    InterpretME = sItems(lPos)
  End If
End Function

Open in new window


Author Closing Comment

ID: 36544921
I've done it with an INI file api

Option Explicit
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long

Public Function GetINIString(ByVal sApp As String, ByVal sKey As String) As String
  Dim sFile As String
  Dim sBuf As String * 256
  Dim lBuf As Long
  sFile = App.Path & "\MyData.ini"
  lBuf = GetPrivateProfileString(sApp, sKey, "", sBuf, Len(sBuf), sFile)
  GetINIString = Left$(sBuf, lBuf)
End Function

Private Sub Command1_Click()
  MsgBox GetINIString("Words", "Lang_Search")
End Sub

Open in new window

Then the ini file's content looks like this:
Lang_Search=Search test

Open in new window


Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Suggested Courses
Course of the Month13 days, 15 hours left to enroll

581 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question