1 <?xml version=
"1.0" encoding=
"UTF-8"?>
2 <!DOCTYPE script:module PUBLIC
"-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
3 <script:module xmlns:
script=
"http://openoffice.org/2000/script" script:
name=
"SF_L10N" script:
language=
"StarBasic" script:
moduleType=
"normal">REM =======================================================================================================================
4 REM === The ScriptForge library and its associated libraries are part of the LibreOffice project. ===
5 REM === Full documentation is available on https://help.libreoffice.org/ ===
6 REM =======================================================================================================================
10 'Option Private Module
14 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
15 ''' L10N (aka SF_L10N)
16 ''' ====
17 ''' Implementation of a Basic class for providing a number of services
18 ''' related to the translation of user interfaces into a huge number of languages
19 ''' with a minimal impact on the program code itself
21 ''' The design choices of this module are based on so-called PO-files
22 ''' PO-files (portable object files) have long been promoted in the free software industry
23 ''' as a mean of providing multilingual UIs. This is accomplished through the use of human-readable
24 ''' text files with a well defined structure that specifies, for any given language,
25 ''' the source language string and the localized string
27 ''' To read more about the PO format and its ecosystem of associated toolsets:
28 ''' https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html#PO-Files
29 ''' and, IMHO, a very good tutorial:
30 ''' http://pology.nedohodnik.net/doc/user/en_US/ch-about.html
32 ''' The main advantage of the PO format is the complete dissociation between the two
33 ''' very different profiles, i.e. the programmer and the translator(s).
34 ''' Being independent text files, one per language to support, the programmer may give away
35 ''' pristine PO template files (known as POT-files) for a translator to process.
37 ''' This class implements mainly
3 mechanisms:
38 ''' - AddText: for the programmer to build a set of words or sentences
39 ''' meant for being translated later
40 ''' - ExportToPOTFile: All the above texts are exported into a pristine POT-file
41 ''' - GetText: At runtime get the text in the user language
42 ''' Note that the first two are optional: POT and PO-files may be built with a simple text editor
44 ''' Several instances of the L10N class may coexist
45 ' The constraint however is that each instance should find its PO-files
46 ''' in a separate directory
47 ''' PO-files must be named with the targeted locale: f.i.
"en-US.po
" or
"fr-BE.po
"
49 ''' Service invocation syntax
50 ''' CreateScriptService(
"L10N
"[, FolderName[, Locale]])
51 ''' FolderName: the folder containing the PO-files (in SF_FileSystem.FileNaming notation)
52 ''' Locale: in the form la-CO (language-COUNTRY)
53 ''' Service invocation examples:
54 ''' Dim myPO As Variant
55 ''' myPO = CreateScriptService(
"L10N
")
' AddText and ExportToPOTFile are allowed
56 ''' myPO = CreateScriptService(
"L10N
",
"C:\myPOFiles\
",
"fr-BE
")
57 ''' 'All functionalities are available
58 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
60 REM =============================================================== PRIVATE TYPES
62 ''' The recognized elements of an entry in a PO file are (other elements are ignored) :
63 ''' #. Extracted comments (given by the programmer to the translator)
64 ''' #, flag (the kde-format flag when the string contains tokens)
65 ''' msgctxt Context (to store an acronym associated with the message, this is a distortion of the norm)
66 ''' msgid untranslated-string
67 ''' msgstr translated-string
68 ''' NB: plural forms are not supported
78 REM ================================================================== EXCEPTIONS
80 Const DUPLICATEKEYERROR =
"DUPLICATEKEYERROR
"
82 REM ============================================================= PRIVATE MEMBERS
84 Private [Me] As Object
85 Private [_Parent] As Object
86 Private ObjectType As String
' Must be
"L10N
"
87 Private ServiceName As String
88 Private _POFolder As String
' PO files container
89 Private _Locale As String
' la-CO
90 Private _POFile As String
' PO file in URL format
91 Private _Encoding As String
' Used to open the PO file, default = UTF-
8
92 Private _Dictionary As Object
' SF_Dictionary
94 REM ===================================================== CONSTRUCTOR/DESTRUCTOR
96 REM -----------------------------------------------------------------------------
97 Private Sub Class_Initialize()
99 Set [_Parent] = Nothing
100 ObjectType =
"L10N
"
101 ServiceName =
"ScriptForge.L10N
"
102 _POFolder =
""
103 _Locale =
""
104 _POFile =
""
105 Set _Dictionary = Nothing
106 End Sub
' ScriptForge.SF_L10N Constructor
108 REM -----------------------------------------------------------------------------
109 Private Sub Class_Terminate()
111 If Not IsNull(_Dictionary) Then Set _Dictionary = _Dictionary.Dispose()
112 Call Class_Initialize()
113 End Sub
' ScriptForge.SF_L10N Destructor
115 REM -----------------------------------------------------------------------------
116 Public Function Dispose() As Variant
117 Call Class_Terminate()
118 Set Dispose = Nothing
119 End Function
' ScriptForge.SF_L10N Explicit Destructor
121 REM ================================================================== PROPERTIES
123 REM -----------------------------------------------------------------------------
124 Property Get Folder() As String
125 ''' Returns the FolderName containing the PO-files expressed as given by the current FileNaming
126 ''' property of the SF_FileSystem service. Default = URL format
127 ''' May be empty
128 ''' Example:
129 ''' myPO.Folder
131 Folder = _PropertyGet(
"Folder
")
133 End Property
' ScriptForge.SF_L10N.Folder
135 REM -----------------------------------------------------------------------------
136 Property Get Languages() As Variant
137 ''' Returns a zero-based array listing all the BaseNames of the PO-files found in Folder,
138 ''' Example:
139 ''' myPO.Languages
141 Languages = _PropertyGet(
"Languages
")
143 End Property
' ScriptForge.SF_L10N.Languages
145 REM -----------------------------------------------------------------------------
146 Property Get Locale() As String
147 ''' Returns the currently active language-COUNTRY combination. May be empty
148 ''' Example:
149 ''' myPO.Locale
151 Locale = _PropertyGet(
"Locale
")
153 End Property
' ScriptForge.SF_L10N.Locale
155 REM ===================================================================== METHODS
157 REM -----------------------------------------------------------------------------
158 Public Function AddText(Optional ByVal Context As Variant _
159 , Optional ByVal MsgId As Variant _
160 , Optional ByVal Comment As Variant _
161 , Optional ByVal MsgStr As Variant _
163 ''' Add a new entry in the list of localizable text strings
164 ''' Args:
165 ''' Context: when not empty, the key to retrieve the translated string via GetText. Default =
""
166 ''' MsgId: the untranslated string, i.e. the text appearing in the program code. Must not be empty
167 ''' The key to retrieve the translated string via GetText when Context is empty
168 ''' May contain placeholders (%
1 ... %
9) for dynamic arguments to be inserted in the text at run-time
169 ''' If the string spans multiple lines, insert escape sequences (\n) where relevant
170 ''' Comment: the so-called
"extracted-comments
" intended to inform/help translators
171 ''' If the string spans multiple lines, insert escape sequences (\n) where relevant
172 ''' MsgStr: (internal use only) the translated string
173 ''' If the string spans multiple lines, insert escape sequences (\n) where relevant
174 ''' Returns:
175 ''' True if successful
176 ''' Exceptions:
177 ''' DUPLICATEKEYERROR: such a key exists already
178 ''' Examples:
179 ''' myPO.AddText(,
"This is a text to be included in a POT file
")
181 Dim bAdd As Boolean
' Output buffer
182 Dim sKey As String
' The key part of the new entry in the dictionary
183 Dim vItem As POEntry
' The item part of the new entry in the dictionary
184 Const cstPipe =
"|
" ' Pipe forbidden in MsgId
's
185 Const cstThisSub =
"L10N.AddText
"
186 Const cstSubArgs =
"[Context=
""""], MsgId, [Comment=
""""]
"
188 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
192 If IsMissing(Context) Or IsMissing(Context) Then Context =
""
193 If IsMissing(Comment) Or IsMissing(Comment) Then Comment =
""
194 If IsMissing(MsgStr) Or IsMissing(MsgStr) Then MsgStr =
""
195 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
196 If Not SF_Utils._Validate(Context,
"Context
", V_STRING) Then GoTo Finally
197 If Not SF_Utils._Validate(MsgId,
"MsgId
", V_STRING) Then GoTo Finally
198 If Not SF_Utils._Validate(Comment,
"Comment
", V_STRING) Then GoTo Finally
199 If Not SF_Utils._Validate(MsgStr,
"MsgStr
", V_STRING) Then GoTo Finally
201 If Len(MsgId) =
0 Then GoTo Finally
204 If Len(Context)
> 0 Then sKey = Context Else sKey = MsgId
205 If _Dictionary.Exists(sKey) Then GoTo CatchDuplicate
209 If InStr(MsgId,
"%
")
> 0 Then .Flag =
"kde-format
" Else .Flag =
""
210 .Context = Replace(Context, cstPipe,
" ")
211 .MsgId = Replace(MsgId, cstPipe,
" ")
214 _Dictionary.Add(sKey, vItem)
218 SF_Utils._ExitFunction(cstThisSub)
223 SF_Exception.RaiseFatal(DUPLICATEKEYERROR, Iif(Len(Context)
> 0,
"Context
",
"MsgId
"), sKey)
225 End Function
' ScriptForge.SF_L10N.AddText
227 REM -----------------------------------------------------------------------------
228 Public Function ExportToPOTFile(Optional ByVal FileName As Variant _
229 , Optional ByVal Header As Variant _
230 , Optional ByVal Encoding As Variant _
232 ''' Export a set of untranslated strings as a POT file
233 ''' The set of strings has been built either by a succession of AddText() methods
234 ''' or by a successful invocation of the L10N service with the FolderName argument
235 ''' The generated file should pass successfully the
"msgfmt --check
'the pofile
'" GNU command
236 ''' Args:
237 ''' FileName: the complete file name to export to. If it exists, is overwritten without warning
238 ''' Header: Comments that will appear on top of the generated file. Do not include any leading
"#
"
239 ''' If the string spans multiple lines, insert escape sequences (\n) where relevant
240 ''' A standard header will be added anyway
241 ''' Encoding: The character set that should be used
242 ''' Use one of the Names listed in https://www.iana.org/assignments/character-sets/character-sets.xhtml
243 ''' Note that LibreOffice probably does not implement all existing sets
244 ''' Default = UTF-
8
245 ''' Returns:
246 ''' True if successful
247 ''' Examples:
248 ''' myPO.ExportToPOTFile(
"myFile.pot
", Header :=
"Top comment\nSecond line of top comment
")
250 Dim bExport As Boolean
' Return value
251 Dim oFile As Object
' Generated file handler
252 Dim vLines As Variant
' Wrapped lines
253 Dim sLine As String
' A single line
254 Dim vItems As Variant
' Array of dictionary items
255 Dim vItem As Variant
' POEntry type
256 Const cstSharp =
"#
", cstSharpDot =
"#.
", cstFlag =
"#, kde-format
"
259 Const cstThisSub =
"L10N.ExportToPOTFile
"
260 Const cstSubArgs =
"FileName, [Header=
""""], [Encoding=
""UTF-
8"""
262 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
266 If IsMissing(Header) Or IsMissing(Header) Then Header =
""
267 If IsMissing(Encoding) Or IsMissing(Encoding) Then Encoding =
"UTF-
8"
268 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
269 If Not SF_Utils._ValidateFile(FileName,
"FileName
") Then GoTo Finally
270 If Not SF_Utils._Validate(Header,
"Header
", V_STRING) Then GoTo Finally
271 If Not SF_Utils._Validate(Encoding,
"Encoding
", V_STRING) Then GoTo Finally
275 Set oFile = SF_FileSystem.CreateTextFile(FileName, Overwrite := True, Encoding := Encoding)
276 If Not IsNull(oFile) Then
278 ' Standard header
280 .WriteLine(cstSharp
& "This pristine POT file has been generated by LibreOffice/ScriptForge
")
281 .WriteLine(cstSharp
& "Full documentation is available on https://help.libreoffice.org/
")
283 If Len(Header)
> 0 Then
285 vLines = SF_String.Wrap(Header, cstWrap, cstTabSize)
286 For Each sLine In vLines
287 .WriteLine(cstSharp
& Replace(sLine, SF_String.sfLF,
""))
290 ' Standard header
292 .WriteLine(
"msgid
""""")
293 .WriteLine(
"msgstr
""""")
294 .WriteLine(SF_String.Quote(
"Project-Id-Version: PACKAGE VERSION\n
"))
295 .WriteLine(SF_String.Quote(
"Report-Msgid-Bugs-To:
" _
296 & "https://bugs.libreoffice.org/enter_bug.cgi?product=LibreOffice
&bug_status=UNCONFIRMED
&component=UI\n
"))
297 .WriteLine(SF_String.Quote(
"POT-Creation-Date:
" & SF_STring.Represent(Now())
& "\n
"))
298 .WriteLine(SF_String.Quote(
"PO-Revision-Date: YYYY-MM-DD HH:MM:SS\n
"))
299 .WriteLine(SF_String.Quote(
"Last-Translator: FULL NAME
<EMAIL@ADDRESS
>\n
"))
300 .WriteLine(SF_String.Quote(
"Language-Team: LANGUAGE
<EMAIL@ADDRESS
>\n
"))
301 .WriteLine(SF_String.Quote(
"Language: en_US\n
"))
302 .WriteLine(SF_String.Quote(
"MIME-Version:
1.0\n
"))
303 .WriteLine(SF_String.Quote(
"Content-Type: text/plain; charset=
" & Encoding
& "\n
"))
304 .WriteLine(SF_String.Quote(
"Content-Transfer-Encoding:
8bit\n
"))
305 .WriteLine(SF_String.Quote(
"Plural-Forms: nplurals=
2; plural=n
> 1;\n
"))
306 .WriteLine(SF_String.Quote(
"X-Generator: LibreOffice - ScriptForge\n
"))
307 .WriteLine(SF_String.Quote(
"X-Accelerator-Marker: ~\n
"))
308 ' Individual translatable strings
309 vItems = _Dictionary.Items()
310 For Each vItem in vItems
313 vLines = Split(vItem.Comment,
"\n
")
314 For Each sLine In vLines
315 .WriteLine(cstSharpDot
& SF_String.ExpandTabs(SF_String.Unescape(sLine), cstTabSize))
318 If InStr(vItem.MsgId,
"%
")
> 0 Then .WriteLine(cstFlag)
320 If Len(vItem.Context)
> 0 Then
321 .WriteLine(
"msgctxt
" & SF_String.Quote(vItem.Context))
324 vLines = SF_String.Wrap(vItem.MsgId, cstWrap, cstTabSize)
325 If UBound(vLines) =
0 Then
326 .WriteLine(
"msgid
" & SF_String.Quote(SF_String.Escape(vLines(
0))))
328 .WriteLine(
"msgid
""""")
329 For Each sLine in vLines
330 .WriteLine(SF_String.Quote(SF_String.Escape(sLine)))
334 .WriteLine(
"msgstr
""""")
342 If Not IsNull(oFile) Then Set oFile = oFile.Dispose()
343 ExportToPOTFile = bExport
344 SF_Utils._ExitFunction(cstThisSub)
348 End Function
' ScriptForge.SF_L10N.ExportToPOTFile
350 REM -----------------------------------------------------------------------------
351 Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant
352 ''' Return the actual value of the given property
353 ''' Args:
354 ''' PropertyName: the name of the property as a string
355 ''' Returns:
356 ''' The actual value of the property
357 ''' If the property does not exist, returns Null
358 ''' Exceptions:
359 ''' ARGUMENTERROR The property does not exist
360 ''' Examples:
361 ''' myL10N.GetProperty(
"MyProperty
")
363 Const cstThisSub =
"L10N.GetProperty
"
364 Const cstSubArgs =
""
366 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
370 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
371 If Not SF_Utils._Validate(PropertyName,
"PropertyName
", V_STRING, Properties()) Then GoTo Catch
375 GetProperty = _PropertyGet(PropertyName)
378 SF_Utils._ExitFunction(cstThisSub)
382 End Function
' ScriptForge.SF_L10N.GetProperty
384 REM -----------------------------------------------------------------------------
385 Public Function GetText(Optional ByVal MsgId As Variant _
386 , ParamArray pvArgs As Variant _
388 ''' Get the translated string corresponding with the given argument
389 ''' Args:
390 ''' MsgId: the identifier of the string or the untranslated string
391 ''' Either - the untranslated text (MsgId)
392 ''' - the reference to the untranslated text (Context)
393 ''' - both (Context|MsgId) : the pipe character is essential
394 ''' pvArgs(): a list of arguments present as %
1, %
2, ... in the (un)translated string)
395 ''' to be substituted in the returned string
396 ''' Any type is admitted but only strings, numbers or dates are relevant
397 ''' Returns:
398 ''' The translated string
399 ''' If not found the MsgId string or the Context string
400 ''' Anyway the substitution is done
401 ''' Examples:
402 ''' myPO.GetText(
"This is a text to be included in a POT file
")
403 ''' ' Ceci est un text à inclure dans un fichier POT
405 Dim sText As String
' Output buffer
406 Dim sContext As String
' Context part of argument
407 Dim sMsgId As String
' MsgId part of argument
408 Dim vItem As POEntry
' Entry in the dictionary
409 Dim vMsgId As Variant
' MsgId split on pipe
410 Dim sKey As String
' Key of dictionary
411 Dim sPercent As String
' %
1, %
2, ... placeholders
413 Const cstPipe =
"|
"
414 Const cstThisSub =
"L10N.GetText
"
415 Const cstSubArgs =
"MsgId, [Arg0, Arg1, ...]
"
417 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
421 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
422 If Not SF_Utils._Validate(MsgId,
"MsgId
", V_STRING) Then GoTo Finally
424 If Len(Trim(MsgId)) =
0 Then GoTo Finally
428 ' Find and load entry from dictionary
429 If Left(MsgId,
1) = cstPipe then MsgId = Mid(MsgId,
2)
430 vMsgId = Split(MsgId, cstPipe)
432 If Not _Dictionary.Exists(sKey) Then
' Not found
433 If UBound(vMsgId) =
0 Then sText = vMsgId(
0) Else sText = Mid(MsgId, InStr(MsgId, cstPipe) +
1)
435 vItem = _Dictionary.Item(sKey)
436 If Len(vItem.MsgStr)
> 0 Then sText = vItem.MsgStr Else sText = vItem.MsgId
439 ' Substitute %i placeholders
440 For i = UBound(pvArgs) To
0 Step -
1 ' Go downwards to not have a limit in number of args
441 sPercent =
"%
" & (i +
1)
442 sText = Replace(sText, sPercent, SF_String.Represent(pvArgs(i)))
447 SF_Utils._ExitFunction(cstThisSub)
451 End Function
' ScriptForge.SF_L10N.GetText
453 REM - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
454 Public Function _(Optional ByVal MsgId As Variant _
455 , ParamArray pvArgs As Variant _
457 ''' Get the translated string corresponding with the given argument
458 ''' Alias of GetText() - See above
459 ''' Examples:
460 ''' myPO._(
"This is a text to be included in a POT file
")
461 ''' ' Ceci est un text à inclure dans un fichier POT
463 Dim sText As String
' Output buffer
464 Dim sPercent As String
' %
1, %
2, ... placeholders
466 Const cstPipe =
"|
"
467 Const cstThisSub =
"L10N._
"
468 Const cstSubArgs =
"MsgId, [Arg0, Arg1, ...]
"
470 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
474 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
475 If Not SF_Utils._Validate(MsgId,
"MsgId
", V_STRING) Then GoTo Finally
477 If Len(Trim(MsgId)) =
0 Then GoTo Finally
480 ' Find and load entry from dictionary
481 sText = GetText(MsgId)
483 ' Substitute %i placeholders - done here, not in GetText(), because # of arguments is undefined
484 For i =
0 To UBound(pvArgs)
485 sPercent =
"%
" & (i +
1)
486 sText = Replace(sText, sPercent, SF_String.Represent(pvArgs(i)))
491 SF_Utils._ExitFunction(cstThisSub)
495 End Function
' ScriptForge.SF_L10N._
497 REM -----------------------------------------------------------------------------
498 Public Function Methods() As Variant
499 ''' Return the list of public methods of the L10N service as an array
502 "AddText
" _
503 ,
"ExportToPOTFile
" _
504 ,
"GetText
" _
508 End Function
' ScriptForge.SF_L10N.Methods
510 REM -----------------------------------------------------------------------------
511 Public Function Properties() As Variant
512 ''' Return the list or properties of the Timer class as an array
514 Properties = Array( _
516 ,
"Languages
" _
517 ,
"Locale
" _
520 End Function
' ScriptForge.SF_L10N.Properties
522 REM -----------------------------------------------------------------------------
523 Public Function SetProperty(Optional ByVal PropertyName As Variant _
524 , Optional ByRef Value As Variant _
526 ''' Set a new value to the given property
527 ''' Args:
528 ''' PropertyName: the name of the property as a string
529 ''' Value: its new value
530 ''' Exceptions
531 ''' ARGUMENTERROR The property does not exist
533 Const cstThisSub =
"L10N.SetProperty
"
534 Const cstSubArgs =
"PropertyName, Value
"
536 If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
540 If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
541 If Not SF_Utils._Validate(PropertyName,
"PropertyName
", V_STRING, Properties()) Then GoTo Catch
545 Select Case UCase(PropertyName)
550 SF_Utils._ExitFunction(cstThisSub)
554 End Function
' ScriptForge.SF_L10N.SetProperty
556 REM =========================================================== PRIVATE FUNCTIONS
558 REM -----------------------------------------------------------------------------
559 Public Sub _Initialize(ByVal psPOFile As String _
560 , ByVal Encoding As String _
562 ''' Completes initialization of the current instance requested from CreateScriptService()
563 ''' Load the POFile in the dictionary, otherwise leave the dictionary empty
564 ''' Args:
565 ''' psPOFile: the file to load the translated strings from
566 ''' Encoding: The character set that should be used. Default = UTF-
8
568 Dim oFile As Object
' PO file handler
569 Dim sContext As String
' Collected context string
570 Dim sMsgId As String
' Collected untranslated string
571 Dim sComment As String
' Collected comment string
572 Dim sMsgStr As String
' Collected translated string
573 Dim sLine As String
' Last line read
574 Dim iContinue As Integer
' 0 = None,
1 = MsgId,
2 = MsgStr
575 Const cstMsgId =
1, cstMsgStr =
2
578 ' Initialize dictionary anyway
579 Set _Dictionary = SF_Services.CreateScriptService(
"Dictionary
")
580 Set _Dictionary.[_Parent] = [Me]
583 If Len(psPOFile)
> 0 Then
585 _POFolder = ._ConvertToUrl(.GetParentFolderName(psPOFile))
586 _Locale = .GetBaseName(psPOFile)
587 _POFile = ._ConvertToUrl(psPOFile)
590 Set oFile = SF_FileSystem.OpenTextFile(psPOFile, IOMode := SF_FileSystem.ForReading, Encoding := Encoding)
591 If Not IsNull(oFile) Then
593 ' The PO file is presumed valid =
> syntax check is not very strict
594 sContext =
"" : sMsgId =
"" : sComment =
"" : sMsgStr =
""
595 Do While Not .AtEndOfStream
596 sLine = Trim(.ReadLine())
597 ' Trivial examination of line header
599 Case sLine =
""
600 If Len(sMsgId)
> 0 Then AddText(sContext, sMsgId, sComment, sMsgStr)
601 sContext =
"" : sMsgId =
"" : sComment =
"" : sMsgStr =
""
603 Case Left(sLine,
3) =
"#.
"
604 sComment = sComment
& Iif(Len(sComment)
> 0,
"\n
",
"")
& Trim(Mid(sLine,
4))
606 Case Left(sLine,
8) =
"msgctxt
"
607 sContext = SF_String.Unquote(Trim(Mid(sLine,
9)))
609 Case Left(sLine,
6) =
"msgid
"
610 sMsgId = SF_String.Unquote(Trim(Mid(sLine,
7)))
612 Case Left(sLine,
7) =
"msgstr
"
613 sMsgStr = sMsgStr
& SF_String.Unquote(Trim(Mid(sLine,
8)))
614 iContinue = cstMsgStr
615 Case Left(sLine,
1) =
""""
616 If iContinue = cstMsgId Then
617 sMsgId = sMsgId
& SF_String.Unquote(sLine)
618 ElseIf iContinue = cstMsgStr Then
619 sMsgStr = sMsgStr
& SF_String.Unquote(sLine)
623 Case Else
' Skip line
627 ' Be sure to store the last entry
628 If Len(sMsgId)
> 0 Then AddText(sContext, sMsgId, sComment, sMsgStr)
630 Set oFile = .Dispose()
634 _POFolder =
""
635 _Locale =
""
636 _POFile =
""
641 End Sub
' ScriptForge.SF_L10N._Initialize
643 REM -----------------------------------------------------------------------------
644 Private Function _PropertyGet(Optional ByVal psProperty As String)
645 ''' Return the value of the named property
646 ''' Args:
647 ''' psProperty: the name of the property
649 Dim vFiles As Variant
' Array of PO-files
651 Dim cstThisSub As String
652 Dim cstSubArgs As String
654 cstThisSub =
"SF_L10N.get
" & psProperty
655 cstSubArgs =
""
656 SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
659 Select Case psProperty
660 Case
"Folder
"
661 If Len(_POFolder)
> 0 Then _PropertyGet = ._ConvertFromUrl(_POFolder) Else _PropertyGet =
""
662 Case
"Languages
"
663 If Len(_POFolder)
> 0 Then
664 vFiles = .Files(._ConvertFromUrl(_POFolder),
"??-??.po
")
665 For i =
0 To UBound(vFiles)
666 vFiles(i) = SF_FileSystem.GetBaseName(vFiles(i))
671 _PropertyGet = vFiles
672 Case
"Locale
"
673 _PropertyGet = _Locale
680 SF_Utils._ExitFunction(cstThisSub)
682 End Function
' ScriptForge.SF_L10N._PropertyGet
684 REM -----------------------------------------------------------------------------
685 Private Function _Repr() As String
686 ''' Convert the L10N instance to a readable string, typically for debugging purposes (DebugPrint ...)
687 ''' Args:
688 ''' Return:
689 ''' "[L10N]: PO file
"
691 _Repr =
"[L10N]:
" & _POFile
693 End Function
' ScriptForge.SF_L10N._Repr
695 REM ============================================ END OF SCRIPTFORGE.SF_L10N