Using too much resources

Posted on 2011-09-15
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
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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.

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


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 500 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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

There are many ways to remove duplicate entries in an SQL or Access database. Most make you temporarily insert an ID field, make a temp table and copy data back and forth, and/or are slow. Here is an easy way in VB6 using ADO to remove duplicate row…
Introduction In a recent article ( for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

740 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