aboutsummaryrefslogblamecommitdiffstats
path: root/Game/Code/Classes/ULanguage.pas
blob: 679f64057525d44c35f06f0c596850dd61ae04d5 (plain) (tree)











































































































































































































































                                                                                           
unit ULanguage;

interface

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
                

type
  TLanguageEntry = record
    ID:     string;
    Text:   string;
  end;

  TLanguageList = record
    Name:     string;
    {FileName: string; }
  end;

  TLanguage = class
    public
      Entry:  array of TLanguageEntry; //Entrys of Chosen Language
      SEntry: array of TLanguageEntry; //Entrys of Standard Language
      CEntry: array of TLanguageEntry; //Constant Entrys e.g. Version
      Implode_Glue1, Implode_Glue2: String;
    public
      List:   array of TLanguageList;

      constructor Create;
      procedure LoadList;
      function Translate(Text: String): String;
      procedure ChangeLanguage(Language: String);
      procedure AddConst(ID, Text: String);
      procedure ChangeConst(ID, Text: String);
      function Implode(Pieces: Array of String): String;
  end;

var
  Language:     TLanguage;

implementation

uses UMain,
     // UFiles,
     UIni,
     IniFiles,
     Classes,
     SysUtils,
     {$IFDEF win32}
     windows,
     {$ENDIF}
     ULog;

//----------
//Create - Construct Class then LoadList + Standard Language + Set Standard Implode Glues
//----------
constructor TLanguage.Create;
var
  I, J: Integer;
begin
  LoadList;

  //Set Implode Glues for Backward Compatibility
  Implode_Glue1 := ', ';
  Implode_Glue2 := ' and ';

  if (Length(List) = 0) then //No Language Files Loaded -> Abort Loading
    Log.CriticalError('Could not load any Language File');

  //Standard Language (If a Language File is Incomplete)
  //Then use English Language
  for I := 0 to high(List) do //Search for English Language
  begin
    //English Language Found -> Load
    if Uppercase(List[I].Name) = 'ENGLISH' then
    begin
      ChangeLanguage('English');

      SetLength(SEntry, Length(Entry));
      for J := low(Entry) to high(Entry) do
        SEntry[J] := Entry[J];

      SetLength(Entry, 0);
      
      Break;
    end;

    if (I = high(List)) then
      Log.LogError('English Languagefile missing! No standard Translation loaded');
  end;
  //Standard Language END
  
end;

//----------
//LoadList - Parse the Language Dir searching Translations
//----------
procedure TLanguage.LoadList;
var
  SR:     TSearchRec;   // for parsing directory
begin
  SetLength(List, 0);
  SetLength(ILanguage, 0);

  if FindFirst(LanguagesPath + '*.ini', 0, SR) = 0 then begin
    repeat
      SetLength(List, Length(List)+1);
      SetLength(ILanguage, Length(ILanguage)+1);
      SR.Name := ChangeFileExt(SR.Name, '');

      List[High(List)].Name := SR.Name;
      ILanguage[High(ILanguage)] := SR.Name;

    until FindNext(SR) <> 0;
  SysUtils.FindClose(SR);
  end; // if FindFirst
end;

//----------
//ChangeLanguage - Load the specified LanguageFile
//----------
procedure TLanguage.ChangeLanguage(Language: String);
var
  IniFile:    TIniFile;
  E:          integer; // entry
  S:          TStringList;
begin
  SetLength(Entry, 0);
  IniFile := TIniFile.Create(LanguagesPath + Language + '.ini');
  S := TStringList.Create;

  IniFile.ReadSectionValues('Text', S);
  SetLength(Entry, S.Count);
  for E := 0 to high(Entry) do
  begin
    if S.Names[E] = 'IMPLODE_GLUE1' then
      Implode_Glue1 := S.ValueFromIndex[E]+ ' '
    else if S.Names[E] = 'IMPLODE_GLUE2' then
      Implode_Glue2 := ' ' + S.ValueFromIndex[E] + ' ';

    Entry[E].ID := S.Names[E];
    Entry[E].Text := S.ValueFromIndex[E];
  end;

  S.Free;
  IniFile.Free;
end;

//----------
//Translate - Translate the Text
//----------
Function TLanguage.Translate(Text: String): String;
var
  E:    integer; // entry
begin
  Result := Text;
  Text := Uppercase(Result);

  //Const Mod
  for E := 0 to high(CEntry) do
    if Text = CEntry[E].ID then
    begin
     Result := CEntry[E].Text;
     exit;
    end;
  //Const Mod End

  for E := 0 to high(Entry) do
    if Text = Entry[E].ID then
    begin
     Result := Entry[E].Text;
     exit;
    end;

  //Standard Language (If a Language File is Incomplete)
  //Then use Standard Language
    for E := low(SEntry) to high(SEntry) do
      if Text = SEntry[E].ID then
      begin
        Result := SEntry[E].Text;
        Break;
      end;
  //Standard Language END
end;

//----------
//AddConst - Add a Constant ID that will be Translated but not Loaded from the LanguageFile
//----------
procedure TLanguage.AddConst (ID, Text: String);
begin
  SetLength (CEntry, Length(CEntry) + 1);
  CEntry[high(CEntry)].ID := ID;
  CEntry[high(CEntry)].Text := Text;
end;

//----------
//ChangeConst - Change a Constant Value by ID
//----------
procedure TLanguage.ChangeConst(ID, Text: String);
var
  I: Integer;
begin
  for I := 0 to high(CEntry) do
  begin
    if CEntry[I].ID = ID then
    begin
     CEntry[I].Text := Text;
     Break;
    end;
  end;
end;

//----------
//Implode - Connect an Array of Strings with ' and ' or ', ' to one String
//----------
function TLanguage.Implode(Pieces: Array of String): String;
var
  I: Integer;
begin
  Result := '';
  //Go through Pieces
  for I := low(Pieces) to high(Pieces) do
  begin
    //Add Value
    Result := Result + Pieces[I];

    //Add Glue
    if (I < high(Pieces) - 1) then
      Result := Result + Implode_Glue1
    else if (I < high(Pieces)) then
      Result := Result + Implode_Glue2;
  end;
end;

end.