Monday, June 17, 2013

Welcome, gettext, this is VBasic script

Task description
There is a project containing thousands of CPP sources that have to be localized into Chinese ASAP. We're using gettext technique for localization and strings to be translated have to be wrapped with _(), for example:
::MessageBox( _("Translate me please"), _("Warning"), MB_OK)
We can run Visual Studio Find In Files->Current File for each file with the following regexp:
\".*\" 
in order to search all strings, а then insert _('s and )'s.
But this is dull and boring, so let's switch on the brains and write a VisualBasic script in VBasic IDE (Alt-F11) which can be invoked by pressing F5 (or whatever you like, use Tools->Customize-Keyboard to setup hotkey).
Now just you have to traverse "Find Results" window by pressing F4 and optionally pressing F5 on each string that should be wrapped with _(). You can even avoid watching into .cpp source in simple cases with MessageBoxes (90% of strings). This way you reduce summary time  of processing all the .cpp sources for at least thrice, and even five times.

Here is VBasic Script. Note that it even handles multiline strings!



VBasic Script
Public Module Module1

    'Look for 1st " character ignoring any other alphanum characters
    Sub LookupMultilineBegining(ByVal sel As TextSelection)
        While Not sel.ActivePoint.AtEndOfDocument()
            sel.CharRight(True, 1)
            If Right(sel.Text, 1) = """" Then
                sel.Collapse()
                sel.CharLeft(False, 1)
                Exit While
            End If
        End While
    End Sub

    'Look for 1st " character ignoring any other alphanum characters
    Function LookupStringBegining(ByVal sel As TextSelection) As Boolean
        Dim res As Boolean
        res = False
        While Not sel.ActivePoint.AtEndOfDocument()
            sel.CharRight(True, 1)
            Dim chr As Char
            chr = Right(sel.Text, 1)
            If chr = """" Then
                sel.Collapse()
                res = True
                Exit While
            ElseIf Not (chr = " " Or chr = vbTab Or chr = vbCr Or chr = vbLf Or chr = vbCrLf) Then
                res = False
                Exit While
            End If
        End While
        Return res
    End Function

    'Look end of C++ string and places curser after " character
    Function LookupStringEnding(ByVal sel As TextSelection) As Boolean
        Dim res As Boolean
        res = False
        While Not sel.ActivePoint.AtEndOfLine()
            sel.CharRight(True, 1)
            If Right(sel.Text, 1) = """" And Not Right(sel.Text, 2) = "\""" Then
                sel.Collapse()
                res = True
                Exit While
            End If
        End While
        Return res
    End Function

    Sub InsertGetTextUnderscore()
        ' Description: Comments out a selected block of text.
        Dim sel As TextSelection
        sel = DTE.ActiveDocument.Selection

        'Look for 1st " character ignoring any other alphanum characters
        LookupMultilineBegining(sel)

        'Wrap string with _( ... )
        sel.CharRight(True, 1)
        If sel.Text = """" Then
            sel.Text = "_("""
            If LookupStringEnding(sel) Then
                sel.Text = ")"
            End If
        Else
            sel.Collapse()
        End If

    End Sub

    Enum MultilineParseState
        Start       'Before first " of multiline
        OutsideLine 'Before or after           "Some С++ string with \"Escape\" characters", probably it is a multiline
        Finished    'Non-space character after "Some С++ string with \"Escape\" characters", multiline finished
    End Enum

    Sub InsertGetTextUnderscoreMultiline()
        ' Description: Comments out a selected block of text.
        Dim CommentType As String
        Dim sel As TextSelection
        sel = DTE.ActiveDocument.Selection
        Dim state As MultilineParseState
        state = MultilineParseState.Start
        Dim insertPointer As Integer

        'Wrap muiltiline string with _( ... )
        While (Not state = MultilineParseState.Finished)
            If (state = MultilineParseState.Start) Then
                'Look for 1st " character ignoring any other alphanum characters
                LookupMultilineBegining(sel)

                'insert _(
                sel.CharRight(True, 1)
                If sel.Text = """" Then
                    sel.Text = "_("""
                    If LookupStringEnding(sel) Then
                        'remember where to insert )
                        insertPointer = sel.ActivePoint.AbsoluteCharOffset()
                        state = MultilineParseState.OutsideLine
                    Else
                        state = MultilineParseState.Finished
                    End If
                Else
                    sel.Collapse()
                    state = MultilineParseState.Finished
                End If
            ElseIf (state = MultilineParseState.OutsideLine) Then
                'Look for 1st " character
                If LookupStringBegining(sel) Then
                    If LookupStringEnding(sel) Then
                        'remember where to insert )
                        insertPointer = sel.ActivePoint.AbsoluteCharOffset()
                        state = MultilineParseState.OutsideLine
                    Else
                        'Insert )
                        sel.MoveToAbsoluteOffset(insertPointer)
                        sel.Text = ")"
                        state = MultilineParseState.Finished
                    End If

                Else
                    'Insert )
                    sel.MoveToAbsoluteOffset(insertPointer)
                    sel.Text = ")"
                    state = MultilineParseState.Finished
                End If
            End If
        End While

    End Sub

End Module


No comments:

Post a Comment