From 552a1f30eca91eb647d10d77135b32a5729f11bd Mon Sep 17 00:00:00 2001 From: Jean-Pierre Ledure Date: Thu, 2 Sep 2021 16:08:44 +0200 Subject: ScriptForge - add AddTextsFromDialog and GetTextsFromL10N methods The objective is to facilitate the automatic translation of all fixed texts in dialogs and dialog controls. Concerned items are: - the title of the dialog - the caption associated with next control types: Button, CheckBox, FixedLine, FixedText, GroupBox and RadioButton - the content of list- and comboboxes - the tip- or helptext displayed when the mouse is hovering the control ScriptForge.SF_L10N.AddTextsFromDialog(dialog) store all fixed texts of the dialog in the list of translatable strings of a L10N object to prepare a POT file SFDialogs.Dialog.GetTextsFromL10N(l10n) get the translated versions of all fixed texts in the dialog from a L10N object and apply them on the dialog before display Both methods are executable from Basic and Python user scripts Change-Id: I3dc9fbbce287d7af4040df713f9d11e0ff928b1c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121514 Tested-by: Jean-Pierre Ledure Tested-by: Jenkins Reviewed-by: Jean-Pierre Ledure --- wizards/source/scriptforge/SF_L10N.xba | 135 +++++++++++++++++++++-- wizards/source/scriptforge/SF_Root.xba | 2 - wizards/source/scriptforge/SF_Utils.xba | 5 - wizards/source/scriptforge/python/scriptforge.py | 8 ++ wizards/source/sfdialogs/SF_Dialog.xba | 93 ++++++++++++++++ wizards/source/sfdialogs/SF_DialogControl.xba | 4 +- wizards/source/sfdialogs/SF_Register.xba | 2 +- 7 files changed, 232 insertions(+), 17 deletions(-) (limited to 'wizards') diff --git a/wizards/source/scriptforge/SF_L10N.xba b/wizards/source/scriptforge/SF_L10N.xba index 020dca541831..6aab1f7b4f14 100644 --- a/wizards/source/scriptforge/SF_L10N.xba +++ b/wizards/source/scriptforge/SF_L10N.xba @@ -34,11 +34,12 @@ Option Explicit ''' Being independent text files, one per language to support, the programmer may give away ''' pristine PO template files (known as POT-files) for a translator to process. ''' -''' This class implements mainly 3 mechanisms: -''' - AddText: for the programmer to build a set of words or sentences +''' This class implements mainly 4 mechanisms: +''' 1. AddText: for the programmer to build a set of words or sentences ''' meant for being translated later -''' - ExportToPOTFile: All the above texts are exported into a pristine POT-file -''' - GetText: At runtime get the text in the user language +''' 2. AddTextsFromDialog: to automatically execute AddText() on each fixed text of a dialog +''' 3. ExportToPOTFile: All the above texts are exported into a pristine POT-file +''' 4. GetText: At runtime get the text in the user language ''' Note that the first two are optional: POT and PO-files may be built with a simple text editor ''' ''' Several instances of the L10N class may coexist @@ -52,7 +53,7 @@ Option Explicit ''' Locale: in the form la-CO (language-COUNTRY) ''' Service invocation examples: ''' Dim myPO As Variant -''' myPO = CreateScriptService("L10N") ' AddText and ExportToPOTFile are allowed +''' myPO = CreateScriptService("L10N") ' AddText, AddTextsFromDialogt and ExportToPOTFile are allowed ''' myPO = CreateScriptService("L10N", "C:\myPOFiles\", "fr-BE") ''' 'All functionalities are available ''' @@ -228,6 +229,91 @@ CatchDuplicate: GoTo Finally End Function ' ScriptForge.SF_L10N.AddText +REM ----------------------------------------------------------------------------- +Public Function AddTextsFromDialog(Optional ByRef Dialog As Variant) As Boolean +''' Add all fixed text strings of a dialog to the list of localizable text strings +''' Added texts are: +''' - the title of the dialog +''' - the caption associated with next control types: Button, CheckBox, FixedLine, FixedText, GroupBox and RadioButton +''' - the content of list- and comboboxes +''' - the tip- or helptext displayed when the mouse is hovering the control +''' The current method has method SFDialogs.SF_Dialog.GetTextsFromL10N as counterpart +''' The targeted dialog must not be open when the current method is run +''' Args: +''' Dialog: a SFDialogs.Dialog service instance +''' Returns: +''' True when successful +''' Examples: +''' Dim myDialog As Object +''' Set myDialog = CreateScriptService("SFDialogs.Dialog", "GlobalScope", "XrayTool", "DlgXray") +''' myPO.AddTextsFromDialog(myDialog) + +Dim bAdd As Boolean ' Return value +Dim vControls As Variant ' Array of control names +Dim sControl As String ' A single control name +Dim oControl As Object ' SFDialogs.DialogControl +Dim sText As String ' The text to insert in the dictionary +Dim sDialogComment As String ' The prefix in the comment to insert in the dictionary for the dialog +Dim sControlComment As String ' The prefix in the comment to insert in the dictionary for a control +Dim vSource As Variant ' RowSource property of dialog control as an array +Dim i As Long + +Const cstThisSub = "L10N.AddTextsFromDialog" +Const cstSubArgs = "Dialog" + + If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch + bAdd = False + +Check: + If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then + If Not SF_Utils._Validate(Dialog, "Dialog", V_OBJECT, , , "DIALOG") Then GoTo Finally + End If + +Try: + With Dialog + ' Store the title of the dialog + sDialogComment = "Dialog => " & ._Container & " : " & ._Library & " : " & ._Name & " : " + stext = .Caption + If Len(sText) > 0 Then + If Not _ReplaceText("", sText, sDialogComment & "Caption") Then GoTo Catch + End If + ' Scan all controls + vControls = .Controls() + For Each sControl In vControls + Set oControl = .Controls(sControl) + sControlComment = sDialogComment & sControl & "." + With oControl + ' Extract fixed texts + sText = .Caption + If Len(sText) > 0 Then + If Not _ReplaceText("", sText, sControlComment & "Caption") Then GoTo Catch + End If + vSource = .RowSource ' List and comboboxes only + If IsArray(vSource) Then + For i = 0 To UBound(vSource) + If Len(vSource(i)) > 0 Then + If Not _ReplaceText("", vSource(i), sControlComment & "RowSource[" & i & "]") Then GoTo Catch + End If + Next i + End If + sText = .TipText + If Len(sText) > 0 Then + If Not _ReplaceText("", sText, sControlComment & "TipText") Then GoTo Catch + End If + End With + Next sControl + End With + + bAdd = True + +Finally: + AddTextsFromDialog = bAdd + SF_Utils._ExitFunction(cstThisSub) + Exit Function +Catch: + GoTo Finally +End Function ' ScriptForge.SF_L10N.AddTextsFromDialog + REM ----------------------------------------------------------------------------- Public Function ExportToPOTFile(Optional ByVal FileName As Variant _ , Optional ByVal Header As Variant _ @@ -267,8 +353,8 @@ Const cstSubArgs = "FileName, [Header=""""], [Encoding= bExport = False Check: - If IsMissing(Header) Or IsMissing(Header) Then Header = "" - If IsMissing(Encoding) Or IsMissing(Encoding) Then Encoding = "UTF-8" + If IsMissing(Header) Or IsEmpty(Header) Then Header = "" + If IsMissing(Encoding) Or IsEmpty(Encoding) Then Encoding = "UTF-8" If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then If Not SF_Utils._ValidateFile(FileName, "FileName") Then GoTo Finally If Not SF_Utils._Validate(Header, "Header", V_STRING) Then GoTo Finally @@ -506,6 +592,7 @@ Public Function Methods() As Variant "AddText" _ , "ExportToPOTFile" _ , "GetText" _ + , "AddTextsFromDialog" _ , "_" _ ) @@ -685,6 +772,40 @@ Finally: Exit Function End Function ' ScriptForge.SF_L10N._PropertyGet +REM ----------------------------------------------------------------------------- +Private Function _ReplaceText(ByVal psContext As String _ + , ByVal psMsgId As String _ + , ByVal psComment As String _ + ) As Boolean +''' When the entry in the dictionary does not yet exist, equivalent to AddText +''' When it exists already, extend the existing comment with the psComment argument +''' Used from AddTextsFromDialog to manage identical strings without raising errors, +''' e.g. when multiple dialogs have the same "Close" button + +Dim bAdd As Boolean ' Return value +Dim sKey As String ' The key part of an entry in the dictionary +Dim vItem As POEntry ' The item part of the new entry in the dictionary + +Try: + bAdd = False + If Len(psContext) > 0 Then sKey = psContext Else sKey = psMsgId + If _Dictionary.Exists(sKey) Then + ' Load the entry, adapt comment and rewrite + vItem = _Dictionary.Item(sKey) + If Len(vItem.Comment) = 0 Then vItem.Comment = psComment Else vItem.Comment = vItem.Comment & "\n" & psComment + bAdd = _Dictionary.ReplaceItem(sKey, vItem) + Else + ' Add a new entry as usual + bAdd = AddText(psContext, psMsgId, psComment) + End If + +Finally: + _ReplaceText = bAdd + Exit Function +Catch: + GoTo Finally +End Function ' ScriptForge.SF_L10N._ReplaceText + REM ----------------------------------------------------------------------------- Private Function _Repr() As String ''' Convert the L10N instance to a readable string, typically for debugging purposes (DebugPrint ...) diff --git a/wizards/source/scriptforge/SF_Root.xba b/wizards/source/scriptforge/SF_Root.xba index 131f2eb90d56..7d9132caf205 100644 --- a/wizards/source/scriptforge/SF_Root.xba +++ b/wizards/source/scriptforge/SF_Root.xba @@ -72,7 +72,6 @@ Private DatabaseContext As Object ' com.sun.star.sdb.DatabaseContext Private ConfigurationProvider _ As Object ' com.sun.star.configuration.ConfigurationProvider Private MailService As Object ' com.sun.star.system.SimpleCommandMail or com.sun.star.system.SimpleSystemMail -Private TreeDataModel As Object ' com.sun.star.awt.tree.MutableTreeDataModel Private GraphicExportFilter As Object ' com.sun.star.drawing.GraphicExportFilter ' Specific persistent services objects or properties @@ -135,7 +134,6 @@ Private Sub Class_Initialize() Set DatabaseContext = Nothing Set ConfigurationProvider = Nothing Set MailService = Nothing - Set TreeDataModel = Nothing Set GraphicExportFilter = Nothing OSName = "" SFDialogs = Empty diff --git a/wizards/source/scriptforge/SF_Utils.xba b/wizards/source/scriptforge/SF_Utils.xba index 99ee224cc79f..1505e4cfd308 100644 --- a/wizards/source/scriptforge/SF_Utils.xba +++ b/wizards/source/scriptforge/SF_Utils.xba @@ -439,11 +439,6 @@ Dim vNodePath As Variant Set .TextSearch = CreateUnoService("com.sun.star.util.TextSearch") End If Set _GetUNOService = .TextSearch - Case "TreeDataModel" - If IsEmpty(.TreeDataModel) Or IsNull(.TreeDataModel) Then - Set .TreeDataModel = CreateUnoService("com.sun.star.awt.tree.MutableTreeDataModel") - End If - Set _GetUNOService = .TreeDataModel Case "URLTransformer" If IsEmpty(.URLTransformer) Or IsNull(.URLTransformer) Then Set .URLTransformer = CreateUnoService("com.sun.star.util.URLTransformer") diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py index 498da0637dd7..12039b1d923d 100644 --- a/wizards/source/scriptforge/python/scriptforge.py +++ b/wizards/source/scriptforge/python/scriptforge.py @@ -1179,6 +1179,10 @@ class SFScriptForge: def AddText(self, context = '', msgid = '', comment = ''): return self.ExecMethod(self.vbMethod, 'AddText', context, msgid, comment) + def AddTextsFromDialog(self, dialog): + dialogobj = dialog.objectreference if isinstance(dialog, SFDialogs.SF_Dialog) else dialog + return self.ExecMethod(self.vbMethod + self.flgObject, 'AddTextsFromDialog', dialogobj) + def ExportToPOTFile(self, filename, header = '', encoding= 'UTF-8'): return self.ExecMethod(self.vbMethod, 'ExportToPOTFile', filename, header, encoding) @@ -1659,6 +1663,10 @@ class SFDialogs: def Execute(self, modal = True): return self.ExecMethod(self.vbMethod, 'Execute', modal) + def GetTextsFromL10N(self, l10n): + l10nobj = l10n.objectreference if isinstance(l10n, SFScriptForge.SF_L10N) else l10n + return self.ExecMethod(self.vbMethod + self.flgObject, 'GetTextsFromL10N', l10nobj) + def Terminate(self): return self.ExecMethod(self.vbMethod, 'Terminate') diff --git a/wizards/source/sfdialogs/SF_Dialog.xba b/wizards/source/sfdialogs/SF_Dialog.xba index a574cf87ef25..b69e4b3ff5cf 100644 --- a/wizards/source/sfdialogs/SF_Dialog.xba +++ b/wizards/source/sfdialogs/SF_Dialog.xba @@ -498,6 +498,98 @@ Catch: GoTo Finally End Function ' SFDialogs.SF_Dialog.GetProperty +REM ----------------------------------------------------------------------------- +Public Function GetTextsFromL10N(Optional ByRef L10N As Variant) As Boolean +''' Replace all fixed text strings of a dialog by their localized version +''' Replaced texts are: +''' - the title of the dialog +''' - the caption associated with next control types: Button, CheckBox, FixedLine, FixedText, GroupBox and RadioButton +''' - the content of list- and comboboxes +''' - the tip- or helptext displayed when the mouse is hovering the control +''' The current method has a twin method ScriptForge.SF_L10N.AddTextsFromDialog +''' The current method is probably run before the Execute() method +''' Args: +''' L10N : a "L10N" service instance created with CreateScriptService("L10N") +''' Returns: +''' True when successful +''' Examples: +''' Dim myPO As Object, oDlg As Object +''' Set oDlg = CreateScriptService("Dialog", "GlobalScope", "XrayTool", "DlgXray") +''' Set myPO = CreateScriptService("L10N", "C:\myPOFiles\", "fr-BE") +''' oDlg.GetTextsFromL10N(myPO) + +Dim bGet As Boolean ' Return value +Dim vControls As Variant ' Array of control names +Dim sControl As String ' A single control name +Dim oControl As Object ' SFDialogs.DialogControl +Dim sText As String ' The text found in the dialog +Dim sTranslation As String ' The translated text got from the dictionary +Dim vSource As Variant ' RowSource property of dialog control as an array +Dim bChanged As Boolean ' True when at least 1 item of a RowSource is modified +Dim i As Long + +Const cstThisSub = "SFDialogs.Dialog.GetTextsFromL10N" +Const cstSubArgs = "L10N" + + If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch + bGet = False + +Check: + If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then + If Not SF_Utils._Validate(L10N, "L10N", V_OBJECT, , , "L10N") Then GoTo Finally + End If + +Try: + ' Get the dialog title + sText = Caption + If Len(sText) > 0 Then + sTranslation = L10N._(sText) + If sText <> sTranslation Then Caption = sTranslation + End If + ' Scan all controls + vControls = Controls() + For Each sControl In vControls + Set oControl = Controls(sControl) + With oControl + ' Extract fixed texts + sText = .Caption + If Len(sText) > 0 Then + sTranslation = L10N._(sText) + If sText <> sTranslation Then .Caption = sTranslation + End If + vSource = .RowSource ' List and comboboxes only + If IsArray(vSource) Then + bChanged = False + For i = 0 To UBound(vSource) + If Len(vSource(i)) > 0 Then + sTranslation = L10N._(vSource(i)) + If sTranslation <> vSource(i) Then + bChanged = True + vSource(i) = sTranslation + End If + End If + Next i + ' Rewrite if at least 1 item has been modified by the translation process + If bChanged Then .RowSource = vSource + End If + sText = .TipText + If Len(sText) > 0 Then + sTranslation = L10N._(sText) + If sText <> sTranslation Then .TipText = sTranslation + End If + End With + Next sControl + + bGet = True + +Finally: + GetTextsFromL10N = bGet + SF_Utils._ExitFunction(cstThisSub) + Exit Function +Catch: + GoTo Finally +End Function ' SFDialogs.SF_Dialog.GetTextsFromL10N + REM ----------------------------------------------------------------------------- Public Function Methods() As Variant ''' Return the list of public methods of the Model service as an array @@ -507,6 +599,7 @@ Public Function Methods() As Variant , "Controls" _ , "EndExecute" _ , "Execute" _ + , "GetTextsFromL10N" _ , "Terminate" _ ) diff --git a/wizards/source/sfdialogs/SF_DialogControl.xba b/wizards/source/sfdialogs/SF_DialogControl.xba index 42270e32bcd3..f4a0891d92c4 100644 --- a/wizards/source/sfdialogs/SF_DialogControl.xba +++ b/wizards/source/sfdialogs/SF_DialogControl.xba @@ -1440,7 +1440,7 @@ Try: Case "TreeControlModel" ' Initialize the data model _ControlType = CTLTREECONTROL - Set _ControlModel.DataModel = ScriptForge.SF_Utils._GetUNOService("TreeDataModel") + Set _ControlModel.DataModel = CreateUnoService("com.sun.star.awt.tree.MutableTreeDataModel") Set _TreeDataModel = _ControlModel.DataModel Case "UnoControlGridModel" _ControlType = CTLTABLECONTROL @@ -2081,4 +2081,4 @@ Private Function _Repr() As String End Function ' SFDialogs.SF_DialogControl._Repr REM ============================================ END OF SFDIALOGS.SF_DIALOGCONTROL - + \ No newline at end of file diff --git a/wizards/source/sfdialogs/SF_Register.xba b/wizards/source/sfdialogs/SF_Register.xba index b99c9e337526..11ee1543b412 100644 --- a/wizards/source/sfdialogs/SF_Register.xba +++ b/wizards/source/sfdialogs/SF_Register.xba @@ -220,7 +220,7 @@ End Function ' SFDialogs.SF_Register._FindDialogInCache REM ----------------------------------------------------------------------------- Public Function _NewDialog(Optional ByVal pvArgs As Variant) As Object ''' Create a new instance of the SF_Dialog class -' Args: +''' Args: ''' Container: either "GlobalScope" or a WindowName. Default = the active window ''' see the definition of WindowName in the description of the UI service ''' Library: the name of the library hosting the dialog. Default = "Standard" -- cgit