diff options
author | Christ van Willegen <cvwillegen@gmail.com> | 2024-06-20 23:41:59 +0200 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2024-06-20 23:41:59 +0200 |
commit | ce0ef910df837b9b961f007a0a35064cad85188b (patch) | |
tree | bd8b18ad704b6166904c78b706b1a4e359e3124b /src | |
parent | f7f8f0b76dc6a3bf5d51825db65245221e5d265e (diff) |
patch 9.1.0509: not possible to translate Vim script messagesv9.1.0509
Problem: not possible to translate Vim script messages
(RestorerZ)
Solution: implement bindtextdomain() and gettext() to support Vim script
message translations (Christ van Willegen)
fixes: #11637
closes: #12447
Signed-off-by: Christ van Willegen <cvwillegen@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Diffstat (limited to 'src')
-rwxr-xr-x | src/auto/configure | 24 | ||||
-rw-r--r-- | src/config.h.in | 7 | ||||
-rw-r--r-- | src/configure.ac | 6 | ||||
-rw-r--r-- | src/evalfunc.c | 55 | ||||
-rw-r--r-- | src/po/Make_all.mak | 4 | ||||
-rw-r--r-- | src/po/Makefile | 11 | ||||
-rw-r--r-- | src/po/fixfilenames.vim | 2 | ||||
-rw-r--r-- | src/po/tojavascript.vim | 2 | ||||
-rw-r--r-- | src/testdir/Make_all.mak | 6 | ||||
-rw-r--r-- | src/testdir/ru_RU/LC_MESSAGES/__PACKAGE__.mo | bin | 0 -> 875 bytes | |||
-rw-r--r-- | src/testdir/test_functions.vim | 5 | ||||
-rw-r--r-- | src/testdir/test_gettext.vim | 16 | ||||
-rw-r--r-- | src/testdir/test_gettext_cp1251.vim | 22 | ||||
-rw-r--r-- | src/testdir/test_gettext_utf8.vim | 22 | ||||
-rw-r--r-- | src/version.c | 2 |
15 files changed, 166 insertions, 18 deletions
diff --git a/src/auto/configure b/src/auto/configure index 98b9580b74..26ac458262 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -15876,6 +15876,30 @@ then : fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dgettext" >&5 +printf %s "checking for dgettext... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <libintl.h> +int +main (void) +{ +dgettext("Test", "Test"); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; }; printf "%s\n" "#define HAVE_DGETTEXT 1" >>confdefs.h + +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _nl_msg_cat_cntr" >&5 printf %s "checking for _nl_msg_cat_cntr... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/src/config.h.in b/src/config.h.in index 8ad9f03136..530c0829f0 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -222,7 +222,6 @@ #undef HAVE_UNSETENV #undef HAVE_USLEEP #undef HAVE_UTIME -#undef HAVE_BIND_TEXTDOMAIN_CODESET #undef HAVE_MBLEN #undef HAVE_TIMER_CREATE #undef HAVE_CLOCK_GETTIME @@ -424,6 +423,12 @@ /* Define if there is a working gettext(). */ #undef HAVE_GETTEXT +/* Define if there is a working bind_textdomain_codeset(). */ +#undef HAVE_BIND_TEXTDOMAIN_CODESET + +/* Define if there is a working dgettext(). */ +#undef HAVE_DGETTEXT + /* Define if _nl_msg_cat_cntr is present. */ #undef HAVE_NL_MSG_CAT_CNTR diff --git a/src/configure.ac b/src/configure.ac index 946fe52ffe..29cd926b56 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -4497,6 +4497,12 @@ if test "$enable_nls" = "yes"; then AC_SUBST(MAKEMO) dnl this was added in GNU gettext 0.10.36 AC_CHECK_FUNCS(bind_textdomain_codeset) + AC_MSG_CHECKING([for dgettext]) + AC_LINK_IFELSE([AC_LANG_PROGRAM( + [#include <libintl.h>], + [dgettext("Test", "Test");])], + AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_DGETTEXT), + AC_MSG_RESULT([no])) dnl _nl_msg_cat_cntr is required for GNU gettext AC_MSG_CHECKING([for _nl_msg_cat_cntr]) AC_LINK_IFELSE([AC_LANG_PROGRAM( diff --git a/src/evalfunc.c b/src/evalfunc.c index 2a0eb27ad5..4fffa50d31 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -28,6 +28,7 @@ static void f_balloon_show(typval_T *argvars, typval_T *rettv); static void f_balloon_split(typval_T *argvars, typval_T *rettv); # endif #endif +static void f_bindtextdomain(typval_T *argvars, typval_T *rettv); static void f_byte2line(typval_T *argvars, typval_T *rettv); static void f_call(typval_T *argvars, typval_T *rettv); static void f_changenr(typval_T *argvars, typval_T *rettv); @@ -1824,6 +1825,8 @@ static funcentry_T global_functions[] = NULL #endif }, + {"bindtextdomain", 2, 2, 0, arg2_string, + ret_void, f_bindtextdomain}, {"blob2list", 1, 1, FEARG_1, arg1_blob, ret_list_number, f_blob2list}, {"browse", 4, 4, 0, arg4_browse, @@ -2154,7 +2157,7 @@ static funcentry_T global_functions[] = ret_any, f_gettabwinvar}, {"gettagstack", 0, 1, FEARG_1, arg1_number, ret_dict_any, f_gettagstack}, - {"gettext", 1, 1, FEARG_1, arg1_string, + {"gettext", 1, 2, FEARG_1, arg2_string, ret_string, f_gettext}, {"getwininfo", 0, 1, FEARG_1, arg1_number, ret_list_dict_any, f_getwininfo}, @@ -3477,6 +3480,24 @@ get_buf_arg(typval_T *arg) } /* + * "bindtextdomain(package, path)" function + */ + static void +f_bindtextdomain(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + if (check_for_nonempty_string_arg(argvars, 0) == FAIL + || check_for_nonempty_string_arg(argvars, 1) == FAIL) + return; + + if (strcmp((const char *)argvars[0].vval.v_string, VIMPACKAGE) == 0) + semsg(_(e_invalid_argument_str), tv_get_string(&argvars[0])); + else + bindtextdomain((const char *)argvars[0].vval.v_string, (const char *)argvars[1].vval.v_string); + + return; +} + +/* * "byte2line(byte)" function */ static void @@ -6033,11 +6054,39 @@ f_gettagstack(typval_T *argvars, typval_T *rettv) static void f_gettext(typval_T *argvars, typval_T *rettv) { - if (check_for_nonempty_string_arg(argvars, 0) == FAIL) +#if defined(HAVE_BIND_TEXTDOMAIN_CODESET) + char *prev = NULL; +#endif + + if (check_for_nonempty_string_arg(argvars, 0) == FAIL + || check_for_opt_string_arg(argvars, 1) == FAIL) return; rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave((char_u *)_(argvars[0].vval.v_string)); + + if (argvars[1].v_type == VAR_STRING && + argvars[1].vval.v_string != NULL && + *(argvars[1].vval.v_string) != NUL) + { +#if defined(HAVE_BIND_TEXTDOMAIN_CODESET) + prev = bind_textdomain_codeset((const char *)argvars[1].vval.v_string, (char *)p_enc); +#endif + +#if defined(HAVE_DGETTEXT) + rettv->vval.v_string = vim_strsave((char_u *)dgettext((const char *)argvars[1].vval.v_string, (const char *)argvars[0].vval.v_string)); +#else + textdomain((const char *)argvars[1].vval.v_string); + rettv->vval.v_string = vim_strsave((char_u *)_(argvars[0].vval.v_string)); + textdomain(VIMPACKAGE); +#endif + +#if defined(HAVE_BIND_TEXTDOMAIN_CODESET) + if (prev != NULL) + bind_textdomain_codeset((const char *)argvars[1].vval.v_string, prev); +#endif + } + else + rettv->vval.v_string = vim_strsave((char_u *)_(argvars[0].vval.v_string)); } // for VIM_VERSION_ defines diff --git a/src/po/Make_all.mak b/src/po/Make_all.mak index ac1122863d..c3e6459164 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 = \ - optwin.js \ - defaults.js + ________runtime__optwin.js \ + ________runtime__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/Makefile b/src/po/Makefile index cc4008fa37..87d657bd90 100644 --- a/src/po/Makefile +++ b/src/po/Makefile @@ -1,17 +1,18 @@ # Makefile for the Vim message translations. +PO_BASEDIR = . # Include stuff found by configure. -include ../auto/config.mk +include $(PO_BASEDIR)/../auto/config.mk # Get LANGUAGES, MOFILES, MOCONVERTED and others. -include Make_all.mak +include $(PO_BASEDIR)/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 -VIM = ../vim +VIM = $(PO_BASEDIR)/../vim # MacOS sed is locale aware, set $LANG to avoid problems. SED = LANG=C sed @@ -261,13 +262,13 @@ PO_INPUTLIST = \ $(PACKAGE).pot: $(PO_INPUTLIST) $(PO_VIM_INPUTLIST) # Convert the Vim scripts to (what looks like) Javascript. - $(VIM) -u NONE --not-a-term -S tojavascript.vim $(PACKAGE).pot $(PO_VIM_INPUTLIST) + $(VIM) -u NONE --not-a-term -S $(PO_BASEDIR)/tojavascript.vim $(PACKAGE).pot $(PO_VIM_INPUTLIST) # Create vim.pot. $(XGETTEXT) --default-domain=$(PACKAGE) --add-comments \ $(XGETTEXT_KEYWORDS) $(PO_INPUTLIST) $(PO_VIM_JSLIST) mv -f $(PACKAGE).po $(PACKAGE).pot # Fix Vim scripts names, so that "gf" works. - $(VIM) -u NONE --not-a-term -S fixfilenames.vim $(PACKAGE).pot $(PO_VIM_INPUTLIST) + $(VIM) -u NONE --not-a-term -S $(PO_BASEDIR)/fixfilenames.vim $(PACKAGE).pot $(PO_VIM_INPUTLIST) # Delete the temporary files. rm *.js diff --git a/src/po/fixfilenames.vim b/src/po/fixfilenames.vim index 04bc0791c0..c92839e556 100644 --- a/src/po/fixfilenames.vim +++ b/src/po/fixfilenames.vim @@ -4,7 +4,7 @@ set shortmess+=A for name in argv()[1:] - let jsname = fnamemodify(name, ":t:r") .. ".js" + let jsname = fnamemodify(name, ":r:gs?\\~?_?:gs?\\.?_?:gs?/?__?:gs?\\?__?") .. ".js" exe "%s+" .. jsname .. "+" .. substitute(name, '\\', '/', 'g') .. "+" endfor diff --git a/src/po/tojavascript.vim b/src/po/tojavascript.vim index 8b0dd736d5..32eea9b875 100644 --- a/src/po/tojavascript.vim +++ b/src/po/tojavascript.vim @@ -13,7 +13,7 @@ for name in argv()[1:] g/^\s*set .*"/s/.*// " Write as .js file, xgettext recognizes them - exe 'w! ' .. fnamemodify(name, ":t:r") .. ".js" + exe 'w! ' .. fnamemodify(name, ":r:gs?\\~?_?:gs?\\.?_?:gs?/?__?:gs?\\?__?") .. ".js" endfor quit diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index e31d2b5f3e..a49f158757 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -161,6 +161,9 @@ NEW_TESTS = \ test_function_lists \ test_ga \ test_getcwd \ + test_gettext \ + test_gettext_cp1251 \ + test_gettext_utf8 \ test_getvar \ test_gf \ test_glob2regpat \ @@ -420,6 +423,9 @@ NEW_TESTS_RES = \ test_functions.res \ test_function_lists.res \ test_getcwd.res \ + test_gettext.res \ + test_gettext_cp1251.res \ + test_gettext_utf8.res \ test_getvar.res \ test_gf.res \ test_gn.res \ diff --git a/src/testdir/ru_RU/LC_MESSAGES/__PACKAGE__.mo b/src/testdir/ru_RU/LC_MESSAGES/__PACKAGE__.mo Binary files differnew file mode 100644 index 0000000000..300eba2137 --- /dev/null +++ b/src/testdir/ru_RU/LC_MESSAGES/__PACKAGE__.mo diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index ba8f18fa5a..8e973f6c9e 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -3865,11 +3865,6 @@ func Test_default_arg_value() call assert_equal('msg', HasDefault()) endfunc -" Test for gettext() -func Test_gettext() - call assert_fails('call gettext(1)', 'E1174:') -endfunc - func Test_builtin_check() call assert_fails('let g:["trim"] = {x -> " " .. x}', 'E704:') call assert_fails('let g:.trim = {x -> " " .. x}', 'E704:') diff --git a/src/testdir/test_gettext.vim b/src/testdir/test_gettext.vim new file mode 100644 index 0000000000..6a5aafdfe2 --- /dev/null +++ b/src/testdir/test_gettext.vim @@ -0,0 +1,16 @@ +source check.vim + +" Test for gettext() +func Test_gettext() + call assert_fails('call bindtextdomain("test")', 'E119:') + call assert_fails('call bindtextdomain("vim", "test")', 'E475:') + + call assert_fails('call gettext(1)', 'E1174:') + call assert_equal('xxxTESTxxx', gettext("xxxTESTxxx")) + + call assert_equal('xxxTESTxxx', gettext("xxxTESTxxx", "vim")) + call assert_equal('xxxTESTxxx', gettext("xxxTESTxxx", "__PACKAGE__")) + call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__")) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_gettext_cp1251.vim b/src/testdir/test_gettext_cp1251.vim new file mode 100644 index 0000000000..fe02a03fc5 --- /dev/null +++ b/src/testdir/test_gettext_cp1251.vim @@ -0,0 +1,22 @@ +source check.vim + +" Test for gettext() +func Test_gettext() + set encoding=cp1251 + call bindtextdomain("__PACKAGE__", getcwd()) + try + language ru_RU + call assert_equal(': ', gettext("ERROR: ", "__PACKAGE__")) + catch /^Vim\%((\a\+)\)\=:E197:/ + throw "Skipped: not possible to set locale to ru (missing?)" + endtry + try + language en_GB.UTF-8 + call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__")) + catch /^Vim\%((\a\+)\)\=:E197:/ + throw "Skipped: not possible to set locale to en (missing?)" + endtry + set encoding& +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_gettext_utf8.vim b/src/testdir/test_gettext_utf8.vim new file mode 100644 index 0000000000..277710e14d --- /dev/null +++ b/src/testdir/test_gettext_utf8.vim @@ -0,0 +1,22 @@ +source check.vim + +" Test for gettext() +func Test_gettext() + set encoding=utf-8 + call bindtextdomain("__PACKAGE__", getcwd()) + try + language ru_RU + call assert_equal('ОШИБКА: ', gettext("ERROR: ", "__PACKAGE__")) + catch /^Vim\%((\a\+)\)\=:E197:/ + throw "Skipped: not possible to set locale to ru (missing?)" + endtry + try + language en_GB.UTF-8 + call assert_equal('ERROR: ', gettext("ERROR: ", "__PACKAGE__")) + catch /^Vim\%((\a\+)\)\=:E197:/ + throw "Skipped: not possible to set locale to en (missing?)" + endtry + set encoding& +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index f9c298346f..5f9f2b09a9 100644 --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 509, +/**/ 508, /**/ 507, |