Localization (Lokalisierung bzw. Übersetzung)

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

Jolinah

Betreff: Localization (Lokalisierung bzw. Übersetzung)

BeitragFr, Aug 18, 2006 23:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe ein kleines Modul zur Lokalisierung programmiert. Damit ist es ziemlich einfach ein Programm in mehreren Sprachen anzubieten. Angenommen man will eine Deutsche und eine Englische Version erstellen, dann macht man zunächst 2 Resource-Files mit folgendem Format:

example_de.txt
Code: [AUSKLAPPEN]
HELLO_WORLD = Hallo Welt!


example_en.txt
Code: [AUSKLAPPEN]
HELLO_WORLD = Hello world!



Diese kann man nun mit dem Modul auf unterschiedliche Art laden:

Beispiel
Code: [AUSKLAPPEN]
SuperStrict

Import "Localization.bmx"

'Sprachen hinzufügen
Localization.AddLanguages("de, en")

'Aktuelle Sprache wählen
Localization.SetLanguage("de")

'Einzelne Resource-Datei öffnen (Nichts wird in den Speicher geladen)
'Bei jedem GetString wird direkt in der Datei gesucht
'Localization.OpenResource("Resources/example_de.txt")

'Einzelne Resource-Datei laden (Wird in Speicher geladen)
'GetString holt die Daten aus dem Speicher, es ist keine Datei geöffnet
'Localization.LoadResource("Resources/example_en.txt")

'Mehrere Resource-Dateien öffnen anhand eines Filters (Dateizugriff)
'Localization.OpenResources("Resources/example*.txt")


'Mehrere Resource-Dateien laden anhand eines Filters (Speicherzugriff)
Localization.LoadResources("Resources/example*.txt")

Graphics 800, 600, 0

Repeat
Cls

   If KeyHit(KEY_SPACE) Then
      'Sprache abfragen
      If Localization.Language() = "de"
         Localization.SetLanguage("en")
      Else
         Localization.SetLanguage("de")
      EndIf
   EndIf

   'Wert für den Key HELLO_WORLD in der aktuellen Sprache abfragen
   DrawText Localization.GetString("HELLO_WORLD"), 10, 10
   
   'Wert für den Key HELLO_WORLD in der Gruppe Version2 in der aktuellen Sprache abfragen
   DrawText Localization.GetString("HELLO_WORLD", "Version2"), 10, 50

Flip
Until KeyHit(KEY_ESCAPE)

'Dateien schliessen und Speicher freigeben
Localization.Dispose()

EndGraphics
GCCollect()
End



Ein Resource-File kann auch Gruppen beinhalten, diese sind gleich wie bei INI-Dateien definiert:

Code: [AUSKLAPPEN]
[Version1]
HELLO_WORLD = Hallo Welt!

[Version2]
HELLO_WORLD = Gugu!


Nun kann man mit Localization.GetString("HELLO_WORLD", "Version2") die zweite Version abfragen, in dem Fall "Gugu!". Gibt man keine Gruppe an so wird der erste gefundene Wert verwendet, egal in welcher Gruppe.

Noch ein Hinweis zum Laden einer Resource-File: Die Sprache wird anhand des Dateinamens automatisch erkannt, jedoch nur diese beiden Formate:

name_de.extension (hier alles was zwischen _ und . ist)
name_de_zusatz.extension (alles was zwischen _ und _ ist)

Wenn die Datei ein anderes Format benutzt kann man die Sprache manuell angeben, als zweiten Parameter der Load-Funktionen.

Z.Bsp.: Localization.LoadResource("meineDatei.txt", "de")

Bei den Load-Funktionen mit dem Filter geht das jedoch nicht, der Filter sorgt nur dafür dass die entsprechenden Dateien zurückgegeben werden, geladen werden sie jeweils mit den normalen Funktionen (kann ich vielleicht irgendwann noch anpassen)


Für GUI-Anwendungen wo die Labels etc. nur am Anfang geladen werden empfiehlt sich OpenResource(). Bei Spielen etc. wo die Texte vielleicht mehrmals abgefragt werden, oder noch schlimmer in jedem Hauptschleifendurchlauf, empfehle ich LoadResource(), sonst kommt die Harddisk nicht mehr nach Smile



Hier noch das Modul bzw. die Include-File selbst Wink
Code: [AUSKLAPPEN]
SuperStrict

Type Localization
   Global currentLanguage:String
   Global supportedLanguages:TList
   Global Resources:TList
   
   'Set the current language   
   Function SetLanguage:Int(language:String)

      For Local lang:String = EachIn supportedLanguages
         If language = lang Then
            currentLanguage = language
            Return True
         EndIf
      Next
      
      Return False

   End Function
   
   
   'Returns the current language
   Function Language:String()
      Return currentLanguage
   End Function

         
   'Adds a comma separated list of languages to the supported languages list
   Function AddLanguages(languages:String)
      Local pos:Int = Instr(languages, ",")
      If pos = 0 Then
         supportedLanguages.AddLast(languages.Trim())
         Return
      EndIf
      
      Local lang:String
      While pos > 0
         supportedLanguages.AddLast(Left(languages, pos - 1).Trim())
         languages = Mid(languages, pos + 1)
         pos = Instr(languages, ",")
      Wend
      
      supportedLanguages.AddLast(languages.Trim())
   End Function
   
   
   'Opens a resource file (no memory used)
   Function OpenResource(filename:String)
      LocalizationStreamingResource.Open(filename)
   End Function

      
   'Loads the specified resource file into memory (faster, memory used)
   Function LoadResource(filename:String)
      LocalizationMemoryResource.Open(filename)
   End Function
   
   
   'Opens all resource files according to the filter (for example: myfile*.txt will open myfile_en.txt, myfile_de.txt etc.)
   Function OpenResources(filter:String)
      For Local file:String = EachIn GetResourceFiles(filter)
         OpenResource(file)
      Next
   End Function
   
   
   'Loads all resource files according to the filter (for example: myfile*.txt will load myfile_en.txt, myfile_de.txt etc.)
   Function LoadResources(filter:String)
      For Local file:String = EachIn GetResourceFiles(filter)
         LoadResource(file)
      Next
   End Function
   
   
   'Returns the value for the specified key, or an empty string if the key was not found
   Function GetString:String(key:String, group:String = Null)
      Local ret:String = ""

      For Local r:LocalizationResource = EachIn resources
         If r.language <> currentLanguage Then Continue
         ret = r.GetString(key, group)
         If ret <> Null Then Return ret
      Next
      
      Return ret
   End Function
   

   'Detects the language of a resource file   
   Function GetLanguageFromFilename:String(filename:String)
         Local lastpos:Int = 0
         Local pos:Int = Instr(filename, "_")

         'Look for the last occurence of "_"
         While pos > 0
            lastpos = pos
            pos = Instr(filename, "_", lastpos + 1)
         Wend
         
         If lastpos > 0
            pos = Instr(filename, "_", lastpos + 1)
            If pos > 0
               Return Mid(filename, lastpos + 1, pos - lastpos - 1)
            EndIf
         
            pos = Instr(filename, ".", lastpos + 1)
            If pos > 0
               Return Mid(filename, lastpos + 1, pos - lastpos - 1)
            EndIf
            
            Return Mid(filename, lastpos + 1)
         EndIf
         
         Return Null         
   End Function
   
   
   'Returns all resource files according to the filter
   Function GetResourceFiles:TList(filter:String)
      Local ret:TList = New TList
      Local pos:Int = Instr(filter, "*")

      If pos > 0

         Local prefix:String = Left(filter, pos - 1)
         Local suffix:String = Mid(filter, pos + 1)
         
         Local dir:String = ExtractDir(filter)
         Local dir_content:String[] = LoadDir(dir)
         
         prefix = Mid(prefix, dir.Length + 1)
         If Left(prefix, 1) = "/" Or Left(prefix, 1) = "\" Then prefix = Mid(prefix, 2)
         
         For Local file:String = EachIn dir_content
            If file.Length >= prefix.Length And Left(file, prefix.Length) = prefix
               If file.Length >= prefix.Length + suffix.Length And Right(file, suffix.Length) = suffix
                  ret.AddLast(dir + "/" + file)
               EndIf
            EndIf
         Next
         
      EndIf
            
      Return ret
   End Function
   
   
   'Releases all resources used by the Localization Module
   Function Dispose()
      For Local r:LocalizationResource = EachIn Resources
         r.Close()
      Next
      
      Resources.Clear()
      Resources = Null
      supportedLanguages = Null
   End Function
End Type

'Initialize
Localization.Resources = New TList
Localization.supportedLanguages = New TList







'resource file base type -----------------------------------------------------
Type LocalizationResource Abstract
   Field language:String
   Field _link:TLink

   Method GetString:String(key:String, group:String = Null) Abstract
   Method Close() Abstract
End Type



'resource type (uses a stream to read on demand, lower access, no memory used) ------------------
Type LocalizationStreamingResource Extends LocalizationResource
   Field stream:TStream


   'Opens a resource file
   Function Open:LocalizationStreamingResource(filename:String, language:String = Null)
      If language = Null Then
         language = Localization.GetLanguageFromFilename(filename)
         If language = Null Then Throw "No language was specified for loading the resource file and the language could not be detected from the filename itself.~r~nPlease specify the language or use the format ~qname_language.extension~q for the resource files."
      EndIf
      
      Local file:TStream = ReadFile(filename)
      If file = Null Then Throw "The resource file ~q" + filename + "~q was not found or could not be opened for reading."
      
      Local r:LocalizationStreamingResource = New LocalizationStreamingResource
      r.language = language
      r.stream = file
      r._link = Localization.resources.AddLast(r)
   End Function
   
   
   'Gets the value for the specified key
   Method GetString:String(key:String, group:String = Null)
      If stream = Null Then Return Null
      stream.Seek(0)
      
      Local line:String
      Local _key:String
      Local value:String
      Local skip:Int = False
      Local pos:Int = 0
      
      While Not Eof(stream)
         line = ReadLine(stream).Trim()

         'If a group was specified, look for the group and skip lines (faster)
         If group <> Null

            If skip And Left(line, 1) <> "[" Then Continue
         
            If Left(line, 1) = "[" And Right(line, 1) = "]"
               If Mid(line, 2, line.Length - 2) <> group Then
                  skip = True
               Else
                  skip = False
               EndIf
            EndIf
            
         EndIf
         
         
         'Look for the key
         pos = Instr(line, "=")
         If pos > 0 Then
            _key = Left(line, pos - 1).Trim()
            value = Mid(line, pos + 1).Trim()
         EndIf

         If _key =  key Then Return value
      Wend
      
      'Not found, or maybe the wrong group was specified
      Return Null
   End Method


   'Close the resource file manually
   Method Close()
      If _link <> Null Then _link.Remove()
      If stream <> Null Then stream.Close()
   End Method

      
   'If there are no references to this resource, the object will be deleted automatically
   Method Delete()
      Close()
   End Method
End Type



'resource type (loads the resource file in the memory, faster access, increased memory usage) ----------------
Type LocalizationMemoryResource Extends LocalizationResource
   Field map:TMap
   
   'Opens a resource file and loads the content into memory
   Function Open:LocalizationMemoryResource(filename:String, language:String = Null)
      If language = Null Then
         language = Localization.GetLanguageFromFilename(filename)
         If language = Null Then Throw "No language was specified for loading the resource file and the language could not be detected from the filename itself.~r~nPlease specify the language or use the format ~qname_language.extension~q for the resource files."
      EndIf
   
      Local file:TStream = ReadFile(filename)
      If file = Null Then Throw "The resource file ~q" + filename + "~q was not found or could not be opened for reading."
      
      Local r:LocalizationMemoryResource = New LocalizationMemoryResource
      r.language = language
      r.map = New TMap
      r._link = Localization.resources.AddLast(r)

      Local line:String
      Local key:String
      Local value:String
      Local pos:Int = 0
      Local group:String = ""
      
      
      While Not Eof(file)
         line = ReadLine(file)

         If Left(line, 1) = "[" And Right(line, 1) = "]"
            group = Mid(line, 2, line.Length - 2).Trim()
         EndIf

         pos = Instr(line, "=")
         If pos > 0 Then
            key = Left(line, pos - 1).Trim()
            value = Mid(line, pos + 1).Trim()
         EndIf
         
         If key <> Null And key <> "" Then
            If group <> Null And group <> ""
               r.map.Insert(group + "::" + key, value)
               If r.map.ValueForKey(key) = Null Then r.map.Insert(key, value)
            Else
               r.map.Insert(key, value)
            EndIf
         EndIf
      Wend
      
      file.Close()
      
      Return r
   End Function

      
   'Gets the value for the specified key
   Method GetString:String(key:String, group:String = Null)
      Local ret:Object

      If group <> Null Then
         ret = map.ValueForKey(group + "::" + key)
      Else
         ret = map.ValueForKey(key)
      EndIf
      
      If ret = Null Then Return Null
      Return String(ret)
   End Method
   
   
   'Releases the used memory
   Method Close()
      If _link <> Null Then _link.Remove()
      If map <> Null Then map.Clear()
   End Method
   
   
   'If there are no references to this resource, the object will be deleted automatically
   Method Delete()
      Close()
   End Method
   
End Type

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group