1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2024-10-27 20:34:16 +00:00

ParserFunctions: Handle spaces in {{int}} keys [#817]

This commit is contained in:
gnosygnu 2020-11-03 07:59:21 -05:00
parent 845253af79
commit b1c52aa2b2
3 changed files with 146 additions and 122 deletions

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.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.*; package gplx.xowa.xtns.pfuncs.langs;
import gplx.langs.phps.*;
import gplx.xowa.langs.*; import gplx.xowa.langs.kwds.*; import gplx.xowa.langs.msgs.*; import gplx.Bry_;
import gplx.xowa.parsers.*; import gplx.xowa.parsers.tmpls.*; import gplx.Bry_bfr;
public class Pfunc_int extends Pf_func_base { import gplx.xowa.Xoa_ttl;
@Override public int Id() {return Xol_kwd_grp_.Id_i18n_int;} import gplx.xowa.Xowe_wiki;
@Override public boolean Func_require_colon_arg() {return true;} import gplx.xowa.langs.Xol_lang_itm;
@Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) { import gplx.xowa.langs.kwds.Xol_kwd_grp_;
byte[] msg_key = Eval_argx(ctx, src, caller, self); import gplx.xowa.langs.msgs.Xol_msg_mgr_;
Xowe_wiki wiki = ctx.Wiki(); import gplx.xowa.parsers.Xop_ctx;
Xol_lang_itm page_lang = ctx.Page().Lang(); import gplx.xowa.parsers.tmpls.Xot_invk;
byte[][] args_ary = Bry_.Ary_empty; import gplx.xowa.xtns.pfuncs.Pf_func;
int args_len = self.Args_len(); import gplx.xowa.xtns.pfuncs.Pf_func_;
if (args_len > 0) { import gplx.xowa.xtns.pfuncs.Pf_func_base;
args_ary = new byte[args_len][];
for (int i = 0; i < args_len; i++) public class Pfunc_int extends Pf_func_base {
args_ary[i] = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self.Args_len(), i); @Override public int Id() {return Xol_kwd_grp_.Id_i18n_int;}
} @Override public boolean Func_require_colon_arg() {return true;}
byte[] msg_val = Xol_msg_mgr_.Get_msg_val(wiki, page_lang, msg_key, args_ary); @Override public void Func_evaluate(Bry_bfr bfr, Xop_ctx ctx, Xot_invk caller, Xot_invk self, byte[] src) {
bfr.Add(msg_val); 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
@Override public Pf_func New(int id, byte[] name) {return new Pfunc_int().Name_(name);} 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);}
}

View File

@ -1,6 +1,6 @@
/* /*
XOWA: the XOWA Offline Wiki Application 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, 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. 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 GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.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.*; package gplx.xowa.xtns.pfuncs.langs;
import org.junit.*; import gplx.xowa.langs.*; import gplx.xowa.langs.msgs.*;
public class Pfunc_int_tst { import gplx.Bry_;
@Before public void init() {fxt.Reset();} private Pf_msg_mgr_fxt fxt = new Pf_msg_mgr_fxt(); import gplx.xowa.Xop_fxt;
@Test public void Basic() {fxt.Test_parse_en("{{int:january}}" , "January");} import gplx.xowa.Xowe_wiki;
@Test public void Upper() {fxt.Test_parse_en("{{int:JANUARY}}" , "January");} import gplx.xowa.langs.Xol_lang_itm;
@Test public void Unknown() {fxt.Test_parse_en("{{int:unknown_msg}}" , "<unknown_msg>");} import gplx.xowa.langs.msgs.Xol_msg_itm;
@Test public void Fmt() {fxt.Test_parse_en("{{int:pfunc_expr_unrecognised_word|1a}}" , "Expression error: Unrecognised word \"1a\"");} import org.junit.Before;
@Test public void Tmpl_txt() { import org.junit.Test;
fxt.Init_msg_gfs("tst_msg", "{{#expr:1}}", false, true);
fxt.Test_parse_en("{{int:tst_msg}}", "1"); 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 Tmpl_html_entity() { // PURPOSE: check that &nbsp; is swapped out correctly for (194,160); PAGE:fr.s:Main_Page DATE:2014-08-17 @Test public void Basic() {fxt.Test_parse_en("{{int:january}}" , "January");}
fxt.Init_msg_gfs("tst_msg", "A&nbsp;B", false, true); @Test public void Upper() {fxt.Test_parse_en("{{int:JANUARY}}" , "January");}
fxt.Test_parse_en("{{int:tst_msg}}", "A B"); // NOTE: &nbsp; @Test public void Unknown() {fxt.Test_parse_en("{{int:unknown_msg}}" , "<unknown_msg>");}
} @Test public void Fmt() {fxt.Test_parse_en("{{int:pfunc_expr_unrecognised_word|1a}}" , "Expression error: Unrecognised word \"1a\"");}
@Test public void Lang_current_defaults_to_en() { // PURPOSE: specifying same language as current returns same; ie: int:january/en -> int:january @Test public void Tmpl_txt() {
fxt.Test_parse_en("{{int:january/en}}", "January"); fxt.Init_msg_gfs("tst_msg", "{{#expr:1}}", false, true);
} fxt.Test_parse_en("{{int:tst_msg}}", "1");
@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 Tmpl_html_entity() { // PURPOSE: check that &nbsp; is swapped out correctly for (194,160); PAGE:fr.s:Main_Page DATE:2014-08-17
} fxt.Init_msg_gfs("tst_msg", "A&nbsp;B", false, true);
@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.Test_parse_en("{{int:tst_msg}}", "A B"); // NOTE: &nbsp;
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 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 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); @Test public void Lang_specified_by_page() {
fxt.Test_parse_en("{{int:tst_msg}}" , "a$1b"); 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 Mediawiki_overrides_gfs() { @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("mw_overrides", "gfs", false, false); fxt.Init_msg_gfs("en_only_key", "en_only_val", false, false);
fxt.Init_msg_db("mw_overrides", "mw"); fxt.Test_parse_lang("fr", "{{int:en_only_key}}", "en_only_val");
fxt.Test_parse_en("{{int:mw_overrides}}", "mw"); }
} @Test public void Err_fmt_failed() { // PURPOSE: if no args passed to msg, return "$1", not "~{0}"
@Test public void Convert_php() { fxt.Init_msg_gfs("tst_msg", "a~{0}b", true, false);
fxt.Init_msg_db("convert_php", "a\\\\b\\$c$1e"); fxt.Test_parse_en("{{int:tst_msg}}" , "a$1b");
fxt.Test_parse_en("{{int:convert_php|d}}", "a\\b$cde"); }
} @Test public void Mediawiki_overrides_gfs() {
@Test public void Convert_php_tilde() { // PURPOSE: tildes should be escaped, else will fail inside ByteAryBfrFmtr; DATE:2013-11-11 fxt.Init_msg_gfs("mw_overrides", "gfs", false, false);
fxt.Init_msg_db("convert_php_tilde", "$1~u"); fxt.Init_msg_db("mw_overrides", "mw");
fxt.Test_parse_en("{{int:convert_php_tilde|a}}", "a~u"); fxt.Test_parse_en("{{int:mw_overrides}}", "mw");
} }
@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 @Test public void Convert_php() {
fxt.Test_parse_lang("fr", "{{int:january/fr}}", "January"); fxt.Init_msg_db("convert_php", "a\\\\b\\$c$1e");
} fxt.Test_parse_en("{{int:convert_php|d}}", "a\\b$cde");
@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 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");
@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.Test_parse_en("{{int:convert_php_tilde|a}}", "a~u");
fxt.Init_msg_db("january/en", "January_en"); }
fxt.Test_parse_en("{{MediaWiki:january/en}}", "January_en"); @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 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 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 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"); @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(enwiktionary, "wiki_only_msg", "enwiktionary_msg"); fxt.Init_msg_db("january/en", "January_en");
fxt.Init_msg_gfs("wiki_only_msg", "en_gfs_msg", false, false); fxt.Test_parse_en("{{MediaWiki:january/en}}", "January_en");
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 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
} }
class Pf_msg_mgr_fxt { @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
private Xop_fxt fxt; Xowe_wiki enwiktionary = fxt.Make_wiki("en.wiktionary.org");
private Xol_lang_itm en_lang; fxt.Init_msg_db(enwiktionary, "wiki_only_msg", "enwiktionary_msg");
private Xowe_wiki en_wiki; fxt.Init_msg_gfs("wiki_only_msg", "en_gfs_msg", false, false);
public void Reset() { fxt.Test_parse_en("{{int:wiki_only_msg}}", "en_gfs_msg");
fxt = new Xop_fxt(); // new fxt, else transclude tests will fail fxt.Test_parse_wiki(enwiktionary, "{{int:wiki_only_msg}}", "enwiktionary_msg");
en_wiki = fxt.Wiki(); }
en_lang = en_wiki.Lang(); @Test public void KeyHasSpace() {// 2020-11-02|ISSUE#:817|handle keys with spaces
} fxt.Init_msg_gfs("tst_msg", "{{#expr:1}}", false, true);
public void Init_msg_gfs(String key, String val, boolean fmt, boolean tmpl) {Init_msg_gfs(en_lang, key, val, fmt, tmpl);} fxt.Test_parse_en("{{int:tst msg}}", "1");
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); class Pf_msg_mgr_fxt {
} private Xop_fxt fxt;
public void Init_msg_db(String ttl, String val) {Init_msg_db(en_wiki, ttl, val);} private Xol_lang_itm en_lang;
public void Init_msg_db(Xowe_wiki wiki, String ttl, String val) { private Xowe_wiki en_wiki;
fxt.Init_page_create(wiki, "MediaWiki:" + ttl, val); public void Reset() {
} fxt = new Xop_fxt(); // new fxt, else transclude tests will fail
public Xowe_wiki Make_wiki(String domain) {return fxt.App().Wiki_mgr().Get_by_or_make(Bry_.new_u8(domain));} en_wiki = fxt.Wiki();
public void Test_parse_en(String raw, String expd) { en_lang = en_wiki.Lang();
fxt.Test_parse_tmpl_str_test(raw, "{{test}}" , expd); }
} public void Init_msg_gfs(String key, String val, boolean fmt, boolean tmpl) {Init_msg_gfs(en_lang, key, val, fmt, tmpl);}
public void Test_parse_wiki(Xowe_wiki alt_wiki, String raw, String expd) { public void Init_msg_gfs(Xol_lang_itm lang, String key, String val, boolean fmt, boolean tmpl) {
fxt.Test_parse_tmpl_str_test(alt_wiki, raw, "{{test}}" , expd); 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 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)); public void Init_msg_db(String ttl, String val) {Init_msg_db(en_wiki, ttl, val);}
fxt.Page().Lang_(other_lang); public void Init_msg_db(Xowe_wiki wiki, String ttl, String val) {
fxt.Test_parse_tmpl_str_test(raw, "{{test}}", expd); fxt.Init_page_create(wiki, "MediaWiki:" + ttl, val);
fxt.Page().Lang_(en_lang); // NOTE: must reset back to en_lang, else rest of tests will look up under fr }
} 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
}
}

View File

@ -4869,6 +4869,7 @@ apihelp-wbsetdescription-param-language|Lingua della descrizione
apihelp-wbsetdescription-param-value|Il valore da impostare per la descrizione apihelp-wbsetdescription-param-value|Il valore da impostare per la descrizione
apihelp-wbsetlabel-param-language|Lingua dell'etichetta apihelp-wbsetlabel-param-language|Lingua dell'etichetta
apihelp-wbsetlabel-param-value|Il valore dell'etichetta apihelp-wbsetlabel-param-value|Il valore dell'etichetta
history_short|Cronologia
']:> ']:>
).lang ).lang
; ;