mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
Dev: Add synchronized block when loading lang [#330]
This commit is contained in:
@@ -33,21 +33,29 @@ public class Xoa_lang_mgr implements Gfo_invk {
|
||||
public int Len() {return hash.Count();}
|
||||
public void Add(Xol_lang_itm itm) {hash.Add(itm.Key_bry(), itm);}
|
||||
public Io_url Root_dir() {return root_dir;} private final Io_url root_dir;
|
||||
public Xol_lang_itm Get_at(int i) {return (Xol_lang_itm)hash.Get_at(i);}
|
||||
public Xol_lang_itm Get_by(byte[] key) {return (Xol_lang_itm)hash.Get_by(key);}
|
||||
public Xol_lang_itm Get_by_or_load(byte[] key) {return Get_by_or_new(key).Init_by_load_assert();}
|
||||
public Xol_lang_itm Get_by_or_en(byte[] key) { // called by Xowv_wiki for its .Lang()
|
||||
Xol_lang_itm rv = Get_by(key);
|
||||
return rv == null ? lang_en : rv;
|
||||
public Xol_lang_itm Get_by_or_null(byte[] key) {return (Xol_lang_itm)hash.Get_by(key);} // check if exists
|
||||
public Xol_lang_itm Get_by_or_load(byte[] key) { // main call
|
||||
Xol_lang_itm rv = Get_by_or_null(key);
|
||||
if (rv == null) {
|
||||
rv = Xol_lang_itm.New(this, key);
|
||||
rv.Init_by_load();
|
||||
this.Add(rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public Xol_lang_itm Get_by_or_new(byte[] key) {
|
||||
Xol_lang_itm rv = Get_by(key);
|
||||
public Xol_lang_itm Get_by_or_new(byte[] key) { // largely deprecated; should only be used for builders
|
||||
Xol_lang_itm rv = Get_by_or_null(key);
|
||||
if (rv == null) {
|
||||
rv = Xol_lang_itm.New(this, key);
|
||||
this.Add(rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public Xol_lang_itm Get_at(int i) {return (Xol_lang_itm)hash.Get_at(i);} // called by Xol_mw_lang_parser
|
||||
public Xol_lang_itm Get_by_or_en(byte[] key) { // called by Xowv_wiki to set .Lang() for DRD
|
||||
Xol_lang_itm rv = Get_by_or_null(key);
|
||||
return rv == null ? lang_en : rv;
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_get)) return Get_by_or_new(m.ReadBry("key"));
|
||||
else if (ctx.Match(k, Invk_mediawiki_converter)) return mw_converter;
|
||||
|
||||
@@ -21,6 +21,7 @@ import gplx.xowa.apps.gfs.*; import gplx.xowa.apps.fsys.*; import gplx.core.intl
|
||||
import gplx.xowa.guis.langs.*;
|
||||
public class Xol_lang_itm implements Gfo_invk {
|
||||
private boolean loaded = false;
|
||||
private final Object thread_lock = new Object();
|
||||
public Xol_lang_itm(Xoa_lang_mgr lang_mgr, byte[] key_bry) {
|
||||
this.lang_mgr = lang_mgr; this.key_bry = key_bry; this.key_str = String_.new_u8(key_bry);
|
||||
Xol_lang_stub lang_itm = Xol_lang_stub_.Get_by_key_or_null(key_bry); if (lang_itm == null) throw Err_.new_wo_type("unknown lang_key", "key", String_.new_u8(key_bry));
|
||||
@@ -32,7 +33,6 @@ public class Xol_lang_itm implements Gfo_invk {
|
||||
this.specials_mgr = new Xol_specials_mgr(this);
|
||||
this.case_mgr = Env_.Mode_testing() ? Xol_case_mgr_.A7() : Xol_case_mgr_.U8(); // NOTE: if test load ascii b/c utf8 is large; NOTE: placed here b/c tests do not call load; DATE:2014-07-04
|
||||
this.num_mgr = Xol_num_mgr_.new_by_lang_id(lang_id);
|
||||
this.lnki_trail_mgr = new Xol_lnki_trail_mgr(this);
|
||||
this.vnt_mgr = new Xol_vnt_mgr(this);
|
||||
this.grammar = Xol_grammar_.new_by_lang_id(lang_id);
|
||||
this.gender = Xol_gender_.new_by_lang_id(lang_id);
|
||||
@@ -78,7 +78,7 @@ public class Xol_lang_itm implements Gfo_invk {
|
||||
public Xol_gender Gender() {return gender;} private final Xol_gender gender;
|
||||
public Xol_plural Plural() {return plural;} private final Xol_plural plural;
|
||||
public Xol_duration_mgr Duration_mgr() {return duration_mgr;} private final Xol_duration_mgr duration_mgr;
|
||||
public Xol_lnki_trail_mgr Lnki_trail_mgr() {return lnki_trail_mgr;} private final Xol_lnki_trail_mgr lnki_trail_mgr;
|
||||
public Xol_lnki_trail_mgr Lnki_trail_mgr() {return lnki_trail_mgr;} private final Xol_lnki_trail_mgr lnki_trail_mgr = new Xol_lnki_trail_mgr();
|
||||
public Xop_lnki_arg_parser Lnki_arg_parser() {return lnki_arg_parser;} private Xop_lnki_arg_parser lnki_arg_parser = new Xop_lnki_arg_parser();
|
||||
public Xol_func_regy Func_regy() {return func_regy;} private final Xol_func_regy func_regy;
|
||||
public int Img_thumb_halign_default() {return img_thumb_halign_default;} private int img_thumb_halign_default = Xop_lnki_align_h_.Right;
|
||||
@@ -119,18 +119,20 @@ public class Xol_lang_itm implements Gfo_invk {
|
||||
;
|
||||
|
||||
private static final Hash_adp_bry fallback_dupes_regy = Hash_adp_bry.cs(); // to prevent cyclical loops during loading
|
||||
public Xol_lang_itm Init_by_load_assert() {if (!loaded) Init_by_load(); return this;}
|
||||
public boolean Init_by_load() {
|
||||
if (this.loaded) return false;
|
||||
fallback_dupes_regy.Clear();
|
||||
this.loaded = true;
|
||||
boolean lang_is_en = lang_id == Xol_lang_stub_.Id_en;
|
||||
if (!lang_is_en) Xol_lang_itm_.Lang_init(this);
|
||||
msg_mgr.Itm_by_key_or_new(Bry_.new_a7("Lang")).Atrs_set(key_bry, false, false); // set "Lang" keyword; EX: for "fr", "{{int:Lang}}" -> "fr"
|
||||
Load_lang(key_bry);
|
||||
ns_aliases.Ary_add_(Xow_ns_canonical_.Ary); // NOTE: always add English canonical as aliases to all languages
|
||||
this.Evt_lang_changed();
|
||||
return true;
|
||||
public Xol_lang_itm Init_by_load() {
|
||||
synchronized (thread_lock) { // Scribunto can create langs outside of wiki_lang; EX:dewiki and multiple scripts call isRTL for fr; ISSUE#:330; DATE:2019-02-09
|
||||
if (!loaded) {
|
||||
this.loaded = true;
|
||||
fallback_dupes_regy.Clear();
|
||||
boolean lang_is_en = lang_id == Xol_lang_stub_.Id_en;
|
||||
if (!lang_is_en) Xol_lang_itm_.Lang_init(this);
|
||||
msg_mgr.Itm_by_key_or_new(Bry_.new_a7("Lang")).Atrs_set(key_bry, false, false); // set "Lang" keyword; EX: for "fr", "{{int:Lang}}" -> "fr"
|
||||
Load_lang(key_bry);
|
||||
ns_aliases.Ary_add_(Xow_ns_canonical_.Ary); // NOTE: always add English canonical as aliases to all languages
|
||||
this.Evt_lang_changed();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
private void Exec_fallback_load(byte[] fallback_lang) {
|
||||
Fallback_bry_(fallback_lang);
|
||||
|
||||
@@ -45,7 +45,7 @@ public class Xobc_utl_make_lang_kwds implements Gfo_invk, Xol_lang_transform {
|
||||
int hash_len = hash.Count();
|
||||
for (int i = 0; i < hash_len; i++) {
|
||||
Xobcl_kwd_lang cfg_lang = (Xobcl_kwd_lang)hash.Get_at(i);
|
||||
Xol_lang_itm lang = lang_mgr.Get_by(cfg_lang.Key_bry()); if (lang == null) continue;
|
||||
Xol_lang_itm lang = lang_mgr.Get_by_or_null(cfg_lang.Key_bry()); if (lang == null) continue;
|
||||
int cfg_grp_len = cfg_lang.Grps().length;
|
||||
for (int j = 0; j < cfg_grp_len; j++) {
|
||||
Xobcl_kwd_row cfg_grp = cfg_lang.Grps()[j];
|
||||
|
||||
@@ -75,7 +75,7 @@ public class Xol_mw_lang_parser {
|
||||
String lang_key = String_.Replace(String_.Lower(String_.Mid(url.NameOnly(), 8)), "_", "-"); // 8=Messages.length; lower b/c format is MessagesEn.php (need "en")
|
||||
// if (String_.In(lang_key, "qqq", "enrtl", "bbc", "bbc-latn")) continue;
|
||||
String text = Io_mgr.Instance.LoadFilStr(url);
|
||||
Xol_lang_itm lang = lang_mgr.Get_by_or_new(Bry_.new_u8(lang_key));
|
||||
Xol_lang_itm lang = lang_mgr.Get_by_or_new(Bry_.new_u8(lang_key)); // NOTE: cannot be Get_by_or_load else will load from XO; actual definitions will be loaded from MW below
|
||||
this.Parse_core(text, lang, bfr, lang_transform);
|
||||
} catch (Exception exc) {Err_.Noop(exc); Console_adp__sys.Instance.Write_str_w_nl("failed to parse " + url.NameOnly() + Err_.Message_gplx_log(exc));}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
||||
package gplx.xowa.langs.lnki_trails; import gplx.*; import gplx.xowa.*; import gplx.xowa.langs.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Xol_lnki_trail_mgr implements Gfo_invk {
|
||||
public Xol_lnki_trail_mgr(Xol_lang_itm lang) {}
|
||||
public void Clear() {trie.Clear();}
|
||||
public int Count() {return trie.Count();}
|
||||
public Btrie_slim_mgr Trie() {return trie;} private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs();
|
||||
|
||||
@@ -17,22 +17,17 @@ package gplx.xowa.langs.lnki_trails; import gplx.*; import gplx.xowa.*; import g
|
||||
import org.junit.*;
|
||||
import gplx.xowa.langs.names.*;
|
||||
public class Xol_lnki_trail_mgr_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xol_lnki_trail_mgr_fxt fxt = new Xol_lnki_trail_mgr_fxt();
|
||||
private final Xol_lnki_trail_mgr_fxt fxt = new Xol_lnki_trail_mgr_fxt();
|
||||
@Test public void Add_bulk() {
|
||||
fxt.Test_add_bulk("äöüß", "ä", "ö", "ü", "ß");
|
||||
}
|
||||
}
|
||||
class Xol_lnki_trail_mgr_fxt {
|
||||
Xol_lang_itm lang; Xol_lnki_trail_mgr lnki_trail_mgr;
|
||||
public void Clear() {
|
||||
Xoae_app app = Xoa_app_fxt.Make__app__edit();
|
||||
lang = Xol_lang_itm.New(app.Lang_mgr(), Bry_.new_a7("fr"));
|
||||
lnki_trail_mgr = lang.Lnki_trail_mgr();
|
||||
}
|
||||
private final Xol_lnki_trail_mgr lnki_trail_mgr = new Xol_lnki_trail_mgr();
|
||||
public void Test_add_bulk(String raw, String... expd_ary) {
|
||||
lnki_trail_mgr.Add_bulk(Bry_.new_u8(raw));
|
||||
int expd_len = expd_ary.length;
|
||||
Tfds.Eq(expd_len, lang.Lnki_trail_mgr().Count());
|
||||
Tfds.Eq(expd_len, lnki_trail_mgr.Count());
|
||||
for (int i = 0; i < expd_len; i++) {
|
||||
byte[] expd_bry = Bry_.new_u8(expd_ary[i]);
|
||||
byte[] actl_bry = (byte[])lnki_trail_mgr.Trie().Match_bgn(expd_bry, 0, expd_bry.length);
|
||||
|
||||
@@ -148,7 +148,7 @@ public class Xol_msg_mgr_ {
|
||||
Xoa_lang_mgr lang_mgr = wiki.App().Lang_mgr();
|
||||
for (int i = 0; i < fallback_ary_len; i++) {
|
||||
byte[] fallback = fallback_ary[i];
|
||||
Xol_lang_itm fallback_lang = lang_mgr.Get_by(fallback);
|
||||
Xol_lang_itm fallback_lang = lang_mgr.Get_by_or_null(fallback);
|
||||
if (fallback_lang == null) continue; // NOTE: en has fallback of "false"; ignore bad fallbacks;
|
||||
rv = fallback_lang.Msg_mgr().Itm_by_key_or_null(msg_key_sub_root);
|
||||
if (rv != null) break;
|
||||
|
||||
@@ -165,8 +165,7 @@ public class Xol_lang_srl_tst {
|
||||
@Test public void Fallback_circular() { // PURPOSE: pt and pt-br cite each other as fallback in Messages*.php; DATE:2013-02-18
|
||||
Io_mgr.Instance.SaveFilStr(Xol_lang_itm_.xo_lang_fil_(fxt.App().Fsys_mgr(), "pt") , "fallback_load('pt-br');");
|
||||
Io_mgr.Instance.SaveFilStr(Xol_lang_itm_.xo_lang_fil_(fxt.App().Fsys_mgr(), "pt-br") , "fallback_load('pt');");
|
||||
Xol_lang_itm lang = Xol_lang_itm.New(fxt.App().Lang_mgr(), Bry_.new_a7("pt"));
|
||||
lang.Init_by_load();
|
||||
fxt.App().Lang_mgr().Get_by_or_load(Bry_.new_a7("pt")); // fails if test-suite gets stuck
|
||||
}
|
||||
@Test public void Num_fmt() {
|
||||
String raw = String_.Concat_lines_nl
|
||||
@@ -203,7 +202,7 @@ class Xol_lang_srl_fxt {
|
||||
app = Xoa_app_fxt.Make__app__edit();
|
||||
lang = Xol_lang_itm.New(app.Lang_mgr(), Bry_.new_a7("fr"));
|
||||
Xoa_gfs_mgr.Msg_parser_init(); // required by fallback_load
|
||||
} GfsCtx ctx = GfsCtx.new_(); Xoa_gfs_bldr bldr = new Xoa_gfs_bldr(); //Bry_bfr tmp_bfr = Bry_bfr_.Reset(255);
|
||||
} GfsCtx ctx = GfsCtx.new_(); Xoa_gfs_bldr bldr = new Xoa_gfs_bldr();
|
||||
public Xoae_app App() {return app;} private Xoae_app app;
|
||||
public Xol_lang_itm Lang() {return lang;} private Xol_lang_itm lang;
|
||||
public Xow_ns ns_(int id, String s) {return new Xow_ns(id, Xow_ns_case_.Tid__1st, Bry_.new_u8(s), false);}
|
||||
|
||||
Reference in New Issue
Block a user