Jump to content

Recommended Posts

Posted (edited)

Language UDF for AutoIt.

You can also find theย Lang UDF on Github.

This is a UDF, providing a simple way to support different languages and allow dynamically switching between them.
The UDF uses Ini files with sections for each language and key/value pairs for retrieving the text. The values are processed with StringFormat to allow values to be added into the strings.
If a single file gets to large, it is possible to add keys in sub config files (See the __Lang_Load documentation for more information).

The only required file to be included in the script is the "Lang.au3".

Example:

#cs ----------------------------------------------------------------------------

     AutoIt Version: 3.3.18.0
     Author:         Kanashius

     Script Function:
        AutoIt Language example script.

#ce ----------------------------------------------------------------------------
#include <GUIConstantsEx.au3>
#include <GuiComboBox.au3>
#include "../Lang.au3"

; load default language => first language in lang.ini
__Lang_Load()

Local $iWidth = 400, $iHeight = 250, $iSpace = 5, $iCtrlHeight = 25

Local $hGui = GUICreate("AutoIt Language example", $iWidth, $iHeight)
Local $iCallbackWinTitle = __Lang_CreateCallback("_CallbackWinTitle")
__Lang_SetCallback($iCallbackWinTitle, "autoitLanguageExample")

Local $idMenuLang = GUICtrlCreateMenu("Language")
Global $arLanguages = __Lang_GetLanguages()
Local $idMenuLangFirst = Default
For $i=0 To UBound($arLanguages)-1
    Local $idMenuItem = GUICtrlCreateMenuItem($arLanguages[$i][1], $idMenuLang, -1, 1)
    If $i=0 Then
        GUICtrlSetState(-1, $GUI_CHECKED)
        $idMenuLangFirst = $idMenuItem
    EndIf
Next

Local $iLeft = $iSpace, $iTop = $iSpace, $iCtrlWidth = $iWidth-2*$iSpace
Local $idLabelExampleNumber = GUICtrlCreateLabel("", $iLeft, $iTop, $iCtrlWidth, $iCtrlHeight)
Local $iCallbackExampleNumber = __Lang_CreateCallback("__Lang_CallbackLabel", $idLabelExampleNumber)
__Lang_SetCallback($iCallbackExampleNumber, "exampleNumberIs", 5)

$iTop += $iCtrlHeight+$iSpace
Local $idLabelExampleOnlyEnglish = GUICtrlCreateLabel("", $iLeft, $iTop, $iCtrlWidth, $iCtrlHeight)
Local $iCallbackExampleOnlyEnglish = __Lang_CreateCallback("__Lang_CallbackLabel", $idLabelExampleOnlyEnglish)
__Lang_SetCallback($iCallbackExampleOnlyEnglish, "thisIsOnlyAvailableInEnglish")

$iTop += $iCtrlHeight+$iSpace
Local $idButton = GUICtrlCreateButton("", $iLeft, $iTop, $iCtrlWidth, $iCtrlHeight)
Local $iCallbackButton = __Lang_CreateCallback("__Lang_CallbackGuiCtrlSetData", $idButton)
__Lang_SetCallback($iCallbackButton, "setExampleNumberTo10")

$iTop += $iCtrlHeight+$iSpace
Local $idCombo = GUICtrlCreateCombo("", $iLeft, $iTop, $iCtrlWidth, $iCtrlHeight)
Local $iCallbackCombo = __Lang_CreateCallback("_CallbackCombo", $idCombo, 10)
__Lang_SetCallback($iCallbackCombo)

$iTop += $iCtrlHeight+$iSpace
Local $idLabelExampleMissingKey = GUICtrlCreateLabel("", $iLeft, $iTop, $iCtrlWidth, $iCtrlHeight)
Local $iCallbackExampleMissingKey = __Lang_CreateCallback("__Lang_CallbackLabel", $idLabelExampleMissingKey)
__Lang_SetCallback($iCallbackExampleMissingKey, "missingKeyExample")

$iTop += $iCtrlHeight+$iSpace
Local $idButtonAdd = GUICtrlCreateButton("", $iLeft, $iTop, $iCtrlWidth, $iCtrlHeight)
Local $iCallbackButtonAdd = __Lang_CreateCallback("__Lang_CallbackGuiCtrlSetData", $idButtonAdd)
__Lang_SetCallback($iCallbackButtonAdd, "addLabel")

$iTop += $iCtrlHeight+$iSpace

GUISetState(@SW_SHOW, $hGui)
Local $idLabelAdded, $iCallbackLabelAdded = Default

While True
    Local $iMsg = GUIGetMsg()
    Switch $iMsg
        Case -3
            Exit
        Case $idButton
            __Lang_SetCallback($iCallbackExampleNumber, "exampleNumberIs", 10)
        Case $idButtonAdd
            If $iCallbackLabelAdded=Default Then
                $idLabelAdded = GUICtrlCreateLabel("", $iLeft, $iTop, $iCtrlWidth, $iCtrlHeight)
                $iCallbackLabelAdded = __Lang_CreateCallback("__Lang_CallbackLabel", $idLabelAdded)
                __Lang_SetCallback($iCallbackLabelAdded, "thisLabelWasAdded")
                __Lang_SetCallback($iCallbackButtonAdd, "removeLabel")
            Else
                GUICtrlDelete($idLabelAdded)
                ; delete callbacks if they are no longer used
                __Lang_DeleteCallback($iCallbackLabelAdded)
                $iCallbackLabelAdded = Default
                __Lang_SetCallback($iCallbackButtonAdd, "addLabel")
            EndIf
        Case Else
            If $idMenuLangFirst<>Default And $iMsg>=$idMenuLangFirst And $iMsg<$idMenuLangFirst+UBound($arLanguages) Then
                ConsoleWrite(__Lang_Get("switchLanguageTo", $arLanguages[$iMsg-$idMenuLangFirst][1])&@crlf)
                __Lang_Load($arLanguages[$iMsg-$idMenuLangFirst][0])
            EndIf
    EndSwitch
WEnd

Func _CallbackWinTitle($sKey, $sVal, $bRTL)
    WinSetTitle($hGui, "", $sVal)
EndFunc

Func _CallbackCombo($bRTL, $idCtrl, $iItemCount)
    Local $iStyle = __Lang__GUICtrlGetStyle($idCtrl)
    Local $iExStyle = __Lang__GUICtrlGetStyleEx($idCtrl)
    If $bRTL And Not BitAND($iExStyle, $WS_EX_RIGHT) Then
        GUICtrlSetStyle($idCtrl, $iStyle, BitOR(BitAND($iExStyle, BitNOT($WS_EX_LEFT)), $WS_EX_RIGHT))
    ElseIf Not $bRTL And Not BitAND($iStyle, $WS_EX_LEFT) Then
        GUICtrlSetStyle($idCtrl, $iStyle, BitOR(BitAND($iExStyle, BitNOT($WS_EX_RIGHT)), $WS_EX_LEFT))
    EndIf
    _GUICtrlComboBox_BeginUpdate($idCtrl)
    While _GUICtrlComboBox_GetCount($idCtrl)>0
        _GUICtrlComboBox_DeleteString($idCtrl, 0)
    WEnd
    For $i=0 To $iItemCount-1
        _GUICtrlComboBox_AddString($idCtrl, __Lang_Get("comboEntry", $i+1))
    Next
    _GUICtrlComboBox_EndUpdate($idCtrl)
EndFunc

Example language config:

[en]
Name=English
thisIsALongSentence=This is a long sentence.
exampleNumberIs=Example number is %i.
thisIsOnlyAvailableInEnglish=This is only available in english.
setExampleNumberTo10=Set example number to 10
switchLanguageTo=Switch language to %s
addLabel=Add label
removeLabel=Remove label
thisLabelWasAdded=This label was added
comboEntry=Combo entry: %i
autoitLanguageExample=AutoIt Language Example
[de]
Name=Deutsch
File=lang\de.ini
autoitLanguageExample=AutoIt Sprach Beispiel

Changelog:

v1.0.0
- release

The example is provided as a zip file to include the .ini files. The Lang-Example.au3 must be put one directory above the UDF (or the path to the UDF needs to be adjusted).

If you like it, please leave me a comment, also if you have any suggestions to make it better or if you find bugs.


Thank you to everyone helping to improve the UDF :)

Lang.au3 example.zip

Edited by Kanashius
Posted

Hi and thanks @Kanashiusย for the UDF and the approach ๐Ÿค .
I just had a quick look at the GitHub repository and I like it.

A few things to consider:

  • INI files don't provide multi-line strings/texts which could be a problem.
  • INI files can have issues (depending on the codepage) with German umlauts or other special characters.
    • AutoIt's INI usage doesn't adequately consider the codepage, if I remember correctly.
    • That's why I switched to JSON with @AspirinJunkieย JSON UDF (or use jq).

So my suggestion would be, JSON usage instead of INI.
But as always, these are my 2 Cents and I appreciate your effort and the UDF you're sharing, thanks.

Best regards
Sven

==> AutoIt related: ๐Ÿ”—ย Organization AutoIt Community,ย ๐Ÿ”— GitHub, ๐Ÿ”— Discord Server, ๐Ÿ”—ย Cheat Sheet,ย ๐Ÿ”—ย autoit-webdriver-boilerplate

Spoiler

๐ŸŒย Au3Forums

๐ŸŽฒ AutoIt (en) Cheat Sheet

๐Ÿ“Š AutoIt limits/defaults

๐Ÿ’Ž Code Katas: [...] (comming soon)

๐ŸŽญ Collection of GitHub users with AutoIt projects

๐Ÿžย False-Positives

๐Ÿ”ฎย Me on GitHub

๐Ÿ’ฌย Opinion about new forum sub category

๐Ÿ“‘ย UDF wiki list

โœ‚ย VSCode-AutoItSnippets

๐Ÿ“‘ย WebDriver FAQs

๐Ÿ‘จโ€๐Ÿซย WebDriver Tutorial (coming soon)

Posted (edited)
10 minutes ago, SOLVE-SMART said:

INI files can have issues (depending on the codepage) with German umlauts or other special characters.

  • AutoIt's INI usage doesn't adequately consider the codepage, if I remember correctly.

ย 

I see: you do not use the build-in AutoIt INI functions. Smart move ๐Ÿ‘ .

Then my only consern is the lack of multi-line support which also could be handled by adding \n to the INI string and replace it in the UDF function (as one approach).
What ever, thanks again.

Best regards
Sven

Edited by SOLVE-SMART

==> AutoIt related: ๐Ÿ”—ย Organization AutoIt Community,ย ๐Ÿ”— GitHub, ๐Ÿ”— Discord Server, ๐Ÿ”—ย Cheat Sheet,ย ๐Ÿ”—ย autoit-webdriver-boilerplate

Spoiler

๐ŸŒย Au3Forums

๐ŸŽฒ AutoIt (en) Cheat Sheet

๐Ÿ“Š AutoIt limits/defaults

๐Ÿ’Ž Code Katas: [...] (comming soon)

๐ŸŽญ Collection of GitHub users with AutoIt projects

๐Ÿžย False-Positives

๐Ÿ”ฎย Me on GitHub

๐Ÿ’ฌย Opinion about new forum sub category

๐Ÿ“‘ย UDF wiki list

โœ‚ย VSCode-AutoItSnippets

๐Ÿ“‘ย WebDriver FAQs

๐Ÿ‘จโ€๐Ÿซย WebDriver Tutorial (coming soon)

Posted

Sorry for me being so nitpicky today ๐Ÿ˜‡ :
You useย __Lang__GUICtrlGetStyleย in the Lang-Example.au3 file. This function is grouped into the "; #INTERNAL_USE_ONLY#" section in your UDF. Usually when it is internal, the user shouldn't be use the function directly - only your UDF does. But you showed how to use the internal function in the example script.

...ย Thinking about it more closely: I have no idea why that triggered me. It doesn't really matter.ย I have to get more sleep tonight. The last few days were heavy regarding working.

Best regards
Sven

==> AutoIt related: ๐Ÿ”—ย Organization AutoIt Community,ย ๐Ÿ”— GitHub, ๐Ÿ”— Discord Server, ๐Ÿ”—ย Cheat Sheet,ย ๐Ÿ”—ย autoit-webdriver-boilerplate

Spoiler

๐ŸŒย Au3Forums

๐ŸŽฒ AutoIt (en) Cheat Sheet

๐Ÿ“Š AutoIt limits/defaults

๐Ÿ’Ž Code Katas: [...] (comming soon)

๐ŸŽญ Collection of GitHub users with AutoIt projects

๐Ÿžย False-Positives

๐Ÿ”ฎย Me on GitHub

๐Ÿ’ฌย Opinion about new forum sub category

๐Ÿ“‘ย UDF wiki list

โœ‚ย VSCode-AutoItSnippets

๐Ÿ“‘ย WebDriver FAQs

๐Ÿ‘จโ€๐Ÿซย WebDriver Tutorial (coming soon)

Posted

Hey, thanks for the suggestions :)

Yeah, I stumbled over the text encoding myself when using the arabic text (google translated, so please don't judge any errors there ๐Ÿ˜…).

4 hours ago, SOLVE-SMART said:

INI files don't provide multi-line strings/texts which could be a problem.

As mentioned in the function documentations, all values are formatted with StringFormat (Please say, if I missed it at an important function), which uses/supports escape strings.
So when creating the language files, not all characters can be used without escaping (e.g. %,...). This include \n for line breaks.
So they are already supported, but it may not be very pretty for long texts.
Maybe I should make that more clear at the __Lang_Load functionย ๐Ÿค”.

4 hours ago, SOLVE-SMART said:

This function is grouped into the "; #INTERNAL_USE_ONLY#" section

I am a little undecided about that myself and I understand why it triggered you ;)ย . My thinking is, that it is not really providing any real functionality for the UDF. It is just a little helper method I use. So I like to keep it out of the "official" functions for the UDF. At the same time, I do not mind people using the functions, but this way I do not need to do error handling for parameters,... its up to the developer to use them or not and make sure everything works.
I had the same approach for some methods in the TreeListExplorer UDF, where some path methods,... are internal use, but may be helpful for users (and I think I used/suggested some to WildByDesign when helping him). I simply do not check the parameters (for performance reasons, easier implementation,... ).

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...