WaBis

walter.bislins.ch

Datei: xlang.asp

Inhalt der Datei: ./asp/xlang/xlang.asp
<% Option Explicit %>
<%
' xlang.asp: Copyright (C) 2010 Walter Bislin
' http://walter.bislins.ch/doku/xlang

const XLANG_TEMPLATE = "xlang.txt"
const XLANG_FOLDER = "lang"
const XLANG_INCLUDE_SRC = "*.inc;*.asp" ' no spaces!
const XLANG_EXCLUDE_SRC = "*/xlang.*"   ' no spaces!

' util -----------------------------------------------------

function TestPattern( aString, aPattern, bIgnoreCase )
  dim re
  set re = new RegExp
  re.Multiline = false
  re.IgnoreCase = bIgnoreCase
  re.Global = false
  re.Pattern = aPattern
  TestPattern = re.Test(aString)
end function

function ReplacePattern( aString, aPattern, aReplace, bIgnoreCase )
  dim re
  set re = new RegExp
  re.Global = true
  re.Multiline = true
  re.IgnoreCase = bIgnoreCase
  re.Pattern = aPattern
  ReplacePattern = re.Replace( aString, aReplace )
end function

function DataGetNumD( aData, aDefault, byref aPos )
  dim p, s
  DataGetNumD = aDefault
  if Len(aData) = 0 then exit function
  p = InStr(aPos,aData,"|")
  if p > 0 then
    s = Mid(aData,aPos,p-aPos)
    if IsNumeric(s) then
      DataGetNumD = CLng(s)
      aPos = p + 1
    end if
  end if
end function

function DataGetStrD( aData, aDefaultStr, byref aPos )
  dim n
  DataGetStrD = aDefaultStr
  if Len(aData) = 0 then exit function
  n = DataGetNumD(aData,-1,aPos)
  if n = 0 then
    DataGetStrD = ""
  elseif n > 0 and aPos+n <= Len(aData) then
    DataGetStrD = Mid(aData,aPos,n)
    aPos = aPos + n + 1
  end if
end function

function DataGetStrArray( aData, byRef aPos )
  dim sz, i, arr
  sz = DataGetNumD(aData,0,aPos)
  if sz <= 0  then
    DataGetStrArray = Array()
  else
    redim arr(sz-1)
    for i = 0 to sz-1
      arr(i) = DataGetStrD(aData,"",aPos)
    next
    DataGetStrArray = arr
  end if
end function

function DataAddNum( aData, aNum )
  DataAddNum = aData & aNum & "|"
end function

function DataAddStr( aData, aStr )
  dim l, s
  l = Len(aStr)
  s = DataAddNum(aData,l)
  if l > 0 then
    s = s & aStr & "|"
  end if
  DataAddStr = s
end function

function DataAddStrArray( aData, aStrArray )
  dim i, s
  s = DataAddNum(aData,UBound(aStrArray)+1)
  for i = 0 to UBound(aStrArray)
    s = DataAddStr(s,aStrArray(i))
  next
  DataAddStrArray = s
end function

'-----------------

class CFileSystem
  private mFSO

  private sub Class_Initialize()
    set mFSO = Server.CreateObject("Scripting.FileSystemObject")
  end sub

  function MapPath( aRelativePath )
    ' returns the absolute path to aRelativePath
    if Len(aRelativePath) = 0 then
      MapPath = Server.MapPath(".")
    else
      MapPath = Server.MapPath(aRelativePath)
    end if
  end function

  function AppendSlash( aPath )
    AppendSlash = aPath
    if InStrRev(AppendSlash,"/") <> Len(AppendSlash) then
      AppendSlash = AppendSlash & "/"
    end if
  end function

  function AppendName( aPath, aName )
    AppendName = AppendSlash(aPath) & aName
  end function

  function GetFileName( aPath )
    dim p, name
    name = aPath
    p = InStrRev(name,"\")
    if p <= 1 then p = InStrRev(name,"/")
    if p > 0 then name = Right(name,Len(name)-p)
    GetFileName = name
  end function

  function GetBaseName( aPath )
    dim p, name
    name = GetFileName(aPath)
    p = InStrRev(name,".")
    if p > 0 then name = Left(name,p-1)
    GetBaseName = name
  end function

  function GetFolder( aRelPath )
    ' returns a Folder object
    set GetFolder = mFSO.GetFolder(MapPath(aRelPath))
  end function

  function FolderExists( aRelPath )
    on error resume next
    FolderExists = mFSO.FolderExists(MapPath(aRelPath))
    if Err <> 0 then
      FolderExists = false
      Err.Clear
    end if
  end function

  sub CreateFolder( aRelPath )
    dim path
    path = MapPath(aRelPath)
    if not mFSO.FolderExists(path) then
      mFSO.CreateFolder(path)
    end if
  end sub

  function FileExists( aRelPath )
    on error resume next
    FileExists = mFSO.FileExists(MapPath(aRelPath))
    if Err <> 0 then
      FileExists = false
      Err.Clear
    end if
  end function

  sub WriteFile( aRelPath, aText )
    dim file
    set file = mFSO.OpenTextFile(MapPath(aRelPath), 2, True)
    file.Write aText
    file.Close
  end sub

  function ReadFile( aRelPath )
    ' Require FileExists(aRelPath), "CFileSystem.ReadFile", "Nonexistent file, aRelPath = " & aRelPath
    dim file, tstream
    set file = mFSO.GetFile(MapPath(aRelPath))
    set tstream = file.OpenAsTextStream(1)
    if tstream.AtEndOfStream then
      ReadFile = ""
    else
      ReadFile = tstream.Readall
    end if
  end function

  function OpenFileForWriting( aRelPath )
    set OpenFileForWriting = mFSO.OpenTextFile(MapPath(aRelPath), 2, True)
  end function

  sub CopyFile( aRelSrcPath, aRelDestPath )
    dim srcPath, destPath
    srcPath = MapPath(aRelSrcPath)
    destPath = MapPath(aRelDestPath)
    if mFSO.FileExists(srcPath) then
      mFSO.CopyFile srcPath, destPath, true
    end if
  end sub

end class

dim FS
set FS = new CFileSystem

'---------------------

sub QuickSortX(aQuickSortable)
  if aQuickSortable.LastIx <= 0 then exit sub
  QuickSortRangeX aQuickSortable, aQuickSortable.FirstIx, aQuickSortable.LastIx
end sub

sub QuickSortRangeX( aQuickSortable, lo, hi )
  dim i, j, x
  i = lo
  j = hi
  x = CLng((lo+hi)/2)
  do while i <= j
    do while aQuickSortable.Compare(i,x) < 0
      i = i + 1
    loop
    do while aQuickSortable.Compare(j,x) > 0
      j = j - 1
    loop
    if i <= j then
      if i <> j then
        aQuickSortable.Exchange i, j
        if i = x then
          x = j
        elseif j = x then
          x = i
        end if
      end if
      i = i + 1
      j = j - 1
    end if
  loop
  ' recursion
  if lo < j then QuickSortRangeX aQuickSortable, lo, j
  if i < hi then QuickSortRangeX aQuickSortable, i, hi
end sub

'---------------------

const CDA_MIN_CHUNK_SIZE = 128
const CDA_MAX_CHUNK_INCREMENT = 4096

function NewDynArray( aSizeEstimate )
  ' set aSizeEstimate = 0 if final size is not known
  set NewDynArray = new CDynArray
  if aSizeEstimate > 0 then NewDynArray.SetSizeEstimate aSizeEstimate
end function

class CDynArray
  private Chunk ' Array of any
  private ChunkSize
  private ChunkFill

  property Get LastIx
    LastIx = ChunkFill - 1
  end property

  property Get Size
    Size = ChunkFill
  end property

  private sub Class_Initialize()
    Clear
  end sub

  sub Clear()
    Chunk = Array()
    ChunkSize = 0
    ChunkFill = 0
  end sub

  sub SetSizeEstimate( aSize )
    ' give a hint how big the array could grow, if you know
    ' clears the DynArray!
    ' require aSize > 0
    ChunkSize = aSize
    redim Chunk( ChunkSize-1 )
    ChunkFill = 0
  end sub

  private sub EnlargeArray()
    dim increment
    ' resize chunk
    increment = ChunkSize
    if increment < CDA_MIN_CHUNK_SIZE then increment = CDA_MIN_CHUNK_SIZE
    if increment > CDA_MAX_CHUNK_INCREMENT then increment = CDA_MAX_CHUNK_INCREMENT
    ChunkSize = ChunkSize + increment
    redim preserve Chunk(ChunkSize-1)
  end sub

  sub AddItem( aItem )
    ' assert ChunkFill <= ChunkSize
    if ChunkFill = ChunkSize then EnlargeArray
    ' assert ChunkFill < ChunkSize
    Chunk(ChunkFill) = aItem
    ChunkFill = ChunkFill + 1
  end sub

  sub AddObject( aObject )
    ' use this function for object type items instead of AddItem()
    ' assert ChunkFill <= ChunkSize
    if ChunkFill = ChunkSize then EnlargeArray
    ' assert ChunkFill < ChunkSize
    set Chunk(ChunkFill) = aObject
    ChunkFill = ChunkFill + 1
  end sub

  function GetItem( aIx )
    ' require ValidIndex(aIx)
    GetItem = Chunk(aIx)
  end function

  function GetObject( aIx )
    ' use this function for object type items instead of GetItem()
    ' require ValidIndex(aIx)
    set GetObject = Chunk(aIx)
  end function

  function ValidIndex( aIx )
    ValidIndex = (aIx >= 0 and aIx < ChunkFill)
  end function

  function GetArray( bClear )
    ' returns all added items in an array of the correct size
    ' clears the DynArray if bClear is true
    if ChunkSize > ChunkFill then
      redim preserve Chunk( ChunkFill-1 )
      ChunkSize = ChunkFill
    end if
    GetArray = Chunk
    if bClear then Clear
  end function

  function JoinItems( aSep, bClear )
    ' joins all items and returns the resulting big string
    ' clears the DynArray if bClear = true!
    ' note: if bClear is false, the array can be further expanded!
    JoinItems = Join( GetArray(bClear), aSep )
  end function
end class

' appli --------------------------------------------------

class CxLangItem
  public Src
  public Key
  public Text

  private sub Class_Initialize()
    Src = ""
    Key = ""
    Text = ""
  end sub
end class

class CxLangCollection
  private mItems    ' as CDynArray of CxLangItem
  private mItemDict ' as Dictionary of CxLangItem

  private sub Class_Initialize()
    set mItems = NewDynArray(0)
    set mItemDict = Server.CreateObject("Scripting.Dictionary")
    mItemDict.CompareMode = VBTextCompare
  end sub

  sub Clear()
    mItems.Clear
    mItemDict.RemoveAll
  end sub

  sub ParseSrcFile( aPath )
    ' search aPath for xMsg() messages and adds them to mItems if not already there
    dim squot, equot, dquot, qquot, lines, lineNr, i, line, p, item, oldItem, srcName
    dquot = Chr(1)
    squot = Chr(2)
    equot = Chr(3)
    qquot = equot & squot
    lines = Split( FS.ReadFile( aPath ), vbCRLF )
    lineNr = 1
    for i = 0 to UBound(lines)
      ' convert double quots in strings to squot char for easier parsing
      line = lines(i)
      line = ReplacePattern( line, """([^""]*)""", squot & "$1" & equot, false )
      line = Replace( line, qquot, dquot )
      line = Replace( line, squot, """" )
      line = Replace( line, equot, """" )
      p = 1
      do
        set item = ParseNextItem( line, p )
        if not item is Nothing then
          srcName = Replace( aPath, "./", "" )
          item.Key = ReplacePattern( item.Key, "\x01", """", false )
          item.Src = srcName & ": " & lineNr
          ' check if new
          if mItemDict.Exists(item.Key) then
            ' update src
            set oldItem = mItemDict.Item(item.Key)
            if InStr( oldItem.Src, srcName ) then
              oldItem.Src = oldItem.Src & "," & lineNr
            else
              oldItem.Src = oldItem.Src & "; " & item.Src
            end if
          else
            ' insert new item
            mItemDict.Add item.Key, item
            mItems.AddObject item
          end if
        end if
      loop until item is Nothing
      lineNr = lineNr + 1
    next
  end sub

  private function NextNoSpace( aLine, aLen, aPos )
    dim c, l
    NextNoSpace = -1
    while aPos <= aLen
      c = Mid(aLine,aPos,1)
      if c <> " " and c <> Chr(9) then
        NextNoSpace = aPos
        exit function
      end if
      aPos = aPos + 1
    wend
  end function

  private function IsValidItem( aLine, aLen, byRef aPos )
    ' returns position of first String " in aPos if IsValidItem = true
    dim ps, pe, c
    IsValidItem = false
    if aPos <= 0 then exit function
    ps = aPos + 4
    if ps > aLen then exit function
    c = Mid(aLine,ps,1)
    if IsNumeric(c) or c = "D" then
      ps = ps + 1
      if ps > aLen then exit function
    end if
    ps = NextNoSpace( aLine, aLen, ps )
    if ps <= 0 then exit function
    if Mid(aLine,ps,1) <> "(" then exit function
    ps = NextNoSpace( aLine, aLen, ps+1 )
    if ps <= 0 then exit function
    if Mid(aLine,ps,1) <> """" then exit function
    aPos = ps
    IsValidItem = true
  end function

  private function ParseNextItem( aLine, byRef aPos )
    ' parse 'xMsg' [any] '(' '"' [any] '"'
    ' e.g. xMsg("text"), xMsg1("text",var)
    dim ps, pe, l
    l = Len(aLine)
    set ParseNextItem = Nothing
    if aPos <= 0 then exit function
    ps = InStr( aPos, aLine, "xMsg" )
    while ps > 0
      if IsValidItem(aLine,l,ps) then
        ps = ps + 1
        pe = Instr( ps, aLine, """" )
        if pe <= 0 then exit function
        aPos = pe
        set ParseNextItem = new CxLangItem
        ParseNextItem.Key = Mid( aLine, ps, pe-ps )
        exit function
      end if
      ps = InStr( ps+4, aLine, "xMsg" )
    wend
  end function

  sub Load( aPath, bClearSrc )
    ' loads contents of file aPath (textfile) and adds its items
    ' Note: aPath only containes unique keys
    ' use bClearSrc to clear each Src field of the parsed file
    dim lines, item, oldItem, i, line, p, k, v
    lines = Split( FS.ReadFile( aPath ), vbCRLF )
    set item = new CxLangItem
    for i = 0 to UBound(lines)
      line = Trim(lines(i))
      if Len(line) > 0 then
        if Mid(line,1,1) <> "/" then
          p = InStr(line,"=")
          if p > 1 then
            k = Trim(Left(line,p-1))
            v = Trim(Right(line,Len(line)-p))
            if k = "Src" then
              set item = new CxLangItem
              if not bClearSrc then item.Src = v
            elseif k = "Key" then
              item.Key = Unmask(v)
            elseif k = "Txt" then
              item.Text = Unmask(v)
              ' check if new
              if mItemDict.Exists(item.Key) then
                ' update src (Note: keys should not be found more than once at all!)
                if not bClearSrc then
                  set oldItem = mItemDict.Item(item.Key)
                  if Len(oldItem.Src) > 0 then oldItem.Src = oldItemSrc & "; "
                  oldItem.Src = oldItem.Src & item.Src
                end if
              else
                mItemDict.Add item.Key, item
                mItems.AddObject item
              end if
            end if
          end if
        end if
      end if
    next
  end sub

  sub Save( aPath )
    dim file, i, items
    items = mItems.GetArray(false)
    set file = FS.OpenFileForWriting( aPath )
    for i = 0 to UBound(items)
      if Len(items(i).Src) = 0 then
        file.Write "Src = ?" & vbCRLF
      else
        file.Write "Src = " & items(i).Src & vbCRLF
      end if
      file.Write "Key = " & Mask(items(i).Key) & vbCRLF
      file.Write "Txt = " & Mask(items(i).Text) & vbCRLF
      file.Write vbCRLF
    next
    file.Close
  end sub

  sub SaveBinary( aPath )
    dim bin
    set bin = new CxLangBinary
    bin.InitFromItemList mItems.GetArray(false)
    bin.Save aPath
  end sub

  private function Mask( aStr )
    ' Mask some special keys and texts to keep blanks and quots like:
    ' [] -> [?]
    ' [ xxx ] -> [" xxx "]
    ' ["xxx"] -> [""xxx""]
    dim cs, ce
    if aStr = "" then
      Mask = "?"
    else
      cs = Mid(aStr,1,1)
      ce = Mid(aStr,Len(aStr),1)
      if cs = " " or cs = """" or ce = " " or ce = """" then
        Mask = """" & aStr & """"
      else
        Mask = aStr
      end if
    end if
  end function

  private function Unmask( aStr )
    dim cs, ce
    if aStr = "?" then
      Unmask = ""
    elseif aStr <> "" then
      cs = Mid(aStr,1,1)
      ce = Mid(aStr,Len(aStr),1)
      if cs = """" and ce = """" then
        Unmask = Mid(aStr,2,Len(aStr)-2)
      else
        Unmask = aStr
      end if
    else
      Unmask = ""
    end if
  end function

end class

class CxLangBinary
  private mKeys  ' Array of String
  private mTexts ' Array of String

  private sub Class_Initialize()
    mKeys = Array()
    mTexts = Array()
  end sub

  sub InitFromItemList( aItems )
    ' aItems as Array of CxLangItem
    dim c, i, k, p
    ' optimize entries: skip entries with no source and make auto translation of entries like "[spec] key" -> "key"
    c = 0
    for i = 0 to UBound(aItems)
      if aItems(i).Src = "" or aItems(i).Src = "?" then
        aItems(i).Text = ""
      else
        if aItems(i).Text = "" then
          ' Auto translate
          k = aItems(i).Key
          if Mid(k,1,1) = "[" then
            p = InStr(k,"]")
            if p > 0 then
              aItems(i).Text = Right(k,Len(k)-p-1)
            end if
          end if
        end if
      end if
      ' count active items (Text <> "")
      if aItems(i).Text <> "" then c = c + 1
    next
    ' redimension
    redim mKeys(c-1)
    redim mTexts(c-1)
    ' fill
    c = 0
    for i = 0 to UBound(aItems)
      if aItems(i).Text <> "" then
        mKeys(c) = aItems(i).Key
        mTexts(c) = aItems(i).Text
        c = c + 1
      end if
    next
    ' sort
    QuickSortX Me
  end sub

  sub Load( aPath )
    ' Require FS.FileExists(aPath)
    dim s, p
    s = FS.ReadFile( aPath )
    p = 1
    mKeys = DataGetStrArray( s, p )
    mTexts = DataGetStrArray( s, p )
  end sub

  sub Save( aPath )
    dim s1, s2
    s1 = DataAddStrArray( "", mKeys )
    s2 = DataAddStrArray( "", mTexts )
    FS.WriteFile aPath, s1 & s2
  end sub

  function Translate( aKey )
    dim i
    i = Find(aKey)
    if i >= 0 then
      Translate = mTexts(i)
      if Len(Translate) = 0 then Translate = aKey
    else
      Translate = aKey
    end if
  end function

  private function Find( aKey )
    ' binary search for aKey
    dim lo, hi, last, curr, cmp
    Find = -1
    lo = 0
    hi = UBound(mKeys)
    if hi < lo then exit function
    last = -1
    curr = CLng((lo+hi)/2)
    while curr <> last
      cmp = StrComp(mKeys(curr),aKey,1)
      if cmp = 0 then
        Find = curr
        exit function
      end if
      if cmp < 0 then
        lo = curr
      else
        hi = curr
      end if
      last = curr
      curr = CLng((lo+hi)/2)
    wend
  end function

  ' QuickSortable Interface

  property Get FirstIx()
    FirstIx = 0
  end property

  property Get LastIx()
    LastIx = UBound(mKeys)
  end property

  function Compare(i,j)
    dim a, b
    a = mKeys(i)
    b = mKeys(j)
    Compare = StrComp(a,b,1)
  end function

  sub Exchange(i,j)
    dim tmp
    tmp = mKeys(i)
    mKeys(i) = mKeys(j)
    mKeys(j) = tmp
    tmp = mTexts(i)
    mTexts(i) = mTexts(j)
    mTexts(j) = tmp
  end sub

end class

class CxLangApplication
  private mItems ' as CxLangCollection
  private mInclPattern
  private mExclPattern

  private sub Class_Initialize()
    set mItems = new CxLangCollection
    mInclPattern = FilePatternToRegExPattern(XLANG_INCLUDE_SRC)
    mExclPattern = FilePatternToRegExPattern(XLANG_EXCLUDE_SRC)
  end sub

  sub NewLanguage( aLang )
    dim templateFileName, langFolderName, langFileName
    if not FS.FolderExists(XLANG_FOLDER) then
      MakeTemplate
    end if
    templateFileName = FS.AppendName( XLANG_FOLDER, XLANG_TEMPLATE )
    if not FS.FileExists(templateFileName) then
      MakeTemplate
    end if
    ' assert template file exists
    langFolderName = FS.AppendName( XLANG_FOLDER, aLang )
    if not FS.FolderExists(langFolderName) then
      Response.Write "Creating Language Folder: " & langFolderName & "<br>" & vbCRLF
      Response.Flush
      FS.CreateFolder(langFolderName)
    end if
    langFileName = FS.AppendName( langFolderName, XLANG_TEMPLATE )
    if not FS.FileExists(langFileName) then
      Response.Write "Copying Template File to Language Folder. File is: " & langFileName & "<br>" & vbCRLF
      Response.Flush
      FS.CopyFile templateFileName, langFileName
    else
      Response.Write "Language File already exists: " & langFileName & "<br>" & vbCRLF
      Response.Flush
    end if
  end sub

  sub UpdateLanguage( aLang, bUpdateTemplate )
    dim templateFileName, langFolderName, langFileName
    if bUpdateTemplate then MakeTemplate
    templateFileName = FS.AppendName( XLANG_FOLDER, XLANG_TEMPLATE )
    langFolderName = FS.AppendName( XLANG_FOLDER, aLang )
    if not FS.FolderExists(langFolderName) then
      Response.Write "Language not found: " & aLang & "<br>" & vbCRLF
      Response.Flush
      exit sub
    end if
    langFileName = FS.AppendName( langFolderName, XLANG_TEMPLATE )
    if FS.FileExists(langFileName) then
      Response.Write "Updating Message file: " & langFileName & "<br>" & vbCRLF
      Response.Flush
      mItems.Clear
      mItems.Load langFileName, true
      mItems.Load templateFileName, false
      mItems.Save langFileName
    else
      Response.Write "Creating new Message file: " & langFileName & "<br>" & vbCRLF
      Response.Flush
      FS.CopyFile templateFileName, langFileName
    end if
  end sub

  sub UpdateAll()
    dim langHomeFolder, langFolders, folder
    MakeTemplate
    Response.Write "<br>Updating all Message Files:<br>" & vbCRLF
    Response.Flush
    set langHomeFolder = FS.GetFolder(XLANG_FOLDER)
    set langFolders = langHomeFolder.SubFolders
    for each folder in langFolders
      UpdateLanguage folder.Name, false
    next
  end sub

  sub CompileLanguage( aLang )
    dim langFolderName, langFileName, langBinFileName
    langFolderName = FS.AppendName( XLANG_FOLDER, aLang )
    if not FS.FolderExists(langFolderName) then
      Response.Write "Language not found: " & aLang & "<br>" & vbCRLF
      Response.Flush
      exit sub
    end if
    langFileName = FS.AppendName( langFolderName, XLANG_TEMPLATE )
    if FS.FileExists(langFileName) then
      Response.Write "Compiling Message file: " & langFileName & "<br>" & vbCRLF
      Response.Flush
      mItems.Clear
      mItems.Load langFileName, false
      langBinFileName = FS.AppendName( langFolderName, FS.GetBaseName(XLANG_TEMPLATE) & ".po" )
      mItems.SaveBinary langBinFileName
    else
      Response.Write "Message File not found: " & langFileName & "<br>" & vbCRLF
      Response.Flush
    end if
  end sub

  sub CompileAll()
    dim langHomeFolder, langFolders, folder
    Response.Write "<br>Compiling all Message Files:<br>" & vbCRLF
    Response.Flush
    set langHomeFolder = FS.GetFolder(XLANG_FOLDER)
    set langFolders = langHomeFolder.SubFolders
    for each folder in langFolders
      CompileLanguage folder.Name
    next
  end sub

  sub MakeTemplate()
    dim fileNames, i
    if not FS.FolderExists(XLANG_FOLDER) then
      Response.Write "Creating folder " & XLANG_FOLDER & "<br>" & vbCRLF
      Response.Flush
      FS.CreateFolder(XLANG_FOLDER)
    end if
    fileNames = GetSrcFileNames()
    for i = 0 to UBound(fileNames)
      Response.Write "Parsing " & Replace(fileNames(i),"./","") & "<br>" & vbCRLF
      Response.Flush
      mItems.ParseSrcFile fileNames(i)
    next
    Response.Write "Writing template file " & FS.AppendName( XLANG_FOLDER, XLANG_TEMPLATE ) & "<br>" & vbCRLF
    Response.Flush
    mItems.Save FS.AppendName( XLANG_FOLDER, XLANG_TEMPLATE )
  end sub

  private function GetSrcFileNames()
    dim fileNames
    set fileNames = NewDynArray(0)
    GetSrcFileNamesOfFolder ".", fileNames
    GetSrcFileNames = fileNames.GetArray(false)
  end function

  private sub GetSrcFileNamesOfFolder( aFolder, aFileNamesRet )
    ' returns all matching files names of aFolder and his subfolders recursively in aFileNamesRet
    ' aFolder as String: rel Path
    ' aFileNameret as CDynArray
    dim inclPattern, exclPattern, currFolder, subfolders, folder, files, fileNames, file, fileName

    ' first search for files in current folder
    set currFolder = FS.GetFolder(aFolder)
    set files = currFolder.Files
    for each file in files
      fileName = FS.AppendName( aFolder, file.Name )
      if TestPattern( fileName, mInclPattern, true ) then
        if not TestPattern( fileName, mExclPattern, true ) then
          aFileNamesRet.AddItem fileName
        end if
      end if
    next

    ' recursively scan subfolders for more files
    set subfolders = currFolder.SubFolders
    for each folder in subfolders
      GetSrcFileNamesOfFolder FS.AppendName( aFolder, folder.Name ), aFileNamesRet
    next
  end sub

  private function FilePatternToRegExPattern( aFilePattern )
    dim pat
    pat = aFilePattern
    pat = Replace( pat, ".", "\." )
    pat = Replace( pat, "*", ".*" )
    pat = Replace( pat, ";", "$|^" )
    pat = "^" & pat & "$"
    FilePatternToRegExPattern = pat
  end function
end class

' Main --------------------------------

sub ShowMenu()
  Response.Write "<h1>xlang: Message Translation Admin</h1>" & vbCRLF
  Response.Write "<p>Use this page to manage Message Files which contain translations of application messages.</p>"
  Response.Write "<p>See <a href=""http://walter.bislins.ch/doku/xlang"">xlang Documentation and Download</a>.</p>"
  Response.Write "<form name=""frm"" action=""xlang.asp"" method=""post"">" & vbCRLF

  Response.Write "<h2>Update Message Files</h2>" & vbCRLF
  Response.Write "<p>Scans all source files for xMsg() calls and makes an updated template file (" & FS.AppendName( XLANG_FOLDER, XLANG_TEMPLATE ) & ") containing all actual messages. After that, the messgage files for each language are updated with the new messages found in the source files. You have to translate the new messages and then compile the message files.</p>" & vbCRLF
  Response.Write "<p><input type=""submit"" name=""btnUpdate"" value=""Update Message Files""></p>" & vbCRLF

  Response.Write "<h2>Compile Message Files</h2>" & vbCRLF
  Response.Write "<p>Compiles all Message Files into binary Form. The Binaries are loaded into the application and accessed via xMsg() functions.</p>" & vbCRLF
  Response.Write "<p><input type=""submit"" name=""btnCompile"" value=""Compile Message Files""></p>" & vbCRLF

  Response.Write "<h2>Make New Language</h2>" & vbCRLF
  Response.Write "<p>Setup a new language translation. Copies the Template to the corresponding directory. The contents of this file must then be translated.</p>" & vbCRLF
  Response.Write "<p><input type=""text"" name=""lang"" value=""""> <input type=""submit"" name=""btnNewLang"" value=""New Language""></p>" & vbCRLF

  Response.Write "<h2>Make Template</h2>" & vbCRLF
  Response.Write "<p>Scans all source files for xMsg() calls and makes a template file (" & FS.AppendName( XLANG_FOLDER, XLANG_TEMPLATE ) & ") containing all messages. This template is used to create and update individual translation files for each language.</p>" & vbCRLF
  Response.Write "<p><input type=""submit"" name=""btnMake"" value=""Make Template""></p>" & vbCRLF

  Response.Write "</form>" & vbCRLF
end sub

sub UpdateFiles()
  dim xlang
  Response.Write "<h1>Updating Message Files</h1>" & vbCRLF
  Response.Flush
  set xlang = new CxLangApplication
  xlang.UpdateAll
  Response.Write "done" & vbCRLF
  Response.Write "<p><a href=""xlang.asp"">Back</a></p>" & vbCRLF
  Response.Flush
end sub

sub CompileFiles()
  dim xlang
  Response.Write "<h1>Compiling Message Files</h1>" & vbCRLF
  Response.Flush
  set xlang = new CxLangApplication
  xlang.CompileAll
  Response.Write "done" & vbCRLF
  Response.Write "<p><a href=""xlang.asp"">Back</a></p>" & vbCRLF
  Response.Flush
end sub

sub NewLanguage()
  dim xlang, lang
  lang = LCase(Trim(Request.QueryString("lang")))
  if Len(lang) = 0 then lang = LCase(Trim(Request.Form("lang")))
  if Len(lang) = 0 then
    ShowMenu
    exit sub
  end if
  Response.Write "<h1>Making New Language</h1>" & vbCRLF
  Response.Flush
  set xlang = new CxLangApplication
  xlang.NewLanguage lang
  Response.Write "<p><a href=""xlang.asp"">Back</a></p>" & vbCRLF
  Response.Flush
end sub

sub MakeTemplate()
  dim xlang
  Response.Write "<h1>Making Template</h1>" & vbCRLF
  Response.Flush
  set xlang = new CxLangApplication
  xlang.MakeTemplate
  Response.Write "done" & vbCRLF
  Response.Write "<p><a href=""xlang.asp"">Back</a></p>" & vbCRLF
  Response.Flush
end sub

sub LayoutHead( aThisFile, aPageName )
  Response.Write "<html><head>" & vbCRLF
  Response.Write "<title>" & aPageName & "</title>" & vbCRLF
  Response.Write "</head><body>" & vbCRLF
end sub

sub LayoutFoot()
  Response.Write "</body></html>" & vbCRLF
end sub

sub ProcessPage()
  dim id, op
  on error resume next

  op = Request.QueryString("op")
  if Len(Request.Form("btnUpdate"))  > 0 then op = "update"
  if Len(Request.Form("btnCompile")) > 0 then op = "compile"
  if Len(Request.Form("btnNewLang")) > 0 then op = "new"
  if Len(Request.Form("btnMake"))    > 0 then op = "make"

  LayoutHead "xlang.asp", "xlang: Program Message Translation Module"

  if op = "new" then
    NewLanguage
  elseif op = "update" then
    UpdateFiles
  elseif op = "compile" then
    CompileFiles
  elseif op = "make" then
    MakeTemplate
  else
    ShowMenu
  end if

  if Err <> 0 then
    Response.Write "<h4>Error:</h4><p>" & Err.Description & "</p>" & vbCRLF
    Err.Clear
  end if

  LayoutFoot
end sub

'stop
ProcessPage
%>
More Page Infos / Sitemap
Created Montag, 17. Oktober 2011
Scroll to Top of Page
Changed Dienstag, 3. November 2020