Simplest language system
Posted: Fri Jun 09, 2023 4:06 am
Hi #PB_All,
for an application I needed multiple translations. I searched the forum and found some suggestions and also clean and nice includes, but for me they were a bit too powerful (one even included grouping and such). Also I wanted to maintain the code better readable, aka leave the original texts in the code instead of a keyword or constant. This led me to this include, which I use in some programs. The advantage in my eyes is, that the code still contains the original text at its original place and that it doubles as a fallback, if the language file is incomplete or couldn't load at all. I don't know if this helps anyone or not, but maybe it does.
The include file:
The language file for the demo:
It should be pretty selfexplanatory, but in short:
for an application I needed multiple translations. I searched the forum and found some suggestions and also clean and nice includes, but for me they were a bit too powerful (one even included grouping and such). Also I wanted to maintain the code better readable, aka leave the original texts in the code instead of a keyword or constant. This led me to this include, which I use in some programs. The advantage in my eyes is, that the code still contains the original text at its original place and that it doubles as a fallback, if the language file is incomplete or couldn't load at all. I don't know if this helps anyone or not, but maybe it does.
The include file:
Code: Select all
Global NewMap Language.s()
Procedure LoadLanguageFile(file$,Flags=#PB_UTF8)
Protected file,input$,res,RegEx=CreateRegularExpression(#PB_Any,"^([^\|]+)\|(.*)$",#PB_RegularExpression_AnyNewLine|#PB_RegularExpression_MultiLine)
file=ReadFile(#PB_Any,file$,Flags|#PB_File_SharedRead)
If file
input$=ReadString(file,#PB_File_IgnoreEOL)
CloseFile(file)
ClearMap(Language())
If ExamineRegularExpression(RegEx,input$)
While NextRegularExpressionMatch(RegEx)
Language(RegularExpressionGroup(RegEx,1))=ReplaceString(RegularExpressionGroup(RegEx,2),"#CR",#CRLF$,#PB_String_NoCase)
Wend
EndIf
res=1
EndIf
FreeRegularExpression(RegEx)
ProcedureReturn res
EndProcedure
Procedure LoadLanguageString(input$)
Protected res,RegEx=CreateRegularExpression(#PB_Any,"^([^\|]+)\|(.*)$",#PB_RegularExpression_AnyNewLine|#PB_RegularExpression_MultiLine)
ClearMap(Language())
If ExamineRegularExpression(RegEx,input$)
While NextRegularExpressionMatch(RegEx)
Language(RegularExpressionGroup(RegEx,1))=ReplaceString(RegularExpressionGroup(RegEx,2),"#CR",#CRLF$,#PB_String_NoCase)
Wend
EndIf
FreeRegularExpression(RegEx)
ProcedureReturn #True
EndProcedure
Procedure LoadLanguageMem(*Mem,Flags=#PB_UTF8)
Protected input$,res,RegEx=CreateRegularExpression(#PB_Any,"^([^\|]+)\|(.*)$",#PB_RegularExpression_AnyNewLine|#PB_RegularExpression_MultiLine)
input$=PeekS(*Mem,-1,Flags)
ClearMap(Language())
If ExamineRegularExpression(RegEx,input$)
While NextRegularExpressionMatch(RegEx)
Language(RegularExpressionGroup(RegEx,1))=ReplaceString(RegularExpressionGroup(RegEx,2),"#CR",#CRLF$,#PB_String_NoCase)
Wend
EndIf
FreeRegularExpression(RegEx)
ProcedureReturn #True
EndProcedure
Procedure.s LangSEx(index$,standard$,Repl1$="",Repl2$="",Repl3$="",Repl4$="",Repl5$="")
If FindMapElement(Language(),index$)
standard$=Language(index$)
EndIf
If repl1$<>"":standard$=ReplaceString(standard$,"%s1",repl1$,#PB_String_NoCase):EndIf
If repl2$<>"":standard$=ReplaceString(standard$,"%s2",repl2$,#PB_String_NoCase):EndIf
If repl3$<>"":standard$=ReplaceString(standard$,"%s3",repl3$,#PB_String_NoCase):EndIf
If repl4$<>"":standard$=ReplaceString(standard$,"%s4",repl4$,#PB_String_NoCase):EndIf
If repl5$<>"":standard$=ReplaceString(standard$,"%s5",repl5$,#PB_String_NoCase):EndIf
ProcedureReturn standard$
EndProcedure
Procedure.s LangEx(index,standard$,Repl1$="",Repl2$="",Repl3$="",Repl4$="",Repl5$="")
Protected index$=Str(index)
If FindMapElement(Language(),index$)
standard$=Language(index$)
EndIf
If repl1$<>"":standard$=ReplaceString(standard$,"%s1",repl1$,#PB_String_NoCase):EndIf
If repl2$<>"":standard$=ReplaceString(standard$,"%s2",repl2$,#PB_String_NoCase):EndIf
If repl3$<>"":standard$=ReplaceString(standard$,"%s3",repl3$,#PB_String_NoCase):EndIf
If repl4$<>"":standard$=ReplaceString(standard$,"%s4",repl4$,#PB_String_NoCase):EndIf
If repl5$<>"":standard$=ReplaceString(standard$,"%s5",repl5$,#PB_String_NoCase):EndIf
ProcedureReturn standard$
EndProcedure
Procedure.s LangS(index$,standard$)
If FindMapElement(Language(),index$)
standard$=Language(index$)
EndIf
ProcedureReturn standard$
EndProcedure
Procedure.s Lang(index,standard$)
Protected index$=Str(index)
If FindMapElement(Language(),index$)
standard$=Language(index$)
EndIf
ProcedureReturn standard$
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
;Uncomment for language change (maybe need to change path and file):
;LoadLanguageFile("Test.lang")
OpenConsole(Lang(0,"Sprachtest"))
PrintN(Lang(1,"Willkommen zu PureBasic!"))
Print(Lang(2,"Was ist dein Name: "))
name$=Input()
PrintN(LangSEx("Name","Dein Name ist %s1",name$))
PrintN(LangS("Bye","Auf wiedersehen!"))
Input()
CompilerEndIf
Code: Select all
*Language file
*Usage: index|text
*Multiline text is not allowed -> for multilines use #CR
*All missing indices will be replaced by German standard text
*Keep an eye on leading or trailing spaces, they are not cut and sometimes are needed.
*The index number may be led or trailed by spaces/tabs to make the document more readable: " 1 |..."="1|...", but "1|..."<>"01|..."
*%s1...%s5 are placeholders which will be replace while running
0|Language test
1|Welcome to PureBasic!
2|What's your name:
Name|Your name is %s1
Bye|Good bye!
- Load the language file with LoadLanguageFile()
- If you use numerical indexes you can use Lang()/LangEx() to retrieve the texts, otherwise use LangS()/LangSEx()
- Indexes can contain almost anything but "|"
- New lines are replaced by #CR
- The Ex-versions of the Lang-functions allow replacements (see code)