Page 1 of 1

Language files

Posted: Mon Jan 05, 2009 8:59 pm
by reisve
I was reading in this forum about language files for a project I'm working on. Saw all kind of methods but didn't see this one which seems to me to be a very simple ease to implement and very easy to use... Structures. It works for me and is the one I'm planning to use, in a include file

Code: Select all

Structure Language 
    Quit.s
    Save.s
    Save_as.s 
    Close.s
    Failed.s
EndStructure 

en.Language
en\Quit = "Quit"
en\Save = "Save"
en\Save_as = "Save as"
en\Close = "Close"
en\Failed = "Failed"

pt.Language
pt\Quit = "Terminar"
pt\Save = "Guardar"
pt\Save_as = "Guardar como"
pt\Close = "Fechar"
pt\Failed = "Falhou"

MessageRequester("", "Quit in English: " + en\Quit + "; Quit in Portuguese: " + pt\Quit)

; the long line split would be very usefull here to show all the options on the message box :wink: 
; and so on

Posted: Mon Jan 05, 2009 9:44 pm
by reisve
Just realized that you can't reference a strucure by an alias... or a reference. Not even copy a structure.
Maybe that is why no one mention that. :cry:

Forget about this.... How can I delet the post??

Posted: Mon Jan 05, 2009 10:22 pm
by Kaeru Gaman
you can put your structure to an array

Code: Select all

Structure Language
    Quit.s
    Save.s
    Save_as.s
    Close.s
    Failed.s
EndStructure

Enumeration 
  #En
  #Pt
EndEnumeration

Dim Capture.Language(#PB_Compiler_EnumerationValue)

Capture(#En)\Quit = "Quit"
Capture(#En)\Save = "Save"
Capture(#En)\Save_as = "Save as"
Capture(#En)\Close = "Close"
Capture(#En)\Failed = "Failed"

Capture(#Pt)\Quit = "Terminar"
Capture(#Pt)\Save = "Guardar"
Capture(#Pt)\Save_as = "Guardar como"
Capture(#Pt)\Close = "Fechar"
Capture(#Pt)\Failed = "Falhou"

MessageRequester("", "Quit in English: " + Capture(#En)\Quit + "; Quit in Portuguese: " + Capture(#Pt)\Quit)
the main point is, that you normally need A LOT OF terms for language versions,
it's quite inefficient to hardcode them into a structure, thus you don't find this solution suggested often.

Posted: Mon Jan 05, 2009 10:46 pm
by reisve
It is probably a better solution than have it in an array like lang(0) = "quit" and lang(300) = "terminar" and 3XX being the Portuguese, 200 the Geramany and so on. And that would be a huge hard work too. If you start building you language "include" when you start programming, it is not so bad.

Anyhow, thaks to this post http://www.purebasic.fr/english/viewtop ... structures
I found a way to copy structures. Here is the code:

Code: Select all

Structure Language 
    Quit.s 
    Save.s 
    Save_as.s 
    Close.s 
    Failed.s 
EndStructure 

en.Language 
en\Quit = "Quit" 
en\Save = "Save" 
en\Save_as = "Save as" 
en\Close = "Close" 
en\Failed = "Failed" 

pt.Language 
pt\Quit = "Terminar" 
pt\Save = "Guardar" 
pt\Save_as = "Guardar como" 
pt\Close = "Fechar" 
pt\Failed = "Falhou" 

lang.Language

CopyMemory(@en, @lang, SizeOf(Language)) 
MessageRequester("", "Quit in English: " + lang\Quit) 

CopyMemory(@pt, @lang, SizeOf(Language)) 
MessageRequester("", "Quit in Portuguese: " + lang\Quit) 
You define the language structures, and use the default lang structure. At the beguining of the App, according to user choice, you copy the right structure to the default. Seems easy to me, and will give me the same hard work as using an array.

P.S. If you could have multy dimension arrays like in PHP, like this:

language ['en'] ['quit'] = "Quit"
language ['pt'] ['quit'] = "Terminar"

This would be easier, but still a lot of work... You will have to write the messages two, three, four times depending how many languages you will offer to your customer. same work no matter the method you choose

Posted: Mon Jan 05, 2009 10:53 pm
by freak
Just use a pointer...

Code: Select all

Structure Language
    Quit.s
    Save.s
    Save_as.s
    Close.s
    Failed.s
EndStructure

en.Language
en\Quit = "Quit"
en\Save = "Save"
en\Save_as = "Save as"
en\Close = "Close"
en\Failed = "Failed"

pt.Language
pt\Quit = "Terminar"
pt\Save = "Guardar"
pt\Save_as = "Guardar como"
pt\Close = "Fechar"
pt\Failed = "Falhou"

*lang.Language

*lang = @en
MessageRequester("", "Quit in English: " + *lang\Quit)

*lang = @pt
MessageRequester("", "Quit in Portuguese: " + *lang\Quit) 
Btw, for an easy to manage and extend solution, i suggest this: http://www.purebasic.fr/english/viewtopic.php?t=26729
The PureBasic IDE which uses this approach now has 871 language keys in 18 groups and it can still be managed without much effort.

Posted: Mon Jan 05, 2009 11:01 pm
by Kaeru Gaman
reisve wrote:P.S. If you could have multy dimension arrays like in PHP, like this:

language ['en'] ['quit'] = "Quit"
language ['pt'] ['quit'] = "Terminar"

This would be easier, but still a lot of work... You will have to write the messages two, three, four times depending how many languages you will offer to your customer. same work no matter the method you choose
sure you can have multi dimensional Arrays...
Dim Cap( 23, 7 )

... but perhaps you better follow freaks suggestion and have a look at the other topic with the long proven solution.

Posted: Mon Jan 05, 2009 11:07 pm
by reisve
Thanks for the update. much better...

I've seen the post. Still thinking this is simpler. Gues it is a question of taste. And for the number of localized messages I'm planning to have this will do. Just a diferent aproach.
sure you can have multi dimensional Arrays...
Dim Cap( 23, 7 )
With numbers....

Posted: Mon Jan 05, 2009 11:21 pm
by Kaeru Gaman
> With numbers....

*shrug* and what?
if you really need, you can define constants.

Code: Select all

Enumeration 
  #English
  #Portuguese
  #German

  #NoOfLanguages
EndEnumeration

Enumeration 
  #Quit
  #Save
  #Save_as
  #Close
  #Failed

  #NoOfCaptures
EndEnumeration

Dim Cap.s( #NoOfLanguages, #NoOfCaptures )

For n=0 To #NoOfLanguages -1
  For t=0 To #NoOfCaptures -1
    Read.s Cap(n, t)
  Next
Next

Debug Cap( #Portuguese, #Save_as )
Debug Cap( #German, #Close )

End

DataSection
  Data.s "Quit", "Save", "Save as", "Close", "Failed"
  Data.s "Terminar", "Guardar", "Guardar como", "Fechar", "Falhou"
  Data.s "Beenden", "Speichern", "Speichern unter", "Schließen", "Misslungen"
EndDataSection
but in fact it is the way to use numbers instead of words that makes codes flexible...


but this only to answer, I still suggest to look at freaks professional solution.

Posted: Mon Jan 05, 2009 11:43 pm
by Rook Zimbabwe
Nice one Kaeru! :D

Posted: Tue Jan 06, 2009 8:09 am
by reisve
but in fact it is the way to use numbers instead of words that makes codes flexible...
Same flexibility with words. What is the diference? What can you do with numbers that you can't with words? With words it is more readable.

Posted: Tue Jan 06, 2009 1:15 pm
by Kaeru Gaman
numbers you could count in loops.
you can calculate them. the index of your table can be the result of a calculation.


when I write a loop that counts words, I get a large number of junk.
e.g. I start with aaaaa, next is aaaab, then aaaac...
how long would it take to get a meaningful index, and how many gaps would I get?

sure, you can use 'text' to get a number.
in fact it will be a four byte number consisting of the ASCII codes of the chars.
with this approach you would get even more gaps in your indices, because there are a lot of bytevalues not used.
additionally, 'text' is a constant. I only can alter it in compiletime.


but I think we have a really fundamental communication problem,
and you mean something completely different from what I understand...

Posted: Tue Jan 06, 2009 2:25 pm
by reisve
I was just giving the PHP example. in PHP you can use numbers or words at your wish. In my (litle) experience, both have their own places when coding. But as you said, we can use expressions, even if that involve an extra step. As I found out, long time ago, for the same problem, diferent solutions cames out of diferent probrammers. And each one claims his solution is the better one...

Posted: Tue Jan 06, 2009 2:29 pm
by Kaeru Gaman
I don't know PHP, so I don't know how words as indices are handled.

but I suppose there must be a reference table for the allowed verbal indices,
just because of the reasons I pointed out in the above post:
a direct usage of a word as index will produce giant gaps in the table.

Posted: Wed Jan 07, 2009 5:36 pm
by naw
I've done MultiLanguage by using INI files.
Its simple to swap an English INI file with a German INI file and you dont have to keep changing your code each time you add a new language.
I've defined _everything_ in INI files, Menus, Button Text, Currency Symbol, Date format, even gadget positions...

Posted: Wed Jan 07, 2009 7:40 pm
by reisve
I guess I forgot to say this is an havy comercial aplication, and I want the language files to be included in the application. License fees apply for the language :lol:

This is a project I started a couple of yars ago, with VB6. Then it cames VB .Net which I hate. So I decided to look for something not depending in "frameworks". Found PB, PowerBasic and a couple of other languages. PB was the one I fall in love with, so it is the one I using to have this going.