Multilinguale Spieltexte

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

M0rgenstern

Betreff: Multilinguale Spieltexte

BeitragDo, Apr 26, 2012 12:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Leute.

Nachdem ich im Smalltalk ne Diskussion über mutlilinguale Spiele losgetreten habe wollte ich ausprobieren, wie schwierig sowas umzusetzen ist.
Ich muss sagen: Es war erstaunlich simpel.
Auf jeden Fall dachte ich, dass ich vielleicht nicht der einzige bin, der sowas gebrauchen kann.
Also möchte ich den Code einfach hier ins Forum packen.

Aber zuerst eine Erklärung:
Die Klasse liest erstmal alle vorhandenen Sprachen aus einer Datei aus.
Dann liest sie aus einer anderen Datei für jede Sprache die Namen für jede Taste auf der Tastatur aus (sowas kann man ja immer mal gebrauchen).
Und zum Schluss liest sie aus noch einer anderen Datei für jede Sprache alle strings aus, die im Spiel genutzt werden sollen.
Bei den strings und den Tasten ist darauf zu achten, dass gleiche strings auch die gleiche Kennung (bei Tasten ist das die zugehörige Nummer) haben. Das seht ihr aber unten in der Beispieldatei nochmal.

Edit: Habe noch einen Zusatz eingefügt.
Die Klasse beherrscht jetzt auch alternative Dateipfade.
Dazu benötigt man nur noch eine zusätzliche Datei, die für jede Sprache und jede Datei (die betroffen ist) den Default Pfad und den zu der Sprache zugehörigen Pfad angibt.
Code und Download wurden entsprechend angepasst.

Also:
Beispielprojekt: https://www.blitzforum.de/upload/file.php?id=11675

Code:
BlitzMax: [AUSKLAPPEN]
Type TTranslator
Global tlLanguages:TList
Global tmSavedStrings:TMap
Global tmKeyNames:TMap
Global tmPathesToLoad:TMap
Global sCurrentLanguage:String

rem
about: This function initializes the Translator. It reads out all the files. Required to call before using the Translator.
@psPathesPath has to be the path to the file where the alternative pathes for images sounds etc. which depend on the language are.
@psStringPath has to be the path to the file where the strings (ingame texts) are.
@psKeyPath has to be the path to the file where the keynames are.
@psAvailableLanguagesPath has to be the path to the file where the available languages are.
endrem

Function Initialize(psPathesPath:String, psStringsPath:String, psKeyPath:String, psAvailableLanguagesPath:String)
tlLanguages = New TList
tmSavedStrings = New TMap
tmKeyNames = New TMap
tmPathesToLoad = New TMap

LoadLanguages(psAvailableLanguagesPath)
LoadKeyNames(psKeyPath)
LoadStrings(psStringsPath)
LoadPathes(psPathesPath)

sCurrentLanguage = Lower(String(tlLanguages.Last()))

End Function

rem
about: This function reads all available languages from the file @psAvailableLanguagesPath.
endrem

Function LoadLanguages(psAvailableLanguagesPath:String)
Local tsStream:TStream = ReadFile(psAvailableLanguagesPath)

Repeat
Local sLine:String = tsStream.ReadLine()
tlLanguages.AddLast(sLine)
Until(tsStream.Eof())

tsStream.Close()
End Function

rem
about: This function reads all keynames in all languages from the file @psKeyPath.
endrem

Function LoadKeyNames(psKeyPath:String)
Local tsStream:TStream

For Local lang:String = EachIn tlLanguages
tsStream = ReadFile(psKeyPath)
__ReadKeysForLanguage(lang, tsStream)
CloseFile(tsStream)
Next

End Function

rem
about: This function reads all strings in all languages from the file @psStringPath.
endrem

Function LoadStrings(psStringsPath:String)
Local tsStream:TStream

For Local lang:String = EachIn tlLanguages
tsStream = ReadFile(psStringsPath)
__ReadStringsForLanguage(lang, tsStream)
CloseFile(tsStream)
Next

End Function

rem
about: This function reads all pathes (for alternative files) from the file @psPathesPath.
endrem

Function LoadPathes(psPathesPath:String)
Local tsStream:TStream

For Local Lang:String = EachIn tlLanguages
tsStream = ReadFile(psPathesPath)
__ReadPathesForLanguage(Lang, tsStream)
CloseFile(tsStream)
Next
End Function

rem
about: This function reads all strings for a given language @psLanguage from the file @ptsStream.
endrem

Function __ReadStringsForLanguage(psLanguage:String, ptsStream:TStream)
Local sLang:String = "[" + psLanguage + "]"

While Not (Eof(ptsStream))
Local sLine:String = ptsStream.ReadLine()
If(Lower(sLine) = Lower(sLang)) Then
Local bEnd:Byte = False
Repeat
bEnd = False
sLine = ptsStream.ReadLine()
bEnd = (Left(sLine, 1) = "[")
bEnd = bEnd Or (Trim(sLine) = "")
If(Not bEnd) Then
Local sStringName:String = GetLeftPart(sline)
Local sStringValue:String = GetValue(sLine)
tmSavedStrings.Insert(Lower(sStringName) + Lower(psLanguage), sStringValue)
EndIf
Until bEnd
EndIf
Wend
End Function

rem
about: This function reads all keys for a given language @psLanguage from the file @ptsStream.
endrem

Function __ReadKeysForLanguage(psLanguage:String, ptsStream:TStream)
Local sLang:String = "[" + psLanguage + "]"

While Not(Eof(ptsStream))
Local sLine:String = ptsStream.ReadLine()
If(Lower(sLine) = Lower(sLang)) Then
Repeat
sLine = ptsStream.ReadLine()
If(Not(Left(sLine, 1) = "[")) Then
If(Not (Trim(sLine) = "")) Then
Local sKeyName:String = GetLeftPart(sLine)
Local sKeyNumber:String = GetValue(sline)
tmKeyNames.Insert(sKeyNumber + Lower(psLanguage), sKeyName)
EndIf
EndIf
Until(Left(sLine, 1) = "[" Or Eof(ptsStream))
EndIf
Wend
End Function

rem
about: This function reads all paths for a given language @psLanguage from the file @ptsStream.
endrem

Function __ReadPathesForLanguage(psLanguage:String, ptsStream:TStream)
Local sLang:String = "[" + psLanguage + "]"

While Not(Eof(ptsStream))
Local sLine:String = ptsStream.ReadLine()
If(Lower(sLine) = Lower(sLang)) Then
Local bEnd:Byte = False
Repeat
bEnd = False
sLine = ptsStream.ReadLine()
bEnd = (Left(sLine, 1) = "[")
bEnd = bEnd Or (Trim(sLine) = "")
If(Not bEnd) Then
Local sDefaultPath:String = GetLeftPart(sline)
Local sLanguagePath:String = GetValue(sLine)
DebugLog("Inserted: " + sLanguagePath + " with: " + sDefaultPath + Lower(psLanguage))
tmPathesToLoad.Insert(sDefaultPath + Lower(psLanguage), sLanguagePath)
EndIf
Until bEnd
EndIf
Wend
End Function

rem
about: This function returns a file path of a file which depends on the language. Therefore it needs the default path @psDefaultPath and the current language @psLanguage.
If the file is not available in the chosen language or it doesn__COMMENT1__
endrem

Function GetFilePath:String(psDefaultPath:String, psLanguage:String = "")
If(psLanguage = "") Then psLanguage = sCurrentLanguage
DebugLog("Debug: " + psDefaultPath)

If Not(tmPathesToLoad.Contains(psDefaultPath + Lower(psLanguage))) Then
DebugLog("Returns: " + psDefaultPath)
Return psDefaultPath
EndIf

DebugLog("Should be: " + String(tmPathesToLoad.ValueForKey(psDefaultPath + Lower(psLanguage))))

Return String(tmPathesToLoad.ValueForKey(psDefaultPath + Lower(psLanguage)))
End Function

rem
about: This function returns the name of the key with the number @piKeyNumber in the language @psLanguage.
endrem

Function GetKeyName:String(piKeyNumber:Int, psLanguage:String = "")
If(psLanguage = "") Then psLanguage = sCurrentLanguage

Return String(tmKeyNames.ValueForKey(String(piKeyNumber) + Lower(psLanguage)))
End Function

rem
about: This function returns the string which belongs to the name @psStringName in the language @psLanguage without parsing any variables.
endrem

Function GetSingleString:String(psStringName:String, psLanguage:String = "")
If(psLanguage = "") Then psLanguage = sCurrentLanguage

Return String(tmSavedStrings.ValueForKey(Lower(psStringName) + Lower(psLanguage)))
End Function

rem
about: This function returns a string which belogs to the name @psStringName in the language @psLanguage by replacing the variables with strings from the array @psVariables.
endrem

Function GetFixedString:String(psStringName:String, psVariables:String[], psLanguage:String = "")
If(psLanguage = "") Then psLanguage = sCurrentLanguage

Return __FixString(GetSingleString(psStringName, psLanguage), psVariables)
End Function

rem
about: This function replaces all variables in the string @psString with values from @psVariables.
endrem

Function __FixString:String(psString:String, psVariables:String[])
For Local index:Int = 0 Until psVariables.Length
If (psString.Contains("&" + String(index + 1))) Then
psString = psString.Replace("&" + String(index + 1), psVariables[index])
EndIf
Next

Return psString
End Function

rem
about: Returns the value of a line @psLine from an Ini-File. (It returns what is on the right side of "=")
endrem

Function GetValue:String(psLine:String)
If Instr(psLine, "=") > 0 Then
Return Right(psLine, Len(psLine) - Instr(psLine, "="))
Else
Return ""
EndIf
End Function

rem
about: Returns the keyword of a line @psLine from an Ini-File. (It returns what is on the left side of "=")
endrem

Function GetLeftPart:String(psLine:String)
If Instr(psLine, "=") > 0 Then
Return Left(psLine, Instr(psLine, "=") - 1)
Else
Return ""
EndIf
End Function
End Type


Beispielprogramm:

BlitzMax: [AUSKLAPPEN]
SuperStrict
Include "Inc/Translator.bmx"

Graphics(1024, 768)

Global tfFrameTimer:TTimer = TTimer.Create(60) 'Frame Timer

Local font:TImageFont = LoadImageFont("Arial", 15, SMOOTHFONT)
SetImageFont(font) 'Standard imagefont

AutoMidHandle(True)
SeedRnd(MilliSecs())

TTranslator.Initialize("Data/dat/texts/Pathes.ini", "Data/dat/texts/IngameTextLines.ini", "Data/dat/lang/KeyNames.ini", "Data/dat/lang/Languages.ini")

Global iSpacePressed:Int = 0, iScore:Int = 0

Global timgTestImage:TImage = LoadImage(TTranslator.GetFilePath("Data/gfx/backgrounds/default/TestBack.png", "Spanish"))

'Mainloop
While Not (KeyHit(KEY_ESCAPE) Or AppTerminate())
Cls
WaitTimer(tfFrameTimer) 'Wait for the timer

Local keySp:Int = KeyHit(KEY_SPACE)

If(keySp) Then
If(TTranslator.sCurrentLanguage = "English") Then
TTranslator.sCurrentLanguage = "Deutsch"
Else
TTranslator.sCurrentLanguage = "English"
EndIf
iSpacePressed:+1
iScore:+20
timgTestImage = LoadImage(TTranslator.GetFilePath("Data/gfx/backgrounds/default/TestBack.png"))
EndIf

Local sArray:String[] = [String(iScore)]
Local sArray2:String[] = ["100"]
Local sArray3:String[] = ["100", String(iScore), String(iSpacePressed)]

DrawImage(timgTestImage, 400, 200)

DrawText(TTranslator.GetFixedString("Score", sArray), 100.0, 70.0)
DrawText(TTranslator.GetFixedString("LifeEnergy", sArray2), 100.0, 90.0)
DrawText(TTranslator.GetFixedString("Stats", sArray3), 100.0, 150.0)


Flip 0
Wend


Die Dateien sehen dann zum Beispiel so aus:
Sprachen:
Zitat:
English
Deutsch


Alternative Medienpfade:
Zitat:
[Deutsch]
Data/gfx/backgrounds/default/TestBack.png=Data/gfx/backgrounds/de/TestBack.png

[English]
Data/gfx/backgrounds/default/TestBack.png=Data/gfx/backgrounds/en/TestBack.png


Beispielstrings:
Zitat:
[Deutsch]
Score=Punktestand: &1
LifeEnergy=Energie: &1
Stats=Statistik: Energie: &1 | Punktestand: &2 | Leertaste betätigt: &3

[English]
Score=Score: &1
LifeEnergy=Energy: &1
Stats=Statistics: Energy: &1 | Score: &2 | Space Presses: &3


Tasten:
Code: [AUSKLAPPEN]
[English]
Backspace=8
Tab=9
Clear=12
Return=13
Enter=13
Pause=19
Caps Lock=20
Escape=27
Space=32
Page Up=33
Page Down=34
End=35
Home=36
Cursor (Left)=37
Cursor (Up)=38
Cursor (Right)=39
Cursor (Down)=40
Select=41
Print=42
Execute=43
Screen=44
Insert=45
Delete=46
Help=47
0=48
1=49
2=50
3=51
4=52
5=53
6=54
7=55
8=56
9=57
A=65
B=66
C=67
D=68
E=69
F=70
G=71
H=72
I=73
J=74
K=75
L=76
M=77
N=78
O=79
P=80
Q=81
R=82
S=83
T=84
U=85
V=86
W=87
X=88
Y=89
Z=90
Sys key (Left)=91
Sys key (Right)=92
Ziffernblock 0=96
Ziffernblock 1=97
Ziffernblock 2=98
Ziffernblock 3=99
Ziffernblock 4=100
Ziffernblock 5=101
Ziffernblock 6=102
Ziffernblock 7=103
Ziffernblock 8=104
Ziffernblock 9=105
Ziffernblock *=106
Ziffernblock +=107
Ziffernblock /=108
Ziffernblock -=109
Ziffernblock .=110
Ziffernblock /=111
F1=112
F2=113
F3=114
F4=115
F5=116
F6=117
F7=118
F8=119
F9=120
F10=121
F11=122
F12=123
Num Lock=144
Scroll Lock=145
Shift (Left)=160
Shift (Right)=161
Control (Left)=162
Control (Right)=163
Alt key (Left)=164
Alt key (Right)=165
Tilde=192
Minus=107
Equals=109
Bracket (Open)=219
Bracket (Close)=221
Backslash=226
Semicolon=186
Quote=222
Comma=188
Period=190
Slash=191

[Deutsch]
Rücktaste=8
Tab=9
Löschen=12
Return=13
Enter=13
Pause=19
Caps Lock=20
Escape=27
Leertaste=32
Bild Aufwärts=33
Bild Abwärts=34
End=35
Home=36
Pfeiltaste (Links)=37
Pfeiltaste (Hoch)=38
Pfeiltaste (Rechts)=39
Pfeiltaste (Runter)=40
Select=41
Drucken=42
Ausführen=43
Bildschirm=44
Einfügen=45
Löschen=46
Hilfe=47
0=48
1=49
2=50
3=51
4=52
5=53
6=54
7=55
8=56
9=57
A=65
B=66
C=67
D=68
E=69
F=70
G=71
H=72
I=73
J=74
K=75
L=76
M=77
N=78
O=79
P=80
Q=81
R=82
S=83
T=84
U=85
V=86
W=87
X=88
Y=89
Z=90
Systemtaste (Links)=91
Systemtaste (Rechts)=92
Ziffernblock 0=96
Ziffernblock 1=97
Ziffernblock 2=98
Ziffernblock 3=99
Ziffernblock 4=100
Ziffernblock 5=101
Ziffernblock 6=102
Ziffernblock 7=103
Ziffernblock 8=104
Ziffernblock 9=105
Ziffernblock *=106
Ziffernblock +=107
Ziffernblock /=108
Ziffernblock -=109
Ziffernblock .=110
Ziffernblock /=111
F1=112
F2=113
F3=114
F4=115
F5=116
F6=117
F7=118
F8=119
F9=120
F10=121
F11=122
F12=123
Num Lock=144
Scroll Lock=145
Shift (Links)=160
Shift (Rechts)=161
Steuerung (Links)=162
Steuerung (Rechts)=163
Alt=164
AltGr=165
Tilde=192
Minus=107
Gleich=109
Klammer (Offen)=219
Klammer (Geschlossen)=221
Backslash=226
Semicolon=186
Quote=222
Komma=188
Punkt=190
Slash=191


Lg, M0rgenstern

Edit v BladeRunner: Habe mir erlaubt die Tastendingsis in eine Codebox zu packen damit der Post nicht so ewig lang ist.

Edit von M0rgenstern: Wünsche Eingebaut.
  • Zuletzt bearbeitet von M0rgenstern am Fr, Apr 27, 2012 15:57, insgesamt 2-mal bearbeitet
 

PhillipK

BeitragDo, Apr 26, 2012 12:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Schaut subba aus Smile

Allerdings hab ich als absoluter fauler mensch dann doch was zu bemängeln:
BlitzMax: [AUSKLAPPEN]
TTranslator.GetFixedString("Stats", TTranslator.sCurrentLanguage, sArray3)


TTranslator.sCurrentLanguage ist in 99% der fälle wahrscheinlich das, was man nutzen möchte.
Daher mein faulheitsvorschlag: Dreh die parameter um!

BlitzMax: [AUSKLAPPEN]
	Function GetFixedString:String(psStringName:String, psVariables:String[], psLanguage:String = "")
If (Len(psLanguage) = 0) Then ..
psLanguage = TTranslator.sCurrentLanguage
Return __FixString(GetSingleString(psStringName, psLanguage), psVariables)
End Function


Dann isses doch absolut perfekt Wink Leichter zu lesen, weniger zu schreiben - und auch bei BCC's mit Codebeschränkung einfacher Smile

Ansonsten: Danke fürs teilen, super arbeit =)

M0rgenstern

BeitragDo, Apr 26, 2012 17:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey PhillipK:
Habe das ganze umgebaut. Hast schon Recht, ist wirklich angenehmer so.
Keine Ahnung, warum ichs in die Mitte gesteckt hatte, bei den anderen wars auch am Ende.

Lg, M0rgenstern

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group