From b1c52aa2b2195da3e0ada269a406dbb0600a1614 Mon Sep 17 00:00:00 2001 From: gnosygnu Date: Tue, 3 Nov 2020 07:59:21 -0500 Subject: [PATCH] ParserFunctions: Handle spaces in {{int}} keys [#817] --- .../xowa/xtns/pfuncs/langs/Pfunc_int.java | 60 +++-- .../xowa/xtns/pfuncs/langs/Pfunc_int_tst.java | 207 +++++++++--------- res/bin/any/xowa/cfg/lang/core/it.gfs | 1 + 3 files changed, 146 insertions(+), 122 deletions(-) diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/langs/Pfunc_int.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/langs/Pfunc_int.java index 7c276cf48..cd1daabe0 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/langs/Pfunc_int.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/langs/Pfunc_int.java @@ -1,6 +1,6 @@ /* XOWA: the XOWA Offline Wiki Application -Copyright (C) 2012-2017 gnosygnu@gmail.com +Copyright (C) 2012-2020 gnosygnu@gmail.com XOWA is licensed under the terms of the General Public License (GPL) Version 3, or alternatively under the terms of the Apache License Version 2.0. @@ -13,26 +13,38 @@ The terms of each license can be found in the source code repository: GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ -package gplx.xowa.xtns.pfuncs.langs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*; -import gplx.langs.phps.*; -import gplx.xowa.langs.*; import gplx.xowa.langs.kwds.*; import gplx.xowa.langs.msgs.*; -import gplx.xowa.parsers.*; import gplx.xowa.parsers.tmpls.*; -public class Pfunc_int extends Pf_func_base { - @Override public int Id() {return Xol_kwd_grp_.Id_i18n_int;} - @Override public boolean Func_require_colon_arg() {return true;} - @Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) { - byte[] msg_key = Eval_argx(ctx, src, caller, self); - Xowe_wiki wiki = ctx.Wiki(); - Xol_lang_itm page_lang = ctx.Page().Lang(); - byte[][] args_ary = Bry_.Ary_empty; - int args_len = self.Args_len(); - if (args_len > 0) { - args_ary = new byte[args_len][]; - for (int i = 0; i < args_len; i++) - args_ary[i] = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self.Args_len(), i); - } - byte[] msg_val = Xol_msg_mgr_.Get_msg_val(wiki, page_lang, msg_key, args_ary); - bfr.Add(msg_val); - } - @Override public Pf_func New(int id, byte[] name) {return new Pfunc_int().Name_(name);} -} +package gplx.xowa.xtns.pfuncs.langs; + +import gplx.Bry_; +import gplx.Bry_bfr; +import gplx.xowa.Xoa_ttl; +import gplx.xowa.Xowe_wiki; +import gplx.xowa.langs.Xol_lang_itm; +import gplx.xowa.langs.kwds.Xol_kwd_grp_; +import gplx.xowa.langs.msgs.Xol_msg_mgr_; +import gplx.xowa.parsers.Xop_ctx; +import gplx.xowa.parsers.tmpls.Xot_invk; +import gplx.xowa.xtns.pfuncs.Pf_func; +import gplx.xowa.xtns.pfuncs.Pf_func_; +import gplx.xowa.xtns.pfuncs.Pf_func_base; + +public class Pfunc_int extends Pf_func_base { + @Override public int Id() {return Xol_kwd_grp_.Id_i18n_int;} + @Override public boolean Func_require_colon_arg() {return true;} + @Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) { + byte[] msg_key = Eval_argx(ctx, src, caller, self); + msg_key = Xoa_ttl.Replace_spaces(msg_key); // 2020-11-02|ISSUE#:817|handle keys with spaces + Xowe_wiki wiki = ctx.Wiki(); + Xol_lang_itm page_lang = ctx.Page().Lang(); + byte[][] args_ary = Bry_.Ary_empty; + int args_len = self.Args_len(); + if (args_len > 0) { + args_ary = new byte[args_len][]; + for (int i = 0; i < args_len; i++) + args_ary[i] = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self.Args_len(), i); + } + byte[] msg_val = Xol_msg_mgr_.Get_msg_val(wiki, page_lang, msg_key, args_ary); + bfr.Add(msg_val); + } + @Override public Pf_func New(int id, byte[] name) {return new Pfunc_int().Name_(name);} +} diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/langs/Pfunc_int_tst.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/langs/Pfunc_int_tst.java index f8616ae69..e3f3eef76 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/langs/Pfunc_int_tst.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/langs/Pfunc_int_tst.java @@ -1,6 +1,6 @@ /* XOWA: the XOWA Offline Wiki Application -Copyright (C) 2012-2017 gnosygnu@gmail.com +Copyright (C) 2012-2020 gnosygnu@gmail.com XOWA is licensed under the terms of the General Public License (GPL) Version 3, or alternatively under the terms of the Apache License Version 2.0. @@ -13,100 +13,111 @@ The terms of each license can be found in the source code repository: GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt */ -package gplx.xowa.xtns.pfuncs.langs; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*; -import org.junit.*; import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*; -public class Pfunc_int_tst { - @Before public void init() {fxt.Reset();} private Pf_msg_mgr_fxt fxt = new Pf_msg_mgr_fxt(); - @Test public void Basic() {fxt.Test_parse_en("{{int:january}}" , "January");} - @Test public void Upper() {fxt.Test_parse_en("{{int:JANUARY}}" , "January");} - @Test public void Unknown() {fxt.Test_parse_en("{{int:unknown_msg}}" , "");} - @Test public void Fmt() {fxt.Test_parse_en("{{int:pfunc_expr_unrecognised_word|1a}}" , "Expression error: Unrecognised word \"1a\"");} - @Test public void Tmpl_txt() { - fxt.Init_msg_gfs("tst_msg", "{{#expr:1}}", false, true); - fxt.Test_parse_en("{{int:tst_msg}}", "1"); - } - @Test public void Tmpl_html_entity() { // PURPOSE: check that   is swapped out correctly for (194,160); PAGE:fr.s:Main_Page DATE:2014-08-17 - fxt.Init_msg_gfs("tst_msg", "A B", false, true); - fxt.Test_parse_en("{{int:tst_msg}}", "A B"); // NOTE:   - } - @Test public void Lang_current_defaults_to_en() { // PURPOSE: specifying same language as current returns same; ie: int:january/en -> int:january - fxt.Test_parse_en("{{int:january/en}}", "January"); - } - @Test public void Lang_specified_by_page() { - fxt.Test_parse_lang("fr", "{{int:Lang}}", "fr"); // NOTE: "Lang" msg is added by Xol_lang_itm; message_mgr.Itm_by_key_or_new(Bry_.new_a7("Lang")).Atrs_set(key_bry, false, false); - } - @Test public void Lang_missing_msg_return_en() { // PURPOSE: if key does not exist in non-english language, use English; EX: la.w:Fasciculus:HannibalFrescoCapitolinec1510.jpg; DATE:2013-09-10 - fxt.Init_msg_gfs("en_only_key", "en_only_val", false, false); - fxt.Test_parse_lang("fr", "{{int:en_only_key}}", "en_only_val"); - } - @Test public void Err_fmt_failed() { // PURPOSE: if no args passed to msg, return "$1", not "~{0}" - fxt.Init_msg_gfs("tst_msg", "a~{0}b", true, false); - fxt.Test_parse_en("{{int:tst_msg}}" , "a$1b"); - } - @Test public void Mediawiki_overrides_gfs() { - fxt.Init_msg_gfs("mw_overrides", "gfs", false, false); - fxt.Init_msg_db("mw_overrides", "mw"); - fxt.Test_parse_en("{{int:mw_overrides}}", "mw"); - } - @Test public void Convert_php() { - fxt.Init_msg_db("convert_php", "a\\\\b\\$c$1e"); - fxt.Test_parse_en("{{int:convert_php|d}}", "a\\b$cde"); - } - @Test public void Convert_php_tilde() { // PURPOSE: tildes should be escaped, else will fail inside ByteAryBfrFmtr; DATE:2013-11-11 - fxt.Init_msg_db("convert_php_tilde", "$1~u"); - fxt.Test_parse_en("{{int:convert_php_tilde|a}}", "a~u"); - } - @Test public void Unknown_val_returns_en() { // PURPOSE: if no "january" in "fr.gfs" and no "january/fr" in mw, use january in "en.gfs"; EX:none - fxt.Test_parse_lang("fr", "{{int:january/fr}}", "January"); - } - @Test public void Unknown_lang_returns_en() { // PURPOSE: unknown lang default to english; EX:none; DATE:2014-05-09 - fxt.Test_parse_en("{{int:january/unknown}}", "January"); - } - @Test public void Transclude_mw_do_not_strip_lang() { // PURPOSE: if /lang matches wiki.lang, do not strip it, else stack overflow; EX:pl.d:Wikislownik:Bar/Archiwum_6; newarticletext/pl; DATE:2014-05-13 - fxt.Init_msg_db("january/en", "January_en"); - fxt.Test_parse_en("{{MediaWiki:january/en}}", "January_en"); - } - @Test public void Transclude_gfs() { // PURPOSE: transclusion of {{MediaWiki}} pages should call {{int}} instead; EX:zh.w:Main_Page; DATE:2014-05-09 - fxt.Test_parse_en("{{MediaWiki:january/en}}", "January"); // NOTE: no page exists called "MediaWiki:january/en", but returns "{{int:january/en}}" value - } - @Test public void Create_msg_in_wiki_not_lang() { // PURPOSE: if two wikis share same language and msg is missing from one, do not mark it missing in the other; EX: home/wiki/Main_Page and en.w:Main_Page; DATE:2014-05-13 - Xowe_wiki enwiktionary = fxt.Make_wiki("en.wiktionary.org"); - fxt.Init_msg_db(enwiktionary, "wiki_only_msg", "enwiktionary_msg"); - fxt.Init_msg_gfs("wiki_only_msg", "en_gfs_msg", false, false); - fxt.Test_parse_en("{{int:wiki_only_msg}}", "en_gfs_msg"); - fxt.Test_parse_wiki(enwiktionary, "{{int:wiki_only_msg}}", "enwiktionary_msg"); - } -} -class Pf_msg_mgr_fxt { - private Xop_fxt fxt; - private Xol_lang_itm en_lang; - private Xowe_wiki en_wiki; - public void Reset() { - fxt = new Xop_fxt(); // new fxt, else transclude tests will fail - en_wiki = fxt.Wiki(); - en_lang = en_wiki.Lang(); - } - public void Init_msg_gfs(String key, String val, boolean fmt, boolean tmpl) {Init_msg_gfs(en_lang, key, val, fmt, tmpl);} - public void Init_msg_gfs(Xol_lang_itm lang, String key, String val, boolean fmt, boolean tmpl) { - Xol_msg_itm msg_itm = lang.Msg_mgr().Itm_by_key_or_new(Bry_.new_u8(key)); - msg_itm.Atrs_set(Bry_.new_u8(val), fmt, tmpl); - } - public void Init_msg_db(String ttl, String val) {Init_msg_db(en_wiki, ttl, val);} - public void Init_msg_db(Xowe_wiki wiki, String ttl, String val) { - fxt.Init_page_create(wiki, "MediaWiki:" + ttl, val); - } - public Xowe_wiki Make_wiki(String domain) {return fxt.App().Wiki_mgr().Get_by_or_make(Bry_.new_u8(domain));} - public void Test_parse_en(String raw, String expd) { - fxt.Test_parse_tmpl_str_test(raw, "{{test}}" , expd); - } - public void Test_parse_wiki(Xowe_wiki alt_wiki, String raw, String expd) { - fxt.Test_parse_tmpl_str_test(alt_wiki, raw, "{{test}}" , expd); - } - public void Test_parse_lang(String other_lang_id, String raw, String expd) { - Xol_lang_itm other_lang = fxt.App().Lang_mgr().Get_by_or_load(Bry_.new_a7(other_lang_id)); - fxt.Page().Lang_(other_lang); - fxt.Test_parse_tmpl_str_test(raw, "{{test}}", expd); - fxt.Page().Lang_(en_lang); // NOTE: must reset back to en_lang, else rest of tests will look up under fr - } -} - +package gplx.xowa.xtns.pfuncs.langs; + +import gplx.Bry_; +import gplx.xowa.Xop_fxt; +import gplx.xowa.Xowe_wiki; +import gplx.xowa.langs.Xol_lang_itm; +import gplx.xowa.langs.msgs.Xol_msg_itm; +import org.junit.Before; +import org.junit.Test; + +public class Pfunc_int_tst { + @Before public void init() {fxt.Reset();} private Pf_msg_mgr_fxt fxt = new Pf_msg_mgr_fxt(); + @Test public void Basic() {fxt.Test_parse_en("{{int:january}}" , "January");} + @Test public void Upper() {fxt.Test_parse_en("{{int:JANUARY}}" , "January");} + @Test public void Unknown() {fxt.Test_parse_en("{{int:unknown_msg}}" , "");} + @Test public void Fmt() {fxt.Test_parse_en("{{int:pfunc_expr_unrecognised_word|1a}}" , "Expression error: Unrecognised word \"1a\"");} + @Test public void Tmpl_txt() { + fxt.Init_msg_gfs("tst_msg", "{{#expr:1}}", false, true); + fxt.Test_parse_en("{{int:tst_msg}}", "1"); + } + @Test public void Tmpl_html_entity() { // PURPOSE: check that   is swapped out correctly for (194,160); PAGE:fr.s:Main_Page DATE:2014-08-17 + fxt.Init_msg_gfs("tst_msg", "A B", false, true); + fxt.Test_parse_en("{{int:tst_msg}}", "A B"); // NOTE:   + } + @Test public void Lang_current_defaults_to_en() { // PURPOSE: specifying same language as current returns same; ie: int:january/en -> int:january + fxt.Test_parse_en("{{int:january/en}}", "January"); + } + @Test public void Lang_specified_by_page() { + fxt.Test_parse_lang("fr", "{{int:Lang}}", "fr"); // NOTE: "Lang" msg is added by Xol_lang_itm; message_mgr.Itm_by_key_or_new(Bry_.new_a7("Lang")).Atrs_set(key_bry, false, false); + } + @Test public void Lang_missing_msg_return_en() { // PURPOSE: if key does not exist in non-english language, use English; EX: la.w:Fasciculus:HannibalFrescoCapitolinec1510.jpg; DATE:2013-09-10 + fxt.Init_msg_gfs("en_only_key", "en_only_val", false, false); + fxt.Test_parse_lang("fr", "{{int:en_only_key}}", "en_only_val"); + } + @Test public void Err_fmt_failed() { // PURPOSE: if no args passed to msg, return "$1", not "~{0}" + fxt.Init_msg_gfs("tst_msg", "a~{0}b", true, false); + fxt.Test_parse_en("{{int:tst_msg}}" , "a$1b"); + } + @Test public void Mediawiki_overrides_gfs() { + fxt.Init_msg_gfs("mw_overrides", "gfs", false, false); + fxt.Init_msg_db("mw_overrides", "mw"); + fxt.Test_parse_en("{{int:mw_overrides}}", "mw"); + } + @Test public void Convert_php() { + fxt.Init_msg_db("convert_php", "a\\\\b\\$c$1e"); + fxt.Test_parse_en("{{int:convert_php|d}}", "a\\b$cde"); + } + @Test public void Convert_php_tilde() { // PURPOSE: tildes should be escaped, else will fail inside ByteAryBfrFmtr; DATE:2013-11-11 + fxt.Init_msg_db("convert_php_tilde", "$1~u"); + fxt.Test_parse_en("{{int:convert_php_tilde|a}}", "a~u"); + } + @Test public void Unknown_val_returns_en() { // PURPOSE: if no "january" in "fr.gfs" and no "january/fr" in mw, use january in "en.gfs"; EX:none + fxt.Test_parse_lang("fr", "{{int:january/fr}}", "January"); + } + @Test public void Unknown_lang_returns_en() { // PURPOSE: unknown lang default to english; EX:none; DATE:2014-05-09 + fxt.Test_parse_en("{{int:january/unknown}}", "January"); + } + @Test public void Transclude_mw_do_not_strip_lang() { // PURPOSE: if /lang matches wiki.lang, do not strip it, else stack overflow; EX:pl.d:Wikislownik:Bar/Archiwum_6; newarticletext/pl; DATE:2014-05-13 + fxt.Init_msg_db("january/en", "January_en"); + fxt.Test_parse_en("{{MediaWiki:january/en}}", "January_en"); + } + @Test public void Transclude_gfs() { // PURPOSE: transclusion of {{MediaWiki}} pages should call {{int}} instead; EX:zh.w:Main_Page; DATE:2014-05-09 + fxt.Test_parse_en("{{MediaWiki:january/en}}", "January"); // NOTE: no page exists called "MediaWiki:january/en", but returns "{{int:january/en}}" value + } + @Test public void Create_msg_in_wiki_not_lang() { // PURPOSE: if two wikis share same language and msg is missing from one, do not mark it missing in the other; EX: home/wiki/Main_Page and en.w:Main_Page; DATE:2014-05-13 + Xowe_wiki enwiktionary = fxt.Make_wiki("en.wiktionary.org"); + fxt.Init_msg_db(enwiktionary, "wiki_only_msg", "enwiktionary_msg"); + fxt.Init_msg_gfs("wiki_only_msg", "en_gfs_msg", false, false); + fxt.Test_parse_en("{{int:wiki_only_msg}}", "en_gfs_msg"); + fxt.Test_parse_wiki(enwiktionary, "{{int:wiki_only_msg}}", "enwiktionary_msg"); + } + @Test public void KeyHasSpace() {// 2020-11-02|ISSUE#:817|handle keys with spaces + fxt.Init_msg_gfs("tst_msg", "{{#expr:1}}", false, true); + fxt.Test_parse_en("{{int:tst msg}}", "1"); + } +} +class Pf_msg_mgr_fxt { + private Xop_fxt fxt; + private Xol_lang_itm en_lang; + private Xowe_wiki en_wiki; + public void Reset() { + fxt = new Xop_fxt(); // new fxt, else transclude tests will fail + en_wiki = fxt.Wiki(); + en_lang = en_wiki.Lang(); + } + public void Init_msg_gfs(String key, String val, boolean fmt, boolean tmpl) {Init_msg_gfs(en_lang, key, val, fmt, tmpl);} + public void Init_msg_gfs(Xol_lang_itm lang, String key, String val, boolean fmt, boolean tmpl) { + Xol_msg_itm msg_itm = lang.Msg_mgr().Itm_by_key_or_new(Bry_.new_u8(key)); + msg_itm.Atrs_set(Bry_.new_u8(val), fmt, tmpl); + } + public void Init_msg_db(String ttl, String val) {Init_msg_db(en_wiki, ttl, val);} + public void Init_msg_db(Xowe_wiki wiki, String ttl, String val) { + fxt.Init_page_create(wiki, "MediaWiki:" + ttl, val); + } + public Xowe_wiki Make_wiki(String domain) {return fxt.App().Wiki_mgr().Get_by_or_make(Bry_.new_u8(domain));} + public void Test_parse_en(String raw, String expd) { + fxt.Test_parse_tmpl_str_test(raw, "{{test}}" , expd); + } + public void Test_parse_wiki(Xowe_wiki alt_wiki, String raw, String expd) { + fxt.Test_parse_tmpl_str_test(alt_wiki, raw, "{{test}}" , expd); + } + public void Test_parse_lang(String other_lang_id, String raw, String expd) { + Xol_lang_itm other_lang = fxt.App().Lang_mgr().Get_by_or_load(Bry_.new_a7(other_lang_id)); + fxt.Page().Lang_(other_lang); + fxt.Test_parse_tmpl_str_test(raw, "{{test}}", expd); + fxt.Page().Lang_(en_lang); // NOTE: must reset back to en_lang, else rest of tests will look up under fr + } +} diff --git a/res/bin/any/xowa/cfg/lang/core/it.gfs b/res/bin/any/xowa/cfg/lang/core/it.gfs index 7fdc55de2..e3819b39d 100644 --- a/res/bin/any/xowa/cfg/lang/core/it.gfs +++ b/res/bin/any/xowa/cfg/lang/core/it.gfs @@ -4869,6 +4869,7 @@ apihelp-wbsetdescription-param-language|Lingua della descrizione apihelp-wbsetdescription-param-value|Il valore da impostare per la descrizione apihelp-wbsetlabel-param-language|Lingua dell'etichetta apihelp-wbsetlabel-param-value|Il valore dell'etichetta +history_short|Cronologia ']:> ).lang ;