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 End Procedural: 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 play I 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") |