How would I? (Classes)
Monkey Forums/Monkey Programming/How would I? (Classes)
| ||
| I want my game to support several languages. Thinking I would create different Classes (same field names) for each language; Class StringsEN Field MainMenuPlayCMD:String = "play" Field MainMenuSettingsCMD:String = "settings" Field MainMenuAboutCMD:String = "about" End Class Class StringsFR Field MainMenuPlayCMD:String = "fr play" Field MainMenuSettingsCMD:String = "fr settings" Field MainMenuAboutCMD:String = "fr about" End Class Class StringsDE Field MainMenuPlayCMD:String = "de play" Field MainMenuSettingsCMD:String = "de settings" Field MainMenuAboutCMD:String = "de about" End Class ... then some how link a Class or a Global (we'll call it Text) to one of the language Classes so all I need to do programmatic is call the below regardless of the language. DrawText Text.MainMenuPlayCMD,0,0 I could ofc hard code it; Global Text:StringsEN Text = New StringsEN But I want a user to choose on start-up. |
| ||
| You will over complicate your app and end up with lots of duplicate code if you use the method described above. Only use a single field for each of the text strings. Then either create the embedded translations as some kind of array / list or use external files to contain the text. On language selection simply read the file or array and assign the correct strings to the fields for the selected language. |
| ||
Class StringsBase
Field MainMenuPlayCMD:String
Field MainMenuSettingsCMD:String
Field MainMenuAboutCMD:String
End Class
Class StringsEN Extends StringsBase
Method New()
MainMenuPlayCMD = "play"
MainMenuSettingsCMD = "settings"
MainMenuAboutCMD = "about"
End
End
Class StringsFR Extends StringsBase
Method New()
MainMenuPlayCMD = "fr play"
MainMenuSettingsCMD = "fr settings"
MainMenuAboutCMD = "fr about"
End
End
Class StringsDE Extends StringsBase
Method New()
MainMenuPlayCMD = "de play"
MainMenuSettingsCMD = "de settings"
MainMenuAboutCMD = "de about"
End
End
Function Main:Int()
Local Text:StringsBase
Text = New StringsEN
Print(Text.MainMenuPlayCMD)
Text = New StringsFR
Print(Text.MainMenuPlayCMD)
Text = New StringsDE
Print(Text.MainMenuPlayCMD)
Return 0
End |
| ||
Diddy has an international module, where you store your translations in a simple xml file:<?xml version="1.0" ?>
<i18n>
<language name="french">
<string>
<key>Hello World!</key>
<value>Bonjour, tout le monde!</value>
</string>
</language>
<language name="japanese">
<string>
<key>Hello World!</key>
<value>こんにちは、みなさん!</value>
</string>
</language>
</i18n>http://code.google.com/p/diddy/source/browse/examples/I18N/testI18N.monkey |
| ||
| Good point... Diddy, Fantom and Ignition all provide ways to localize the language. |
| ||
Class Translator
Field _map:StringMap<String>
Method New()
_map = New StringMap<String>
Self.SetLanguage("EN") ' default
End
Method Tr:String(txt:String)
If _map.Contains(txt) = True
Return _map.Get(txt)
Else
Return txt
endif
End
Method SetLanguage(lang:String)
' Load all strings from "language.%lang%.txt" into _map
End
End Class
Function Main:Int()
Local Text:Translator = New Translator()
Print(Text.Tr("play"))
Text.SetLanguage("DE")
Print(Text.Tr("play"))
Text.SetLanguage("FR")
Print(Text.Tr("play"))
Return 0
EndProcedural: Global _map:StringMap<String> = New StringMap<String>
Function tr:String(txt:String)
If _map.Contains(txt) = True
Return _map.Get(txt)
Else
Return txt
endif
End
Function SetLanguage(lang:String)
' Load all strings from "language.%lang%.txt" into _map
' foreach line in language.%lang%.txt
' _map.Set( word, translation )
' next
End
Function Main:Int()
SetLanguage("EN") ' default
Print( tr("play") )
SetLanguage("DE")
Print( tr("play") )
SetLanguage("FR")
Print( tr("play") )
Return 0
End
' language.EN.txt contents:
' play = play
' language.DE.txt contents:
' play = spielen
' language.FR.txt contents:
' play = fr playI like the procedural tr() way for translating strings. Quick to write. |
| ||
| @Danilo -Thanks your first solution is perfect @therevills - I should probably look at Diddy for my next project and XML in general @Trez - I am only going to have 20-30 strings in the game so I should be good Thanks all. =D |
| ||
| I have a system nearly equal to the diddy one and load the values from an xml. The only difference is that I use 1 file per language (like en.xml, de.xml, fr.xml, ...) which are all in a folder. This is the interface: Class Localize Function SetLanguage:Void(language:String) Function GetValue:String(key:String) Function SetValue:Void(key:String, value:String) Function GetCurrentLanguage:String() Function SetLanguageDirectory:Void(path:String) Function GetLanguageDirectory:String() Function UnlocalizedWords:String() 'returns all words that could not be localized (for debugging) End E.g. SetLanguage("de") will load de.xml from the folder that has been specified with SetLanguageDirectory().After that you will use your strings like this: Local menuPlay:String = Localize.GetValue("menu_play") |