patch 9.1.0559: translation of vim scripts can be improved

Commit: 
https://github.com/vim/vim/commit/965091001fc131192f0bca49917ed6567cf8f060
Author: RestorerZ <resto...@mail2k.ru>
Date:   Thu Jul 11 21:14:15 2024 +0200

    patch 9.1.0559: translation of vim scripts can be improved
    
    Problem:  translation of vim scripts can be improved
              (after v9.1.0509)
    Solution: improve documentation, add tests, include missing
              libraries for the Windows CI
              (RestorerZ)
    
    closes: #15100
    
    Signed-off-by: RestorerZ <resto...@mail2k.ru>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1110665ec..46eda8d7e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -434,6 +434,9 @@ jobs:
       # SODIUM_MINGW_URL: 
https://download.libsodium.org/libsodium/releases/libsodium-%SODIUM_VER%-stable-mingw.tar.gz
       SODIUM_MINGW_URL: 
https://github.com/jedisct1/libsodium/releases/download/%SODIUM_VER%-RELEASE/libsodium-%SODIUM_VER%-mingw.tar.gz
       SODIUM_MINGW_VER: 26
+      # Gettext-tools, iconv and libraries
+      GETTEXT32_URL: 
https://github.com/mlocati/gettext-iconv-windows/releases/download/v0.21-v1.16/gettext0.21-iconv1.16-shared-32.zip
+      GETTEXT64_URL: 
https://github.com/mlocati/gettext-iconv-windows/releases/download/v0.21-v1.16/gettext0.21-iconv1.16-shared-64.zip
       # Escape sequences
       COL_RED: "\x1b[31m"
       COL_GREEN: "\x1b[32m"
@@ -501,6 +504,7 @@ jobs:
             echo "SODIUM_DIR_SLASH=${SODIUM_DIR_SLASH}" >> $GITHUB_ENV
           fi
           echo "SODIUM_DIR=${SODIUM_DIR}" >> $GITHUB_ENV
+          echo "GETTEXT_PATH=D:\gettext${{ matrix.arch == 'x64' && '64' || 
'32' }}" >> $GITHUB_ENV
 
       - uses: msys2/setup-msys2@v2
         if: matrix.toolchain == 'mingw'
@@ -522,6 +526,8 @@ jobs:
           echo %LUA_RELEASE%>> urls.txt
           echo %WINPTY_URL%>> urls.txt
           echo %SODIUM_VER%>> urls.txt
+          echo %GETTEXT32_URL%>> urls.txt
+          echo %GETTEXT64_URL%>> urls.txt
 
       - name: Cache downloaded files
         uses: actions/cache@v4
@@ -555,6 +561,12 @@ jobs:
             mklink %SODIUM_LIB%\libsodium.dll 
%SODIUM_LIB%\libsodium-%SODIUM_MINGW_VER%.dll
           )
 
+          echo %COL_GREEN%Download Gettext%COL_RESET%
+          call :downloadfile %GETTEXT${{ env.BITS }}_URL% downloads\gettext${{ 
env.BITS }}.zip
+          7z e -y downloads\gettext${{ env.BITS }}.zip -oD:\gettext${{ 
env.BITS }} > nul || exit 1
+          copy /y D:\gettext${{ env.BITS }}\libintl-8.dll src\ || exit 1
+          copy /y D:\gettext${{ env.BITS }}\libiconv-2.dll src\ || exit 1
+
           goto :eof
 
           :downloadfile
diff --git a/ci/appveyor.bat b/ci/appveyor.bat
index 549876951..c77cee19d 100644
--- a/ci/appveyor.bat
+++ b/ci/appveyor.bat
@@ -1,15 +1,20 @@
 @echo off
 :: Batch file for building/testing Vim on AppVeyor
 set target=%1
+set "GETTEXT_PATH=c:\gettext64 in"
 
 setlocal ENABLEDELAYEDEXPANSION
 cd %APPVEYOR_BUILD_FOLDER%
 
 :: Python3
-set PYTHON3_VER=311
-set PYTHON3_RELEASE=3.11.1
-set 
PYTHON3_URL=https://www.python.org/ftp/python/%PYTHON3_RELEASE%/python-%PYTHON3_RELEASE%-amd64.exe
-set PYTHON3_DIR=C:\python%PYTHON3_VER%-x64
+set "PYTHON3_VER=311"
+set "PYTHON3_RELEASE=3.11.1"
+set 
"PYTHON3_URL=https://www.python.org/ftp/python/%PYTHON3_RELEASE%/python-%PYTHON3_RELEASE%-amd64.exe";
+set "PYTHON3_DIR=C:\python%PYTHON3_VER%-x64"
+
+:: Gettext-tools, iconv and libraries
+set 
"GETTEXT64_URL=https://github.com/mlocati/gettext-iconv-windows/releases/download/v0.21-v1.16/gettext0.21-iconv1.16-shared-64.zip";
+set "GETTEXT64_DIR=c:\gettext64"
 
 set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer swhere.exe"
 
@@ -43,6 +48,18 @@ if not exist %PYTHON3_DIR% (
       AssociateFiles=0 Shortcuts=0 Include_doc=0 Include_launcher=0 ^
       InstallLauncherAllUsers=0
 )
+:: GETTEXT
+if not exist %GETTEXT64_DIR% (
+  mkdir %GETTEXT64_DIR%
+  call :downloadfile %GETTEXT64_URL% downloads\gettext64.zip
+  cmd /c powershell.exe -NoLogo -NoProfile -Command ^
+    Add-Type -AssemblyName 'System.IO.Compression.FileSystem'; ^
+    
[System.IO.Compression.ZipFile]::ExtractToDirectory^('downloads\gettext64.zip', 
^
+    '%GETTEXT64_DIR%'^)
+    copy /y %GETTEXT64_DIR% in\libintl-8.dll C:\projects im\src\ || exit 1
+    copy /y %GETTEXT64_DIR% in\libiconv-2.dll C:\projects im\src\ || exit 1
+)
+
 @echo off
 goto :eof
 
@@ -92,7 +109,7 @@ goto :eof
 @echo on
 cd src/testdir
 :: Testing with MSVC gvim
-path %PYTHON3_DIR%;%PATH%
+path %PYTHON3_DIR%;%GETTEXT_PATH%;%PATH%
 nmake -f Make_mvc.mak VIMPROG=..\gvim
 nmake -f Make_mvc.mak clean
 :: Testing with MSVC console version
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 9c3d7a91f..f3baf2470 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1,4 +1,4 @@
-*builtin.txt*  For Vim version 9.1.  Last change: 2024 Jul 09
+*builtin.txt*  For Vim version 9.1.  Last change: 2024 Jul 11
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1226,7 +1226,7 @@ bindtextdomain({package}, {path})                 
*bindtextdomain()*
                Bind a specific {package} to a {path} so that the
                |gettext()| function can be used to get language-specific
                translations for a package.  {path} is the directory name
-               for the translations. See |package-create|.
+               for the translations. See |package-translation|.
 
                Return type: none
 
@@ -5005,17 +5005,18 @@ gettagstack([{winnr}])                                  
*gettagstack()*
 
 gettext({text} [, {package}])                          *gettext()*
                Translate String {text} if possible.
-               This is mainly for use in the distributed Vim scripts.  When
-               generating message translations the {text} is extracted by
-               xgettext, the translator can add the translated message in the
-               .po file and Vim will lookup the translation when gettext() is
-               called.
+               This is intended for use in Vim scripts.  When generating
+               message translations the {text} is extracted by `xgettext`,
+               the translator can add translated messages into the .po file
+               and Vim will lookup the translation when gettext() is called.
                For {text} double quoted strings are preferred, because
-               xgettext does not understand escaping in single quoted
-               strings.
+               `xgettext` does not support single quoted escaped text.
+
                When the {package} is specified, the translation is looked up
-               for that specific package. You need to specify the path to
-               look for translations with the |bindtextdomain()| function.
+               for that specific package.  This is mainly required for
+               third-party Vim scripts.  You need to specify a path to the
+               translations with the |bindtextdomain()| function before
+               using the gettext() function.
 
                Return type: |String|
 
diff --git a/runtime/doc/mlang.txt b/runtime/doc/mlang.txt
index 82c9772a7..9a15bdfb5 100644
--- a/runtime/doc/mlang.txt
+++ b/runtime/doc/mlang.txt
@@ -1,4 +1,4 @@
-*mlang.txt*     For Vim version 9.1.  Last change: 2022 Sep 17
+*mlang.txt*     For Vim version 9.1.  Last change: 2024 Jul 11
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -59,7 +59,9 @@ use of "-" and "_".
 :lan[guage] tim[e] {name}
 :lan[guage] col[late] {name}
                        Set the current language (aka locale) to {name}.
-                       The locale {name} must be a valid locale on your
+                       The POSIX format of {name} is: >
+                               language[_territory][.encoding]
+<                      The locale {name} must be a valid locale on your
                        system.  Some systems accept aliases like "en" or
                        "en_US", but some only accept the full specification
                        like "en_US.ISO_8859-1".  On Unix systems you can use
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index e28f185aa..2dc08e257 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*  For Vim version 9.1.  Last change: 2024 Jul 09
+*options.txt*  For Vim version 9.1.  Last change: 2024 Jul 11
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -6753,7 +6753,7 @@ A jump table for the options with a short description can 
be found at |Q_op|.
          import/       files that are found by `:import`
          indent/       indent scripts |indent-expression|
          keymap/       key mapping files |mbyte-keymap|
-         lang/         menu translations |:menutrans|
+         lang/         message translations |:menutrans| and |multi-lang|
          menu.vim      GUI menus |menu.vim|
          pack/         packages |:packadd|
          plugin/       plugin scripts |write-plugin|
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 0bfb1177c..f2ba03f90 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -1,4 +1,4 @@
-*repeat.txt*    For Vim version 9.1.  Last change: 2024 Jun 20
+*repeat.txt*    For Vim version 9.1.  Last change: 2024 Jul 11
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -735,7 +735,7 @@ Your directory layout would be like this:
    start/foobar/autoload/foo.vim       " loaded when foo command used
    start/foobar/doc/foo.txt            " help for foo.vim
    start/foobar/doc/tags               " help tags
-   start/foobar/lang/<lang_id>/LC_MESSAGES/foo.po
+   start/foobar/lang/<lang_id>/LC_MESSAGES/foobar.mo
                                        " messages for the plugin in the
                                        " <lang_id> language.  These files are
                                        " optional.
@@ -748,53 +748,345 @@ This allows for the user to do: >
        mkdir ~/.vim/pack
        cd ~/.vim/pack
        git clone https://github.com/you/foobar.git myfoobar
-
+<
 Here "myfoobar" is a name that the user can choose, the only condition is that
 it differs from other packages.
 
 In your documentation you explain what the plugins do, and tell the user how
 to load the optional plugin: >
        :packadd! fooextra
-
+<
 You could add this packadd command in one of your plugins, to be executed when
 the optional plugin is needed.
 
+                                       *package-doc* *package-documentation*
 Run the `:helptags` command to generate the doc/tags file.  Including this
 generated file in the package means that the user can drop the package in the
 pack directory and the help command works right away.  Don't forget to re-run
 the command after changing the plugin help: >
        :helptags path/start/foobar/doc
        :helptags path/opt/fooextra/doc
-
-The messages that are in the lang/<lang_id>/LC_MESSAGES/foo.po file need to be
-translated to a format that the |gettext()| function understands by running the
-msgfmt program. This will result in a lang/<lang_id>/LC_MESSAGES/foo.mo
-file. See |multilang| on how to specify languages.
-
-In your plugin, you need to call the |bindtextdomain()| function as follows.
-This assumes that the directory structure is as above: >
-       :call bindtextdomain("foo", fnamemodify(expand("<script>"), ':p:h')
-        .. '/../lang/')
 <
-You only need to do this once. After this call, you can use: >
-       :echo gettext("Hello", "foo")
+                                                       *package-translation*
+In order for a plugin to display translated messages, a few steps are
+required.
+The author of the plugin who likes to translate messages must define the name
+of the package and the location of the directory where the translations can be
+found using the |bindtextdomain()| function: >
+       :call bindtextdomain("foobar",
+       \ fnamemodify(expand("<script>"), ':p:h') .. '/../lang/')
+<
+Where:
+  "foobar"     is the unique package identifier by which the |gettext()|
+               function will later search for translation strings for this
+               plugin.
+  "lang/"      is the relative or absolute path to the directory structure
+               where the translation file is located.
+
+The directory structure where the message translation files should be placed
+is (from the top-level directory of the package):
+"lang/<lang_id>/LC_MESSAGES". For the format of <lang_id> see |multi-lang|.
+This function needs to be called only once during the initialization of the
+plugin.
+Once this is done, the |gettext()| function can be used to retrieve translated
+messages: >
+       :echo gettext("Hello", "foobar")
+<
+Where:
+  "Hello"      the message "Hello" to be translated into the user's language 
|:lang|
+  "foobar"     the package identifier, which was previously defined using the
+               |bindtextdomain()| function.
+
+After that you need to create a template file for translation - POT-file.
+To do this, execute the following commands (using the Vim repository): >
+       cd ~/forkvim/src/po
+       make -f Makefile "PLUGPACKAGE={package}" \
+       "PO_PLUG_INPUTLIST={path/to/scripts-that-need-translations.vim}" \
+       ["POT_PLUGPACKAGE_PATH={path/where/to/write/{package}.pot}" \]
+       ["VIMPROG={path/to/vim} \]
+       {package}.pot
+<
+Where:
+PLUGPACKAGE            A variable containing the name of the package that we
+                       specified in the |bindtextdomain()| and
+                       |gettext()| functions, for example, "foobar".
+PO_PLUG_INPUTLIST      A variable containing scripts that have strings
+                       to translate, i.e. where we specified the |gettext()|
+                       function. Scripts are specified with an absolute
+                       or relative path. Example: start/foobar/plugin/bar.vim
+                       use blanks to separate scripts.
+POT_PLUGPACKAGE_PATH   A variable containing the directory where the prepared
+                       POT file will be saved. This is not a required variable,
+                       if no directory is specified, then the POT file will
+                       be placed in the "src/po" directory.
+VIMPROG                        A variable containing a directory with a 
working Vim.
+                       If the Vim editor is already built and installed, and
+                       is contained in the $PATH environment variable,
+                       then you can specify just the name of the vim
+                       executable.
+{package}.pot          This is the Target. It is specified as the name of
+                       the package, for example, "foobar" with the addition
+                       of the .pot extension.
+Once a POT file is created, its contents are copied into separate PO files for
+each language for which the translation will be prepared.
+
+When the translation is finished, it is necessary to convert the PO files into
+binary MO-files format and place these MO-files into the "lang/" directory, the
+structure of which we created earlier.
+To do this, run the following commands:
+>
+       cd ~/forkvim/src/po
+       make -f Makefile "PLUGPACKAGE={package}" \
+       "PO_PLUGPACKAGE={path/to/{lang}.po}" \
+       ["MO_PLUGPACKAGE_PATH={path/to/lang/<lang_id>/LC_MESSAGES}" \]
+       {package}.mo
+<
+Where:
+PLUGPACKAGE            A variable containing the name of the package that we
+                       specified in the |bindtextdomain()| and |gettext()|
+                       functions, for example, "foobar".
+PO_PLUGPACKAGE         A variable containing a PO file. The file is specified
+                       with an absolute or relative path. For example,
+                       "~/myproject/translate/en.po"
+MO_PLUGPACKAGE_PATH    A variable containing the structure of the "lang/"
+                       directory, where the file with translations will be
+                       placed, for example, "foobar.mo". This is not
+                       a required variable, if the directory is not specified,
+                       the MO file will be saved in the "src/po" directory.
+{package}.mo           This is the Target. It is specified as the name of
+                       the package, for example, "foobar" with the addition
+                       of the .mo extension.
+
+                                               *package-translate_example*
+Let's show it all on some concrete example and translate the
+"ftplugin/aap.vim" file into Russian and German.
+
+First, let's prepare the "aap.vim" file, specifying |bindtextdomain()| and
+|gettext()| function calls in it.
+>
+ " Only do this when not done yet for this buffer
+ if exists("b:did_ftplugin")
+     finish
+ endif
+
+ " Don't load another plugin for this buffer
+ let b:did_ftplugin = 1
+ call bindtextdomain("aap", fnamemodify(expand("<script>"), ':p:h') .. 
'/../lang/')
+
+ " Reset 'formatoptions', 'comments', 'commentstring' and 'expandtab' to undo
+ " this plugin.
+ let b:undo_ftplugin = "setl fo< com< cms< et<"
+
+ " Set 'formatoptions' to break comment lines but not other lines,
+ " and insert the comment leader when hitting <CR> or using "o".
+ setlocal fo-=t fo+=croql
+
+ " Set 'comments' to format dashed lists in comments.
+ setlocal comments=s:#\ -,m:#\ \ ,e:#,n:#,fb:-
+ setlocal commentstring=#\ %s
+
+ " Expand tabs to spaces to avoid trouble.
+ setlocal expandtab
+
+ if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = gettext("Aap Recipe Files (*.aap)        *.aap
", "aap")
+ if has("win32")
+     let b:browsefilter ..= gettext("All Files (*.*)   *
", "aap")
+ else
+     let b:browsefilter ..= gettext("All Files (*)     *
", "aap")
+ endif
+ let b:undo_ftplugin ..= " | unlet! b:browsefilter"
+ endif
+<
+Now let's create a POT file for it (example uses Windows paths):
+>
+       cd /d f: orkvim\src\po
+ (the following command must be entered in one line, here it is separated for 
example)
+       nmake.exe -f Make_mvc.mak "PLUGPACKAGE=aap"
+                   "PO_PLUG_INPUTLIST=d:\Programs im im91 tplugin ap.vim"
+                   "POT_PLUGPACKAGE_PATH=e:\project    ranslate\plugins"
+                   "VIMPROG=d:\Programs im im91 im.exe"
+                   aap.pot
+<
+After the POT file of our package is created, go to the directory where we
+saved it and perform the translation.
+>
+       cd /d e:\project        ranslate\plugins
+       copy aap.pot ru.po
+       copy aap.pot de.po
+<
+We have prepared a PO file with a translation into Russian:
+    # Test plugins translate ~
+    # ~
+    msgid "" ~
+    msgstr "" ~
+    "Project-Id-Version: aap
" ~
+    "Report-Msgid-Bugs-To: 
" ~
+    "POT-Creation-Date: 2024-06-23 14:58+0300
" ~
+    "PO-Revision-Date: 2024-06-23 14:58+0300
" ~
+    "Last-Translator: Restorer
" ~
+    "Language-Team: RuVim
" ~
+    "Language: ru
" ~
+    "MIME-Version: 1.0
" ~
+    "Content-Type: text/plain; charset=UTF-8
" ~
+    "Content-Transfer-Encoding: 8bit
" ~
+
+    #: ../../runtime/ftplugin/aap.vim:32 ~
+    msgid "Aap Recipe Files (*.aap)    *.aap
" ~
+    msgstr "肖邪泄谢褘 懈薪褋褌褉褍泻褑懈泄 Aap (*.aap)       *.aap
" ~
+
+    #: ../../runtime/ftplugin/aap.vim:34 ~
+    msgid "All Files (*.*)     *
" ~
+    msgstr "袙褋械 褎邪泄谢褘 (*.*)    *
" ~
+
+    #: ../../runtime/ftplugin/aap.vim:36 ~
+    msgid "All Files (*)       *
" ~
+    msgstr "袙褋械 褎邪泄谢褘 (*)      *
" ~
+
+And the PO file in German:
+    # Test plugins translate~
+    #~
+    msgid ""~
+    msgstr ""~
+    "Project-Id-Version: aap
"~
+    "Report-Msgid-Bugs-To: 
"~
+    "POT-Creation-Date: 2024-06-23 14:58+0300
"~
+    "PO-Revision-Date: 2024-06-24 13:11+0300
"~
+    "Last-Translator: Restorer
"~
+    "Language-Team: German
"~
+    "Language: de
"~
+    "MIME-Version: 1.0
"~
+    "Content-Type: text/plain; charset=UTF-8
"~
+    "Content-Transfer-Encoding: 8bit
"~
+
+    #: ../../runtime/ftplugin/aap.vim:32~
+    msgid "Aap Recipe Files (*.aap)    *.aap
"~
+    msgstr "Aap-Rezeptdateien (*.aap)  *.aap
"~
+
+    #: ../../runtime/ftplugin/aap.vim:34~
+    msgid "All Files (*.*)     *
"~
+    msgstr "Alle Dateien (*.*) *.*
"~
+
+    #: ../../runtime/ftplugin/aap.vim:36~
+    msgid "All Files (*)       *
"~
+    msgstr "Alle Dateien (*)   *
"~
+
+Now convert these files into MO files so that |gettext()| can display message
+translations. Note that since this is not a specialized plugin package, we
+will put the MO files in the "lang/" directory of the Vim editor.
+Type the following commands:
+>
+       cd /d f: orkvim\src\po
+ (the following command must be entered in one line, here it is separated for 
example)
+ For Russian:
+       nmake.exe -f Make_mvc.mak "PLUGPACKAGE=aap"
+       "PO_PLUGPACKAGE=e:\project      ranslate\plugins
u.po"
+       "MO_PLUGPACKAGE_PATH=d:\Programs im im91\lang
u\LC_MESSAGES"
+       aap.mo
+ For German:
+       nmake.exe -f Make_mvc.mak "PLUGPACKAGE=aap"
+       "PO_PLUGPACKAGE=e:\project      ranslate\plugins\de.po"
+       "MO_PLUGPACKAGE_PATH=d:\Programs im im91\lang\de\LC_MESSAGES"
+       aap.mo
+<
+That's it, the translations are ready and you can see the plugin's messages
+in your native language.
+
+Let's also try to translate a plugin package. For example, when a package
+contains several scripts containing strings that need to be translated.
+For example, let's translate the "netrw" package into Japanese.
+For this example, we will translate only a few lines from this package.
+Let's prepare the scripts where we need to translate the message strings.
+
+The file "autoload
etrw.vim":
+>
+ " Load Once:
+ if &cp || exists("g:loaded_netrw")
+   finish
+ endif
+ call bindtextdomain("netrw", fnamemodify(expand("<script>"), ':p:h') .. 
'/../lang/')
+
+ " Check that vim has patches that netrw requires.
+ " Patches needed for v7.4: 1557, and 213.
+ " (netrw will benefit from vim's having patch#656, too)
+ let s:needspatches=[1557,213]
+ if exists("s:needspatches")
+  for ptch in s:needspatches
+   if v:version < 704 || (v:version == 704 && !has("patch".ptch))
+    if !exists("s:needpatch{ptch}")
+     unsilent echomsg gettext("***sorry*** this version of netrw requires vim 
v7.4 with patch#", "netrw") .. ptch
+    endif
+    let s:needpatch{ptch}= 1
+    finish
+   endif
+  endfor
+ endif
+<
+The file "autoload
etrwSettings.vim":
+>
+ " Load Once:
+ if exists("g:loaded_netrwSettings") || &cp
+   finish
+ endif
+ call bindtextdomain("netrw", fnamemodify(expand("<script>"), ':p:h') .. 
'/../lang/')
+ let g:loaded_netrwSettings = "v18"
+ if v:version < 700
+  echohl WarningMsg
+  echo gettext("***warning*** this version of netrwSettings needs vim 7.0", 
"netrw")
+  echohl Normal
+  finish
+ endif
+<
+Now we will prepare a POT file for further translation of messages.
+Execute the following commands:
+>
+       cd ~/forkvim/src/po
+       make -f Makefile "VIMPROG=/usr/local/bin/vim" "PLUGPACKAGE=netrw" \
+       "POT_PLUGPACKAGE_PATH=~/project/translate/plugins" \
+       "PO_PLUG_INPUTLIST=../../runtime/autoload/netrw.vim
+       ../../runtime/autoload/netrwSettings.vim" \
+       netrw.pot
+<
+Go to the directory with the POT file and make the translation:
+>
+       cd ~/project/translate/plugins
+       cp ./netrw.pot ja.po
 <
-to get the text "Hello" translated to the user's preferred language (if the
-plugin messages have been translated to this language).
-
-To create the foo.po file, you need to create a foo.pot file first. The
-entries in this file need to be translated to the language(s) you want to be
-supported by your plugin.
-
-To create the foo.pot file, run the following command: >
-       cd ~/.vim/pack/start/foobar
-       make -f ~/src/vim/src/po/Makefile PACKAGE=foo \
-       PO_BASEDIR=~/src/vim/src/po PO_INPUTLIST= \
-       PO_VIM_JSLIST="plugin__foo.js plugin__bar.js \
-       autoload__foo.js" \
-       PO_VIM_INPUTLIST="plugin/foo.vim plugin/bar.vim autoload/foo.vim" \
-       foo.pot
+When we have the translation ready in the "ja.po" file:
+    # Test plugins translate ~
+    # ~
+    msgid "" ~
+    msgstr "" ~
+    "Project-Id-Version: netrw
" ~
+    "Report-Msgid-Bugs-To: 
" ~
+    "POT-Creation-Date: 2024-06-23 17:14+0300
" ~
+    "PO-Revision-Date: 2024-06-23 17:14+0300
" ~
+    "Last-Translator: Restorer
" ~
+    "Language-Team: Japanese
" ~
+    "Language: ja
" ~
+    "MIME-Version: 1.0
" ~
+    "Content-Type: text/plain; charset=UTF-8
" ~
+    "Content-Transfer-Encoding: 8bit
" ~
+
+    #: ../../runtime/autoload/netrw.vim:51 ~
+    msgid "***sorry*** this version of netrw requires vim v7.4 with patch#" ~
+    msgstr "" ~
+    "***鐢炽仐瑷炽亗銈娿伨銇涖倱***銇撱伄銉愩兗銈搞儳銉炽伄netrw銇伅銆併儜銉冦儊浠樸亶銇畍im v7.4銇屽繀瑕併仹銇�" ~
+
+    #: ../../runtime/autoload/netrwSettings.vim:28 ~
+    msgid "***warning*** this version of netrwSettings needs vim 7.0" ~
+    msgstr "***璀﹀憡***銇撱伄銉愩兗銈搞儳銉炽伄netrwSettings銇伅vim7.0銇屽繀瑕併仹銇� ~
+
+Convert ja.po to a MO file:
+>
+       cd ~/forkvim/src/po
+       make -f Makefile "PLUGPACKAGE=netrw" \
+       "PO_PLUGPACKAGE=~/project/translate/plugins/ja.po" \
+       "MO_PLUGPACKAGE_PATH=/usr/local/share/vim/vim91/lang/ja/LC_MESSAGES" \
+       netrw.mo
 <
+Executing those steps will allow you to get translation of any third-party
+plug-in packages.
 
 Dependencies between plugins ~
                                                        *packload-two-steps*
diff --git a/runtime/doc/tags b/runtime/doc/tags
index adbc14585..1238a9c8a 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -9308,6 +9308,10 @@ out_timeout      channel.txt     /*out_timeout*
 p      change.txt      /*p*
 pack-add       repeat.txt      /*pack-add*
 package-create repeat.txt      /*package-create*
+package-doc    repeat.txt      /*package-doc*
+package-documentation  repeat.txt      /*package-documentation*
+package-translate_example      repeat.txt      /*package-translate_example*
+package-translation    repeat.txt      /*package-translation*
 packages       repeat.txt      /*packages*
 packload-two-steps     repeat.txt      /*packload-two-steps*
 page-down      intro.txt       /*page-down*
diff --git a/src/po/Make_all.mak b/src/po/Make_all.mak
index c3e645916..ac1122863 100644
--- a/src/po/Make_all.mak
+++ b/src/po/Make_all.mak
@@ -189,8 +189,8 @@ PO_VIM_INPUTLIST = \
        ../../runtime/defaults.vim
 
 PO_VIM_JSLIST = \
-       ________runtime__optwin.js \
-       ________runtime__defaults.js
+       optwin.js \
+       defaults.js
 
 # Arguments for xgettext to pick up messages to translate from the source code.
 XGETTEXT_KEYWORDS = --keyword=_ --keyword=N_ --keyword=NGETTEXT:1,2 
--keyword=PLURAL_MSG:2,4
diff --git a/src/po/Make_mvc.mak b/src/po/Make_mvc.mak
index d56adb0f4..174908ae5 100644
--- a/src/po/Make_mvc.mak
+++ b/src/po/Make_mvc.mak
@@ -40,7 +40,9 @@ VIMRUNTIME = ..\..
untime
 PACKAGE = vim
 # Correct the following line for the where executeable file vim is
 # installed.  Please do not put the path in quotes.
+!IFNDEF VIMPROG
 VIMPROG = .. im.exe
+!ENDIF
 
 # Correct the following line for the directory where gettext et al is
 # installed.  Please do not put the path in quotes.
@@ -498,25 +500,26 @@ files: $(PO_INPUTLIST)
 first_time: files
        "$(VIMPROG)" -u NONE --not-a-term -S tojavascript.vim $(LANGUAGE).po \
                $(PO_VIM_INPUTLIST)
+       @ copy /a . iles+. im_to_js . llfiles
        set OLD_PO_FILE_INPUT=yes
        set OLD_PO_FILE_OUTPUT=yes
        $(XGETTEXT) --default-domain=$(LANGUAGE) --add-comments 
$(XGETTEXT_KEYWORDS) \
-               --files-from=. iles $(PO_VIM_JSLIST)
+               --files-from=. llfiles
        "$(VIMPROG)" -u NONE --not-a-term -S fixfilenames.vim $(LANGUAGE).po \
                $(PO_VIM_INPUTLIST)
-       $(RM) *.js
+       $(RM) *.js . im_to_js
 
 $(PACKAGE).pot: files
        "$(VIMPROG)" -u NONE --not-a-term -S tojavascript.vim $(PACKAGE).pot \
                $(PO_VIM_INPUTLIST)
+       @ copy /a . iles+. im_to_js . llfiles
        set OLD_PO_FILE_INPUT=yes
        set OLD_PO_FILE_OUTPUT=yes
-       $(XGETTEXT) --default-domain=$(PACKAGE) --add-comments 
$(XGETTEXT_KEYWORDS) \
-               --files-from=. iles $(PO_VIM_JSLIST)
-       $(MV) $(PACKAGE).po $(PACKAGE).pot
+       $(XGETTEXT) --default-domain=$(PACKAGE) --output=$(PACKAGE).pot \
+               --add-comments $(XGETTEXT_KEYWORDS) --files-from=. llfiles
        "$(VIMPROG)" -u NONE --not-a-term -S fixfilenames.vim $(PACKAGE).pot \
                $(PO_VIM_INPUTLIST)
-       $(RM) *.js
+       $(RM) *.js . im_to_js
 
 # Only original translations with default encoding should be updated.
 # The files that are converted to a different encoding clearly state "DO NOT 
EDIT".
@@ -546,11 +549,34 @@ cleanup-po: $(LANGUAGE).po
 cleanup-po-all: $(POFILES)
        !"$(VIMPROG)" -u NONE -e -X -S cleanup.vim -c wq $**
 
+#######
+# For translations of plug-ins
+#######
+
+# Preparing the POT file of the plug-in package
+POT_PLUGPACKAGE_PATH = $(MAKEDIR)
+$(PLUGPACKAGE).pot : $(PO_PLUG_INPUTLIST)
+       "$(VIMPROG)" -u NONE --not-a-term -S tojavascript.vim \
+               $(PLUGPACKAGE).pot $**
+       $(XGETTEXT) --from-code=UTF-8 --default-domain=$(PLUGPACKAGE) \
+               --package-name=$(PLUGPACKAGE) \
+               --output-dir="$(POT_PLUGPACKAGE_PATH)" \
+               --output=$(PLUGPACKAGE).pot --files-from=. im_to_js
+       "$(VIMPROG)" -u NONE --not-a-term -S fixfilenames.vim \
+               "$(POT_PLUGPACKAGE_PATH)\$(PLUGPACKAGE).pot" $**
+       $(RM) *.js . im_to_js
+
+# Converting the PO file of the plug-in package to the binary format of the MO 
file
+MO_PLUGPACKAGE_PATH = $(MAKEDIR)
+$(PLUGPACKAGE).mo : $(PO_PLUGPACKAGE)
+       $(MSGFMT) -o $(MO_PLUGPACKAGE_PATH)\$@ $?
+
+
 clean: checkclean
        $(RM) *.mo
        $(RM) *.pot
        $(RM) *.orig
-       $(RM) files
+       $(RM) files allfiles
        $(RM) sjiscorr.obj sjiscorr.exe
 #      $(RM) big5corr.obj big5corr.exe
 
diff --git a/src/po/Makefile b/src/po/Makefile
index eebb7ed64..0f7f85dd1 100644
--- a/src/po/Makefile
+++ b/src/po/Makefile
@@ -1,18 +1,17 @@
 # Makefile for the Vim message translations.
-PO_BASEDIR = .
 
 # Include stuff found by configure.
-include $(PO_BASEDIR)/../auto/config.mk
+include ../auto/config.mk
 
 # Get LANGUAGES, MOFILES, MOCONVERTED and others.
-include $(PO_BASEDIR)/Make_all.mak
+include Make_all.mak
 
 # Note: ja.sjis, *.cp1250 and zh_CN.cp936 are only for MS-Windows, they are
 # not installed on Unix.
 
 PACKAGE = vim
 SHELL = /bin/sh
-VIMPROG = $(PO_BASEDIR)/../vim
+VIMPROG = ../vim
 
 # MacOS sed is locale aware, set $LANG to avoid problems.
 SED = LANG=C sed
@@ -41,8 +40,8 @@ converted: $(MOCONVERTED)
        $(MSGFMTCMD) -o $@ $<
 
 .po.ck:
-       $(VIMPROG) -u NONE --noplugins -e -s -X --cmd "set enc=utf-8" -S 
check.vim \
-               -c "if error == 0 | q | else | num 2 | cq | endif" $<
+       $(VIMPROG) -u NONE --noplugins -e -s -X --cmd "set enc=utf-8" \
+               -S check.vim -c "if error == 0 | q | else | num 2 | cq | endif" 
$<
        touch $@
 
 check: $(CHECKFILES)
@@ -242,6 +241,7 @@ prefixcheck:
 clean: checkclean
        rm -f core core.* *.old.po *.mo *.pot sjiscorr
        rm -f LINGUAS vim.desktop gvim.desktop tmp_*desktop
+       rm -f ./allfiles
 #      rm -f big5corr
 
 distclean: clean
@@ -262,21 +262,25 @@ PO_INPUTLIST = \
 
 $(PACKAGE).pot: $(PO_INPUTLIST) $(PO_VIM_INPUTLIST)
        # Convert the Vim scripts to (what looks like) Javascript.
-       $(VIMPROG) -u NONE --not-a-term -S $(PO_BASEDIR)/tojavascript.vim 
$(PACKAGE).pot $(PO_VIM_INPUTLIST)
+       $(VIMPROG) -u NONE --not-a-term -S tojavascript.vim $(PACKAGE).pot \
+               $(PO_VIM_INPUTLIST)
+       @ echo ${PO_INPUTLIST} | tr ' ' '
' > ./allfiles
+       @ cat ./vim_to_js >> ./allfiles
        # Create vim.pot.
-       $(XGETTEXT) --default-domain=$(PACKAGE) --add-comments \
-               $(XGETTEXT_KEYWORDS) $(PO_INPUTLIST) $(PO_VIM_JSLIST)
-       mv -f $(PACKAGE).po $(PACKAGE).pot
+       $(XGETTEXT) --default-domain=$(PACKAGE) --output=$(PACKAGE).pot \
+               --add-comments $(XGETTEXT_KEYWORDS) --files-from=./allfiles
        # Fix Vim scripts names, so that "gf" works.
-       $(VIMPROG) -u NONE --not-a-term -S $(PO_BASEDIR)/fixfilenames.vim 
$(PACKAGE).pot $(PO_VIM_INPUTLIST)
+       $(VIMPROG) -u NONE --not-a-term -S fixfilenames.vim $(PACKAGE).pot \
+               $(PO_VIM_INPUTLIST)
        # Delete the temporary files.
-       rm *.js
+       rm -f *.js ./vim_to_js
 
 vim.desktop: vim.desktop.in $(POFILES)
        echo $(LANGUAGES) | tr " " "
" |$(SED) -e '/\./d' | sort > LINGUAS
        $(MSGFMT) --desktop -d . --template vim.desktop.in -o tmp_vim.desktop
        rm -f LINGUAS
-       if command -v desktop-file-validate; then desktop-file-validate 
tmp_vim.desktop; fi
+       if command -v desktop-file-validate; \
+               then desktop-file-validate tmp_vim.desktop; fi
        mv tmp_vim.desktop vim.desktop
 
 # The dependency on vim.desktop is only to avoid the two targets are build at
@@ -285,7 +289,8 @@ gvim.desktop: gvim.desktop.in $(POFILES) vim.desktop
        echo $(LANGUAGES) | tr " " "
" |$(SED) -e '/\./d' | sort > LINGUAS
        $(MSGFMT) --desktop -d . --template gvim.desktop.in -o tmp_gvim.desktop
        rm -f LINGUAS
-       if command -v desktop-file-validate; then desktop-file-validate 
tmp_gvim.desktop; fi
+       if command -v desktop-file-validate; \
+               then desktop-file-validate tmp_gvim.desktop; fi
        mv tmp_gvim.desktop gvim.desktop
 
 # Only original translations with default encoding should be updated.
@@ -302,3 +307,28 @@ $(LANGUAGES):
        else \
            echo "msgmerge for $@.po failed!"; mv $@.po.old $@.po; \
        fi
+
+
+#######
+# For translations of plug-ins
+#######
+
+# Preparing the POT file of the plug-in package
+POT_PLUGPACKAGE_PATH != pwd
+$(PLUGPACKAGE).pot: $(PO_PLUG_INPUTLIST)
+       $(VIMPROG) -u NONE --not-a-term -S tojavascript.vim \
+               $(PLUGPACKAGE).pot $?
+       $(XGETTEXT) --from-code=UTF-8 --default-domain=$(PLUGPACKAGE) \
+               --package-name=$(PLUGPACKAGE) \
+               --output-dir=$(POT_PLUGPACKAGE_PATH) \
+               --output=$(PLUGPACKAGE).pot --files-from=./vim_to_js
+       $(VIMPROG) -u NONE --not-a-term -S fixfilenames.vim \
+               $(POT_PLUGPACKAGE_PATH)/$(PLUGPACKAGE).pot $?
+       rm -f *.js ./vim_to_js
+
+# Converting the PO file of the plug-in package to the binary format of the MO
+MO_PLUGPACKAGE_PATH != pwd
+$(PLUGPACKAGE).mo: $(PO_PLUGPACKAGE)
+       $(MSGFMTCMD) -o $(MO_PLUGPACKAGE_PATH)/$@ $<
+
+# vim: set noet sw=8 ts=8 sts=0 wm=0 tw=0 ft=make:
diff --git a/src/po/README.txt b/src/po/README.txt
index 50aff6a83..801f5e56a 100644
--- a/src/po/README.txt
+++ b/src/po/README.txt
@@ -160,3 +160,20 @@ convert ja.po to EUC-JP (supposed as your system encoding):
        "Content-Type: text/plain; charset=EUC-JP
"
 
 There are examples in the Makefile for the conversions already supported.
+
+
+TRANSLATION OF VIM THE EDITOR PLUG-INS
+
+Vim supports displaying plugin messages for various native languages.
+Translation is available both for plugins that are supplied as part of the Vim
+editor (e.g. "optwin.vim") and for third-party plugin packages.
+
+To translate the plugins supplied with the Vim editor, you must specify a
+gettext() function call for the strings you want to translate.
+The translation of these strings will be retrieved by gettext() from the MO
+file "vim.mo".
+
+For third-party plugins, it is necessary to specify a one-time call to the
+bindtextdomain() function in scripts containing translation strings and for
+all message strings to add a {package} argument to the gettext() function. For
+more information, see ":help package-translation".
diff --git a/src/po/README_mvc.txt b/src/po/README_mvc.txt
index ae9fa2b1f..e5fd85e2e 100644
--- a/src/po/README_mvc.txt
+++ b/src/po/README_mvc.txt
@@ -137,4 +137,22 @@ command:
 
        nmake.exe -f Make_mvc.mak clean
 
+
+TRANSLATION OF VIM THE EDITOR PLUG-INS
+
+Vim supports displaying plugin messages for various native languages.
+Translation is available both for plugins that are supplied as part of the Vim
+editor (e.g. "optwin.vim") and for third-party plugin packages.
+
+To translate the plugins supplied with the Vim editor, you must specify a
+gettext() function call for the strings you want to translate.
+The translation of these strings will be retrieved by gettext() from the MO
+file "vim.mo".
+
+For third-party plugins, it is necessary to specify a one-time call to the
+bindtextdomain() function in scripts containing translation strings and for
+all message strings to add a {package} argument to the gettext() function. For
+more information, see ":help package-translation".
+
+
 vim:tw=78:
diff --git a/src/po/fixfilenames.vim b/src/po/fixfilenames.vim
index c92839e55..2344b3bdc 100644
--- a/src/po/fixfilenames.vim
+++ b/src/po/fixfilenames.vim
@@ -3,9 +3,11 @@
 
 set shortmess+=A
 
-for name in argv()[1:]
-  let jsname = fnamemodify(name, ":r:gs?\~?_?:gs?\.?_?:gs?/?__?:gs?\?__?") .. 
".js"
-  exe "%s+" .. jsname .. "+" .. substitute(name, '\', '/', 'g') .. "+"
+let s:namenum = 0
+for s:name in argv()[1:]
+  let s:jsname = fnamemodify(s:name, ":t:r") .. s:namenum .. ".js"
+  exe "%s+" .. s:jsname .. "+" .. substitute(s:name, '\', '/', 'g') .. "+ge"
+  let s:namenum +=1
 endfor
 
 write
diff --git a/src/po/tojavascript.vim b/src/po/tojavascript.vim
index 32eea9b87..4671a472f 100644
--- a/src/po/tojavascript.vim
+++ b/src/po/tojavascript.vim
@@ -5,15 +5,20 @@
 
 set shortmess+=A
 
-for name in argv()[1:]
-  exe 'edit ' .. fnameescape(name)
+let s:namenum = 0
+let s:fls = []
+for s:name in argv()[1:]
+  exe 'edit ' .. fnameescape(s:name)
 
   " Strip comments, also after :set commands.
   g/^\s*"/s/.*//
   g/^\s*set .*"/s/.*//
 
   " Write as .js file, xgettext recognizes them
-  exe 'w! ' .. fnamemodify(name, ":r:gs?\~?_?:gs?\.?_?:gs?/?__?:gs?\?__?") .. 
".js"
+  let s:fl = fnamemodify(s:name, ":t:r") .. s:namenum .. ".js"
+  exe 'w! ' .. s:fl
+  call add(s:fls, s:fl)
+  let s:namenum += 1
 endfor
-
+call writefile(s:fls, "vim_to_js")
 quit
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index f199fec6a..76d44299e 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -166,6 +166,7 @@ NEW_TESTS = \
        test_gettext \
        test_gettext_cp1251 \
        test_gettext_utf8 \
+       test_gettext_make \
        test_getvar \
        test_gf \
        test_glob2regpat \
@@ -428,6 +429,7 @@ NEW_TESTS_RES = \
        test_gettext.res \
        test_gettext_cp1251.res \
        test_gettext_utf8.res \
+       test_gettext_make.res \
        test_getvar.res \
        test_gf.res \
        test_gn.res \
diff --git a/src/testdir/Make_mvc.mak b/src/testdir/Make_mvc.mak
index bd6d1a279..1bf9eae25 100644
--- a/src/testdir/Make_mvc.mak
+++ b/src/testdir/Make_mvc.mak
@@ -42,7 +42,7 @@ report:
                else ( echo No failures reported > test_result.log )
        $(VIMPROG) -u NONE $(COMMON_ARGS) -S summarize.vim messages
        -if exist starttime del starttime
-       @echo.
+       @echo:
        @echo Test results:
        @cmd /c type test_result.log
        @if exist test.log ( echo TEST FAILURE & exit /b 1 ) \
@@ -56,7 +56,7 @@ $(NEW_TESTS):
        -if exist test.log del test.log
        -if exist messages del messages
        -if exist starttime del starttime
-       @$(MAKE) -nologo -f Make_mvc.mak $@.res VIMPROG=$(VIMPROG)
+       @$(MAKE) -nologo -f Make_mvc.mak VIMPROG=$(VIMPROG) $@.res
        @type messages
        @if exist test.log exit 1
 
diff --git a/src/testdir/test_gettext_cp1251.vim 
b/src/testdir/test_gettext_cp1251.vim
index c6f04bb42..c91f7848a 100644
--- a/src/testdir/test_gettext_cp1251.vim
+++ b/src/testdir/test_gettext_cp1251.vim
@@ -1,20 +1,20 @@
 source check.vim
-" TODO: Why does this fail on MacOS 14 and Windows MSVC (Github CI)?
+" This fail on CI MacOS 14 because bindtextdomain() is not available there
+" (missing library?)
 CheckNotMac
-CheckNotMSWindows
 
 " Test for gettext()
 func Test_gettext()
   set encoding=cp1251
   call bindtextdomain("__PACKAGE__", getcwd())
   try
-    language ru_RU
+    language messages ru_RU
     call assert_equal('呜攘世: ', gettext("ERROR: ", "__PACKAGE__"))
   catch /^Vim\%(( \+)\)\=:E197:/
     throw "Skipped: not possible to set locale to ru (missing?)"
   endtry
   try
-    language en_GB.UTF-8
+    language messages en_GB.UTF-8
     call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__"))
   catch /^Vim\%(( \+)\)\=:E197:/
     throw "Skipped: not possible to set locale to en (missing?)"
diff --git a/src/testdir/test_gettext_make.vim 
b/src/testdir/test_gettext_make.vim
new file mode 100644
index 000000000..480e2ee24
--- /dev/null
+++ b/src/testdir/test_gettext_make.vim
@@ -0,0 +1,65 @@
+source check.vim
+"CheckNotMSWindows
+CheckNotMac
+
+" Test for package translation Makefile
+func Test_gettext_makefile()
+  cd ../po
+  if has('win32')
+    call system('nmake.exe -f Make_mvc.mak "VIMPROG=' .. getenv('VIMPROG') ..
+          \ '" "GETTEXT_PATH=' .. getenv('GETTEXT_PATH') ..
+          \ '" PLUGPACKAGE=test_gettext
+          \ "PO_PLUG_INPUTLIST=..      estdir  est_gettext_makefile_in1.vim
+          \ .. estdir  est_gettext_makefile_in2.vim
+          \ .. estdir  est_gettext_makefile_in3.vim
+          \ .. estdir  est_gettext_makefile_in4.vim" test_gettext.pot')
+  else
+" Will it work on macOS?
+    call system("make -f Makefile PLUGPACKAGE=test_gettext
+          \ PO_PLUG_INPUTLIST=\"../testdir/test_gettext_makefile_in1.vim
+          \ ../testdir/test_gettext_makefile_in2.vim
+          \ ../testdir/test_gettext_makefile_in3.vim
+          \ ../testdir/test_gettext_makefile_in4.vim\" test_gettext.pot")
+  endif
+  let expected = [
+          \  '# SOME DESCRIPTIVE TITLE.',
+          \  '# Copyright (C) YEAR THE PACKAGE''S COPYRIGHT HOLDER',
+          \  '# This file is distributed under the same license as the 
test_gettext package.',
+          \  '# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.',
+          \  '#',
+          \  '#, fuzzy',
+          \  'msgid ""',
+          \  'msgstr ""',
+          \  '"Project-Id-Version: test_gettext
"',
+          \  '"Report-Msgid-Bugs-To: 
"',
+          \  '"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
"',
+          \  '"Last-Translator: FULL NAME <EMAIL@ADDRESS>
"',
+          \  '"Language-Team: LANGUAGE <l...@li.org>
"',
+          \  '"Language: 
"',
+          \  '"MIME-Version: 1.0
"',
+          \  '"Content-Type: text/plain; charset=CHARSET
"',
+          \  '"Content-Transfer-Encoding: 8bit
"',
+          \  '',
+          \  '#: ../testdir/test_gettext_makefile_in1.vim:4 
../testdir/test_gettext_makefile_in1.vim:6',
+          \  '#: ../testdir/test_gettext_makefile_in2.vim:5 
../testdir/test_gettext_makefile_in4.vim:4',
+          \  'msgid "This is a test"',
+          \  'msgstr ""',
+          \  '',
+          \  '#: ../testdir/test_gettext_makefile_in1.vim:5',
+          \  'msgid "This is another test"',
+          \  'msgstr ""',
+          \  '',
+          \  '#: ../testdir/test_gettext_makefile_in2.vim:4',
+          \  'msgid "This is a test from the second file"',
+          \  'msgstr ""',
+          \  '',
+          \  '#: ../testdir/test_gettext_makefile_in4.vim:5',
+          \  'msgid "This is a fourth test"',
+          \  'msgstr ""']
+  let potfile = filter(readfile("test_gettext.pot"), 'v:val !~ 
"POT-Creation-Date"')
+  call assert_equal(expected, potfile)
+  call delete('test_gettext.pot')
+  cd -
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_gettext_makefile_in1.vim 
b/src/testdir/test_gettext_makefile_in1.vim
new file mode 100644
index 000000000..cbe11591f
--- /dev/null
+++ b/src/testdir/test_gettext_makefile_in1.vim
@@ -0,0 +1,7 @@
+" Test file for gettext() package makefile
+" Last Change: 2024 Jun 01
+
+echo gettext("This is a test", "test_gettext")
+echo gettext("This is another test", "test_gettext")
+echo gettext("This is a test", "test_gettext")
+" vim: ts=8
diff --git a/src/testdir/test_gettext_makefile_in2.vim 
b/src/testdir/test_gettext_makefile_in2.vim
new file mode 100644
index 000000000..86d3dd9ed
--- /dev/null
+++ b/src/testdir/test_gettext_makefile_in2.vim
@@ -0,0 +1,6 @@
+" Test file for gettext() package makefile
+" Last Change: 2024 Jun 01
+
+echo gettext("This is a test from the second file", "test_gettext")
+echo gettext("This is a test", "test_gettext")
+" vim: ts=8
diff --git a/src/testdir/test_gettext_makefile_in3.vim 
b/src/testdir/test_gettext_makefile_in3.vim
new file mode 100644
index 000000000..f4cf93d1a
--- /dev/null
+++ b/src/testdir/test_gettext_makefile_in3.vim
@@ -0,0 +1,4 @@
+" Test file for gettext() package makefile
+" Last Change: 2024 Jun 01
+
+" vim: ts=8
diff --git a/src/testdir/test_gettext_makefile_in4.vim 
b/src/testdir/test_gettext_makefile_in4.vim
new file mode 100644
index 000000000..7f9f3f7dd
--- /dev/null
+++ b/src/testdir/test_gettext_makefile_in4.vim
@@ -0,0 +1,6 @@
+" Test file for gettext() package makefile
+" Last Change: 2024 Jun 01
+
+echo gettext("This is a test", "test_gettext")
+echo gettext("This is a fourth test", "test_gettext")
+" vim: ts=8
diff --git a/src/testdir/test_gettext_utf8.vim 
b/src/testdir/test_gettext_utf8.vim
index bb46ca0db..7862e39e0 100644
--- a/src/testdir/test_gettext_utf8.vim
+++ b/src/testdir/test_gettext_utf8.vim
@@ -1,20 +1,20 @@
 source check.vim
-" TODO: Why does this fail on MacOS 14 and Windows MSVC (Github CI)?
+" This fail on CI MacOS 14 because bindtextdomain() is not available there
+" (missing library?)
 CheckNotMac
-CheckNotMSWindows
 
 " Test for gettext()
 func Test_gettext()
   set encoding=utf-8
   call bindtextdomain("__PACKAGE__", getcwd())
   try
-    language ru_RU
+    language messages ru_RU
     call assert_equal('袨楔袠袘袣袗: ', gettext("ERROR: ", "__PACKAGE__"))
   catch /^Vim\%(( \+)\)\=:E197:/
     throw "Skipped: not possible to set locale to ru (missing?)"
   endtry
   try
-    language en_GB.UTF-8
+    language messages en_GB.UTF-8
     call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__"))
   catch /^Vim\%(( \+)\)\=:E197:/
     throw "Skipped: not possible to set locale to en (missing?)"
diff --git a/src/version.c b/src/version.c
index aaef85fee..cc2713aa0 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    559,
 /**/
     558,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1sRzUY-000LrN-WB%40256bit.org.

Raspunde prin e-mail lui