@adminforth/i18n 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom/LanguageInUserMenu.vue +74 -0
- package/custom/LanguageUnderLogin.vue +72 -0
- package/custom/langCommon.ts +88 -0
- package/custom/node_modules/.package-lock.json +16 -0
- package/custom/node_modules/flag-icon-css/.github/dependabot.yml +8 -0
- package/custom/node_modules/flag-icon-css/.github/workflows/test.yml +17 -0
- package/custom/node_modules/flag-icon-css/.prettierignore +3 -0
- package/custom/node_modules/flag-icon-css/.prettierrc.json +20 -0
- package/custom/node_modules/flag-icon-css/404.html +6 -0
- package/custom/node_modules/flag-icon-css/CNAME +1 -0
- package/custom/node_modules/flag-icon-css/LICENSE +21 -0
- package/custom/node_modules/flag-icon-css/README.md +54 -0
- package/custom/node_modules/flag-icon-css/assets/docs.css +58 -0
- package/custom/node_modules/flag-icon-css/assets/docs.js +64 -0
- package/custom/node_modules/flag-icon-css/country.json +1857 -0
- package/custom/node_modules/flag-icon-css/css/flag-icons.css +1610 -0
- package/custom/node_modules/flag-icon-css/css/flag-icons.min.css +1 -0
- package/custom/node_modules/flag-icon-css/favicon.ico +0 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ac.svg +81 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ad.svg +148 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ae.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/af.svg +81 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ag.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ai.svg +763 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/al.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/am.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ao.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/aq.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ar.svg +31 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/as.svg +33 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/at.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/au.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/aw.svg +186 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ax.svg +18 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/az.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ba.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bb.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bd.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/be.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bf.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bg.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bh.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bi.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bj.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bl.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bm.svg +99 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bn.svg +36 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bo.svg +678 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bq.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/br.svg +45 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bs.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bt.svg +89 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bv.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bw.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/by.svg +22 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/bz.svg +145 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ca.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cc.svg +19 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cd.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cf.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cg.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ch.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ci.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ck.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cl.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cm.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cn.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/co.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cp.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cr.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cu.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cv.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cw.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cx.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cy.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/cz.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/de.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/dg.svg +140 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/dj.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/dk.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/dm.svg +152 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/do.svg +6745 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/dz.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ea.svg +547 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ec.svg +138 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ee.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/eg.svg +38 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/eh.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/er.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/es-ct.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/es-ga.svg +189 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/es.svg +547 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/et.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/eu.svg +28 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/fi.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/fj.svg +125 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/fk.svg +93 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/fm.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/fo.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/fr.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ga.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gb-eng.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gb-nir.svg +131 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gb-sct.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gb-wls.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gb.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gd.svg +27 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ge.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gf.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gg.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gh.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gi.svg +32 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gl.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gm.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gn.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gp.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gq.svg +23 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gr.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gs.svg +245 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gt.svg +204 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gu.svg +39 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gw.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/gy.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/hk.svg +30 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/hm.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/hn.svg +18 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/hr.svg +56 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ht.svg +116 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/hu.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ic.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/id.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ie.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/il.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/im.svg +36 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/in.svg +25 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/io.svg +140 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/iq.svg +10 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ir.svg +219 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/is.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/it.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/je.svg +47 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/jm.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/jo.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/jp.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ke.svg +23 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/kg.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/kh.svg +61 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ki.svg +36 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/km.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/kn.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/kp.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/kr.svg +24 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/kw.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ky.svg +225 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/kz.svg +23 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/la.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/lb.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/lc.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/li.svg +43 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/lk.svg +22 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/lr.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ls.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/lt.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/lu.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/lv.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ly.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ma.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mc.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/md.svg +71 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/me.svg +118 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mf.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mg.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mh.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mk.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ml.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mm.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mn.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mo.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mp.svg +86 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mq.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mr.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ms.svg +70 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mt.svg +50 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mu.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mv.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mw.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mx.svg +378 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/my.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/mz.svg +21 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/na.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/nc.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ne.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/nf.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ng.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ni.svg +129 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/nl.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/no.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/np.svg +19 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/nr.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/nu.svg +26 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/nz.svg +42 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/om.svg +115 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pa.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pe.svg +244 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pf.svg +18 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pg.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ph.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pk.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pl.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pm.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pn.svg +100 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pr.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ps.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pt.svg +57 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/pw.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/py.svg +156 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/qa.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/re.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ro.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/rs.svg +296 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ru.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/rw.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sa.svg +26 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sb.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sc.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sd.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/se.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sg.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sh.svg +81 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/si.svg +18 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sj.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sk.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sl.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sm.svg +89 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sn.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/so.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sr.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ss.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/st.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sv.svg +594 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sx.svg +56 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sy.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/sz.svg +45 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ta.svg +81 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tc.svg +52 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/td.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tf.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tg.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/th.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tj.svg +26 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tk.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tl.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tm.svg +203 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tn.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/to.svg +10 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tr.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tt.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tv.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tw.svg +32 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/tz.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ua.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ug.svg +30 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/um.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/un.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/us.svg +10 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/uy.svg +28 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/uz.svg +30 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/va.svg +479 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/vc.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ve.svg +26 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/vg.svg +127 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/vi.svg +28 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/vn.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/vu.svg +18 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/wf.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ws.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/xk.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/xx.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/ye.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/yt.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/za.svg +17 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/zm.svg +27 -0
- package/custom/node_modules/flag-icon-css/flags/1x1/zw.svg +21 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ac.svg +76 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ad.svg +150 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ae.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/af.svg +81 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ag.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ai.svg +763 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/al.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/am.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ao.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/aq.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ar.svg +31 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/as.svg +33 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/at.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/au.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/aw.svg +186 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ax.svg +18 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/az.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ba.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bb.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bd.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/be.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bf.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bg.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bh.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bi.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bj.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bl.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bm.svg +99 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bn.svg +36 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bo.svg +676 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bq.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/br.svg +45 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bs.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bt.svg +89 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bv.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bw.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/by.svg +20 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/bz.svg +145 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ca.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cc.svg +19 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cd.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cf.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cg.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ch.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ci.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ck.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cl.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cm.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cn.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/co.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cp.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cr.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cu.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cv.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cw.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cx.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cy.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/cz.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/de.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/dg.svg +138 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/dj.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/dk.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/dm.svg +152 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/do.svg +6745 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/dz.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ea.svg +544 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ec.svg +138 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ee.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/eg.svg +38 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/eh.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/er.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/es-ct.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/es-ga.svg +189 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/es.svg +544 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/et.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/eu.svg +28 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/fi.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/fj.svg +122 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/fk.svg +90 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/fm.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/fo.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/fr.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ga.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gb-eng.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gb-nir.svg +132 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gb-sct.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gb-wls.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gb.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gd.svg +27 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ge.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gf.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gg.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gh.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gi.svg +32 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gl.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gm.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gn.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gp.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gq.svg +23 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gr.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gs.svg +242 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gt.svg +204 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gu.svg +39 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gw.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/gy.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/hk.svg +30 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/hm.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/hn.svg +18 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/hr.svg +58 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ht.svg +116 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/hu.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ic.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/id.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ie.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/il.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/im.svg +36 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/in.svg +25 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/io.svg +138 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/iq.svg +10 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ir.svg +219 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/is.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/it.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/je.svg +47 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/jm.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/jo.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/jp.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ke.svg +23 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/kg.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/kh.svg +61 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ki.svg +36 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/km.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/kn.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/kp.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/kr.svg +24 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/kw.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ky.svg +225 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/kz.svg +23 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/la.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/lb.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/lc.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/li.svg +43 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/lk.svg +22 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/lr.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ls.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/lt.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/lu.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/lv.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ly.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ma.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mc.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/md.svg +70 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/me.svg +116 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mf.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mg.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mh.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mk.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ml.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mm.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mn.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mo.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mp.svg +86 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mq.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mr.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ms.svg +78 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mt.svg +49 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mu.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mv.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mw.svg +10 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mx.svg +382 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/my.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/mz.svg +21 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/na.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/nc.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ne.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/nf.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ng.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ni.svg +129 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/nl.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/no.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/np.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/nr.svg +12 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/nu.svg +26 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/nz.svg +42 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/om.svg +115 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pa.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pe.svg +244 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pf.svg +19 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pg.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ph.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pk.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pl.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pm.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pn.svg +97 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pr.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ps.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pt.svg +57 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/pw.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/py.svg +157 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/qa.svg +4 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/re.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ro.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/rs.svg +292 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ru.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/rw.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sa.svg +26 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sb.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sc.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sd.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/se.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sg.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sh.svg +76 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/si.svg +18 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sj.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sk.svg +9 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sl.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sm.svg +91 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sn.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/so.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sr.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ss.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/st.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sv.svg +594 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sx.svg +56 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sy.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/sz.svg +45 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ta.svg +76 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tc.svg +52 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/td.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tf.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tg.svg +14 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/th.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tj.svg +22 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tk.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tl.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tm.svg +206 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tn.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/to.svg +10 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tr.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tt.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tv.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tw.svg +34 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/tz.svg +13 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ua.svg +6 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ug.svg +30 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/um.svg +15 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/un.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/us.svg +10 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/uy.svg +28 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/uz.svg +30 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/va.svg +479 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/vc.svg +8 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ve.svg +26 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/vg.svg +127 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/vi.svg +28 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/vn.svg +11 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/vu.svg +18 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/wf.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ws.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/xk.svg +16 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/xx.svg +5 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/ye.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/yt.svg +7 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/za.svg +17 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/zm.svg +27 -0
- package/custom/node_modules/flag-icon-css/flags/4x3/zw.svg +21 -0
- package/custom/node_modules/flag-icon-css/flags.py +37 -0
- package/custom/node_modules/flag-icon-css/index.html +68 -0
- package/custom/node_modules/flag-icon-css/less/flag-icons-base.less +28 -0
- package/custom/node_modules/flag-icon-css/less/flag-icons-list.less +249 -0
- package/custom/node_modules/flag-icon-css/less/flag-icons-more.less +16 -0
- package/custom/node_modules/flag-icon-css/less/flag-icons.less +4 -0
- package/custom/node_modules/flag-icon-css/less/variables.less +3 -0
- package/custom/node_modules/flag-icon-css/package.json +28 -0
- package/custom/node_modules/flag-icon-css/sass/_flag-icons-base.scss +28 -0
- package/custom/node_modules/flag-icon-css/sass/_flag-icons-list.scss +273 -0
- package/custom/node_modules/flag-icon-css/sass/_variables.scss +3 -0
- package/custom/node_modules/flag-icon-css/sass/flag-icons.scss +3 -0
- package/custom/node_modules/flag-icon-css/svgo.config.js +16 -0
- package/custom/package-lock.json +24 -0
- package/custom/package.json +15 -0
- package/custom/tsconfig.json +19 -0
- package/dist/custom/LanguageInUserMenu.vue +74 -0
- package/dist/custom/LanguageUnderLogin.vue +72 -0
- package/dist/custom/ResetPassword.vue +295 -0
- package/dist/custom/ResetPasswordUnderLogin.vue +13 -0
- package/dist/custom/SignupPage.vue +278 -0
- package/dist/custom/SignupUnderLogin.vue +13 -0
- package/dist/custom/langCommon.ts +88 -0
- package/dist/custom/package-lock.json +24 -0
- package/dist/custom/package.json +15 -0
- package/dist/custom/tsconfig.json +19 -0
- package/dist/index.js +511 -0
- package/dist/types.js +1 -0
- package/index.ts +603 -0
- package/package.json +24 -0
- package/tsconfig.json +12 -0
- package/types.ts +39 -0
package/index.ts
ADDED
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
import AdminForth, { AdminForthPlugin, Filters, suggestIfTypo, AdminForthDataTypes } from "adminforth";
|
|
2
|
+
import type { IAdminForth, IHttpServer, AdminForthComponentDeclaration, AdminForthResourceColumn, AdminForthResource, BeforeLoginConfirmationFunction } from "adminforth";
|
|
3
|
+
import type { PluginOptions } from './types.js';
|
|
4
|
+
import iso6391, { LanguageCode } from 'iso-639-1';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import chokidar from 'chokidar';
|
|
8
|
+
|
|
9
|
+
interface ICachingAdapter {
|
|
10
|
+
get(key: string): Promise<any>;
|
|
11
|
+
set(key: string, value: any): Promise<void>;
|
|
12
|
+
clear(key: string): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class CachingAdapterMemory implements ICachingAdapter {
|
|
16
|
+
cache: Record<string, any> = {};
|
|
17
|
+
async get(key: string) {
|
|
18
|
+
return this.cache[key];
|
|
19
|
+
}
|
|
20
|
+
async set(key: string, value: any) {
|
|
21
|
+
this.cache[key] = value;
|
|
22
|
+
}
|
|
23
|
+
async clear(key: string) {
|
|
24
|
+
if (this.cache[key]) {
|
|
25
|
+
delete this.cache[key];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class AiTranslateError extends Error {
|
|
31
|
+
constructor(message: string) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = 'AiTranslateError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export default class I18N extends AdminForthPlugin {
|
|
37
|
+
options: PluginOptions;
|
|
38
|
+
emailField: AdminForthResourceColumn;
|
|
39
|
+
passwordField: AdminForthResourceColumn;
|
|
40
|
+
authResource: AdminForthResource;
|
|
41
|
+
emailConfirmedField?: AdminForthResourceColumn;
|
|
42
|
+
trFieldNames: Partial<Record<LanguageCode, string>>;
|
|
43
|
+
enFieldName: string;
|
|
44
|
+
cache: ICachingAdapter;
|
|
45
|
+
primaryKeyFieldName: string;
|
|
46
|
+
|
|
47
|
+
adminforth: IAdminForth;
|
|
48
|
+
|
|
49
|
+
// sorted by name list of all supported languages, without en e.g. 'al|ro|uk'
|
|
50
|
+
fullCompleatedFieldValue: string;
|
|
51
|
+
|
|
52
|
+
constructor(options: PluginOptions) {
|
|
53
|
+
super(options, import.meta.url);
|
|
54
|
+
this.options = options;
|
|
55
|
+
this.cache = new CachingAdapterMemory();
|
|
56
|
+
this.trFieldNames = {};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async computeCompletedFieldValue(record: any) {
|
|
60
|
+
return this.options.supportedLanguages.reduce((acc: string, lang: LanguageCode): string => {
|
|
61
|
+
if (lang === 'en') {
|
|
62
|
+
return acc;
|
|
63
|
+
}
|
|
64
|
+
if (record[this.trFieldNames[lang]]) {
|
|
65
|
+
if (acc !== '') {
|
|
66
|
+
acc += '|';
|
|
67
|
+
}
|
|
68
|
+
acc += (lang as string);
|
|
69
|
+
}
|
|
70
|
+
return acc;
|
|
71
|
+
}, '');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
|
|
75
|
+
super.modifyResourceConfig(adminforth, resourceConfig);
|
|
76
|
+
|
|
77
|
+
// check each supported language is valid ISO 639-1 code
|
|
78
|
+
this.options.supportedLanguages.forEach((lang) => {
|
|
79
|
+
if (!iso6391.validate(lang)) {
|
|
80
|
+
throw new Error(`Invalid language code ${lang}, please define valid ISO 639-1 language code (2 lowercase letters)`);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
// find primary key field
|
|
87
|
+
this.primaryKeyFieldName = resourceConfig.columns.find(c => c.primaryKey)?.name;
|
|
88
|
+
|
|
89
|
+
if (!this.primaryKeyFieldName) {
|
|
90
|
+
throw new Error(`Primary key field not found in resource ${resourceConfig.resourceId}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
// parse trFieldNames
|
|
95
|
+
for (const lang of this.options.supportedLanguages) {
|
|
96
|
+
if (lang === 'en') {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (this.options.translationFieldNames?.[lang]) {
|
|
100
|
+
this.trFieldNames[lang] = this.options.translationFieldNames[lang];
|
|
101
|
+
} else {
|
|
102
|
+
this.trFieldNames[lang] = lang + '_string';
|
|
103
|
+
}
|
|
104
|
+
// find column by name
|
|
105
|
+
const column = resourceConfig.columns.find(c => c.name === this.trFieldNames[lang]);
|
|
106
|
+
if (!column) {
|
|
107
|
+
throw new Error(`Field ${this.trFieldNames[lang]} not found for storing translation for language ${lang}
|
|
108
|
+
in resource ${resourceConfig.resourceId}, consider adding it to columns or change trFieldNames option to remap it to existing column`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
this.enFieldName = this.trFieldNames['en'] || 'en_string';
|
|
113
|
+
|
|
114
|
+
this.fullCompleatedFieldValue = this.options.supportedLanguages.reduce((acc: string, lang: LanguageCode) => {
|
|
115
|
+
if (lang === 'en') {
|
|
116
|
+
return acc;
|
|
117
|
+
}
|
|
118
|
+
if (acc !== '') {
|
|
119
|
+
acc += '|';
|
|
120
|
+
}
|
|
121
|
+
acc += lang as string;
|
|
122
|
+
return acc;
|
|
123
|
+
}, '');
|
|
124
|
+
|
|
125
|
+
// if not enFieldName column is not found, throw error
|
|
126
|
+
const enColumn = resourceConfig.columns.find(c => c.name === this.enFieldName);
|
|
127
|
+
if (!enColumn) {
|
|
128
|
+
throw new Error(`Field ${this.enFieldName} not found column to store english original string in resource ${resourceConfig.resourceId}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// if sourceFieldName defined, check it exists
|
|
132
|
+
if (this.options.sourceFieldName) {
|
|
133
|
+
if (!resourceConfig.columns.find(c => c.name === this.options.sourceFieldName)) {
|
|
134
|
+
throw new Error(`Field ${this.options.sourceFieldName} not found in resource ${resourceConfig.resourceId}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// if completedFieldName defined, check it exists and should be string
|
|
139
|
+
if (this.options.completedFieldName) {
|
|
140
|
+
const column = resourceConfig.columns.find(c => c.name === this.options.completedFieldName);
|
|
141
|
+
if (!column) {
|
|
142
|
+
const similar = suggestIfTypo(resourceConfig.columns.map((col) => col.name), this.options.completedFieldName);
|
|
143
|
+
throw new Error(`Field ${this.options.completedFieldName} not found in resource ${resourceConfig.resourceId}${similar ? `Did you mean '${similar}'?` : ''}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// if showIn is not defined, add it as empty
|
|
147
|
+
column.showIn = [];
|
|
148
|
+
|
|
149
|
+
// add virtual field for incomplete
|
|
150
|
+
resourceConfig.columns.push({
|
|
151
|
+
name: 'fully_translated',
|
|
152
|
+
label: 'Fully translated',
|
|
153
|
+
virtual: true,
|
|
154
|
+
showIn: ['list', 'show', 'filter'],
|
|
155
|
+
type: AdminForthDataTypes.BOOLEAN,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const compMeta = {
|
|
160
|
+
brandSlug: adminforth.config.customization.brandNameSlug,
|
|
161
|
+
pluginInstanceId: this.pluginInstanceId,
|
|
162
|
+
supportedLanguages: this.options.supportedLanguages.map(lang => (
|
|
163
|
+
{
|
|
164
|
+
code: lang,
|
|
165
|
+
// lang name on on language native name
|
|
166
|
+
name: iso6391.getNativeName(lang),
|
|
167
|
+
}
|
|
168
|
+
))
|
|
169
|
+
};
|
|
170
|
+
// add underLogin component
|
|
171
|
+
(adminforth.config.customization.loginPageInjections.underInputs).push({
|
|
172
|
+
file: this.componentPath('LanguageUnderLogin.vue'),
|
|
173
|
+
meta: compMeta
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
(adminforth.config.customization.globalInjections.userMenu).push({
|
|
177
|
+
file: this.componentPath('LanguageInUserMenu.vue'),
|
|
178
|
+
meta: compMeta
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// disable create allowedActions for translations
|
|
182
|
+
resourceConfig.options.allowedActions.create = false;
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
// add hook on edit of any translation
|
|
186
|
+
resourceConfig.hooks.edit.afterSave.push(async ({ record, oldRecord }: { record: any, oldRecord?: any }): Promise<{ ok: boolean, error?: string }> => {
|
|
187
|
+
if (oldRecord) {
|
|
188
|
+
// find lang which changed
|
|
189
|
+
let langsChanged: LanguageCode[] = [];
|
|
190
|
+
for (const lang of this.options.supportedLanguages) {
|
|
191
|
+
if (lang === 'en') {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (record[this.trFieldNames[lang]] !== oldRecord[this.trFieldNames[lang]]) {
|
|
195
|
+
langsChanged.push(lang);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// clear frontend cache for all langsChanged
|
|
200
|
+
for (const lang of langsChanged) {
|
|
201
|
+
this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
}
|
|
206
|
+
// clear frontend cache for all lan
|
|
207
|
+
|
|
208
|
+
return { ok: true };
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
if (this.options.completedFieldName) {
|
|
212
|
+
// on show and list add a list hook which will add incomplete field to record if translation is missing for at least one language
|
|
213
|
+
const addIncompleteField = (record: any) => {
|
|
214
|
+
// form list of all langs, sorted by alphabet, without en, to get 'al|ro|uk'
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
record.fully_translated = this.fullCompleatedFieldValue === record[this.options.completedFieldName];
|
|
218
|
+
}
|
|
219
|
+
resourceConfig.hooks.list.afterDatasourceResponse.push(async ({ response }: { response: any[] }): Promise<{ ok: boolean, error?: string }> => {
|
|
220
|
+
response.forEach(addIncompleteField);
|
|
221
|
+
return { ok: true }
|
|
222
|
+
});
|
|
223
|
+
resourceConfig.hooks.show.afterDatasourceResponse.push(async ({ response }: { response: any }): Promise<{ ok: boolean, error?: string }> => {
|
|
224
|
+
addIncompleteField(response.length && response[0]);
|
|
225
|
+
return { ok: true }
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// also add edit hook beforeSave to update completedFieldName
|
|
229
|
+
resourceConfig.hooks.edit.beforeSave.push(async ({ record, oldRecord }: { record: any, oldRecord: any }): Promise<{ ok: boolean, error?: string }> => {
|
|
230
|
+
const futureRecord = { ...oldRecord, ...record };
|
|
231
|
+
|
|
232
|
+
const futureCompletedFieldValue = await this.computeCompletedFieldValue(futureRecord);
|
|
233
|
+
|
|
234
|
+
record[this.options.completedFieldName] = futureCompletedFieldValue;
|
|
235
|
+
return { ok: true };
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// add list hook to support filtering by fully_translated virtual field
|
|
239
|
+
resourceConfig.hooks.list.beforeDatasourceRequest.push(async ({ query }: { query: any }): Promise<{ ok: boolean, error?: string }> => {
|
|
240
|
+
if (!query.filters || query.filters.length === 0) {
|
|
241
|
+
query.filters = [];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// get fully_translated field from filter if it is there
|
|
245
|
+
const fullyTranslatedFilter = query.filters.find((f: any) => f.field === 'fully_translated');
|
|
246
|
+
if (fullyTranslatedFilter) {
|
|
247
|
+
// remove it from filters because it is virtual field
|
|
248
|
+
query.filters = query.filters.filter((f: any) => f.field !== 'fully_translated');
|
|
249
|
+
if (fullyTranslatedFilter.value[0]) {
|
|
250
|
+
query.filters.push({
|
|
251
|
+
field: this.options.completedFieldName,
|
|
252
|
+
value: this.fullCompleatedFieldValue,
|
|
253
|
+
operator: 'eq',
|
|
254
|
+
});
|
|
255
|
+
} else {
|
|
256
|
+
query.filters.push({
|
|
257
|
+
field: this.options.completedFieldName,
|
|
258
|
+
value: this.fullCompleatedFieldValue,
|
|
259
|
+
operator: 'ne',
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return { ok: true };
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// add bulk action
|
|
269
|
+
if (!resourceConfig.options.bulkActions) {
|
|
270
|
+
resourceConfig.options.bulkActions = [];
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (this.options.completeAdapter) {
|
|
274
|
+
resourceConfig.options.bulkActions.push(
|
|
275
|
+
{
|
|
276
|
+
label: 'Translate selected',
|
|
277
|
+
icon: 'flowbite:language-outline',
|
|
278
|
+
// if optional `confirm` is provided, user will be asked to confirm action
|
|
279
|
+
confirm: 'Are you sure you want to translate selected items?',
|
|
280
|
+
state: 'selected',
|
|
281
|
+
action: async ({ selectedIds, tr }) => {
|
|
282
|
+
try {
|
|
283
|
+
await this.bulkTranslate({ selectedIds });
|
|
284
|
+
} catch (e) {
|
|
285
|
+
if (e instanceof AiTranslateError) {
|
|
286
|
+
return { ok: false, error: e.message };
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
ok: true, error: undefined,
|
|
291
|
+
successMessage: await tr(`Translated {count} items`, 'frontend', {count: selectedIds.length}),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
);
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async bulkTranslate({ selectedIds }: { selectedIds: string[] }) {
|
|
300
|
+
|
|
301
|
+
const needToTranslateByLang : Partial<
|
|
302
|
+
Record<
|
|
303
|
+
LanguageCode,
|
|
304
|
+
{
|
|
305
|
+
en_string: string;
|
|
306
|
+
category: string;
|
|
307
|
+
}[]
|
|
308
|
+
>
|
|
309
|
+
> = {};
|
|
310
|
+
|
|
311
|
+
const translations = await this.adminforth.resource(this.resourceConfig.resourceId).list(Filters.IN(this.primaryKeyFieldName, selectedIds));
|
|
312
|
+
|
|
313
|
+
for (const lang of this.options.supportedLanguages) {
|
|
314
|
+
if (lang === 'en') {
|
|
315
|
+
// all strings are in English, no need to translate
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
for (const translation of translations) {
|
|
319
|
+
if (!translation[this.trFieldNames[lang]]) {
|
|
320
|
+
if (!needToTranslateByLang[lang]) {
|
|
321
|
+
needToTranslateByLang[lang] = [];
|
|
322
|
+
}
|
|
323
|
+
needToTranslateByLang[lang].push({
|
|
324
|
+
'en_string': translation[this.enFieldName],
|
|
325
|
+
category: translation[this.options.categoryFieldName],
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const maxKeysInOneReq = 10;
|
|
332
|
+
|
|
333
|
+
const updateStrings: Record<string, {
|
|
334
|
+
updates: any, category: string, strId: string
|
|
335
|
+
}> = {};
|
|
336
|
+
|
|
337
|
+
const translateToLang = async (langIsoCode: LanguageCode, strings: { en_string: string, category: string }[]) => {
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
if (strings.length > maxKeysInOneReq) {
|
|
341
|
+
for (let i = 0; i < strings.length; i += maxKeysInOneReq) {
|
|
342
|
+
const slicedStrings = strings.slice(i, i + maxKeysInOneReq);
|
|
343
|
+
await translateToLang(langIsoCode, slicedStrings);
|
|
344
|
+
}
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
const lang = langIsoCode;
|
|
348
|
+
const prompt = `
|
|
349
|
+
I need to translate strings in JSON to ${lang} language from English for my web app.
|
|
350
|
+
Keep keys, as is, write translation into values! Here are the strings:
|
|
351
|
+
|
|
352
|
+
\`\`\`json
|
|
353
|
+
${
|
|
354
|
+
JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object => {
|
|
355
|
+
acc[s.en_string] = '';
|
|
356
|
+
return acc;
|
|
357
|
+
}, {}), null, 2)
|
|
358
|
+
}
|
|
359
|
+
\`\`\`
|
|
360
|
+
`;
|
|
361
|
+
// call OpenAI
|
|
362
|
+
const resp = await this.options.completeAdapter.complete(
|
|
363
|
+
prompt,
|
|
364
|
+
[],
|
|
365
|
+
300,
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
if (resp.error) {
|
|
369
|
+
throw new AiTranslateError(resp.error);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// parse response like
|
|
373
|
+
// Here are the translations for the strings you provided:
|
|
374
|
+
// ```json
|
|
375
|
+
// [{"live": "canlı"}, {"Table Games": "Masa Oyunları"}]
|
|
376
|
+
// ```
|
|
377
|
+
let res;
|
|
378
|
+
try {
|
|
379
|
+
res = resp.content.split("```json")[1].split("```")[0];
|
|
380
|
+
} catch (e) {
|
|
381
|
+
console.error('error in parsing OpenAI', resp);
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
res = JSON.parse(res);
|
|
385
|
+
for (const [enStr, translatedStr] of Object.entries(res)) {
|
|
386
|
+
const translationsTargeted = translations.filter(t => t[this.enFieldName] === enStr);
|
|
387
|
+
// might be several with same en_string
|
|
388
|
+
for (const translation of translationsTargeted) {
|
|
389
|
+
translation[this.trFieldNames[lang]] = translatedStr;
|
|
390
|
+
// process.env.HEAVY_DEBUG && console.log(`🪲translated to ${lang} ${translation.en_string}, ${translatedStr}`)
|
|
391
|
+
if (!updateStrings[enStr]) {
|
|
392
|
+
updateStrings[enStr] = {
|
|
393
|
+
updates: {},
|
|
394
|
+
category: translation[this.options.categoryFieldName],
|
|
395
|
+
strId: translation[this.primaryKeyFieldName],
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
updateStrings[enStr].updates[this.trFieldNames[lang]] = translatedStr;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const langsInvolved = new Set(Object.keys(needToTranslateByLang));
|
|
405
|
+
|
|
406
|
+
await Promise.all(Object.entries(needToTranslateByLang).map(async ([lang, strings]: [LanguageCode, { en_string: string, category: string }[]]) => {
|
|
407
|
+
await translateToLang(lang, strings);
|
|
408
|
+
}));
|
|
409
|
+
|
|
410
|
+
await Promise.all(
|
|
411
|
+
Object.entries(updateStrings).map(
|
|
412
|
+
async ([_, { updates, strId }]: [string, { updates: any, category: string, strId: string }]) => {
|
|
413
|
+
// because this will translate all languages, we can set completedLangs to all languages
|
|
414
|
+
const futureCompletedFieldValue = this.fullCompleatedFieldValue;
|
|
415
|
+
|
|
416
|
+
await this.adminforth.resource(this.resourceConfig.resourceId).update(strId, {
|
|
417
|
+
...updates,
|
|
418
|
+
[this.options.completedFieldName]: futureCompletedFieldValue,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
)
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
for (const lang of langsInvolved) {
|
|
425
|
+
this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
|
|
426
|
+
for (const [enStr, { category }] of Object.entries(updateStrings)) {
|
|
427
|
+
this.cache.clear(`${this.resourceConfig.resourceId}:${category}:${lang}:${enStr}`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
async processExtractedMessages(adminforth: IAdminForth, filePath: string) {
|
|
434
|
+
// messages file is in i18n-messages.json
|
|
435
|
+
let messages;
|
|
436
|
+
try {
|
|
437
|
+
messages = await fs.readJson(filePath);
|
|
438
|
+
process.env.HEAVY_DEBUG && console.info('🐛 Messages file found');
|
|
439
|
+
|
|
440
|
+
} catch (e) {
|
|
441
|
+
process.env.HEAVY_DEBUG && console.error('🐛 Messages file not yet exists, probably npm run i18n:extract not finished/started yet, might be ok');
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
// loop over missingKeys[i].path and add them to database if not exists
|
|
445
|
+
await Promise.all(messages.missingKeys.map(async (missingKey: any) => {
|
|
446
|
+
const key = missingKey.path;
|
|
447
|
+
const file = missingKey.file;
|
|
448
|
+
const category = 'frontend';
|
|
449
|
+
const exists = await adminforth.resource(this.resourceConfig.resourceId).count(Filters.EQ(this.enFieldName, key));
|
|
450
|
+
if (exists) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const record = {
|
|
454
|
+
[this.enFieldName]: key,
|
|
455
|
+
[this.options.categoryFieldName]: category,
|
|
456
|
+
...(this.options.sourceFieldName ? { [this.options.sourceFieldName]: file } : {}),
|
|
457
|
+
};
|
|
458
|
+
try {
|
|
459
|
+
await adminforth.resource(this.resourceConfig.resourceId).create(record);
|
|
460
|
+
} catch (e) {
|
|
461
|
+
console.error('🐛 Error creating record', e);
|
|
462
|
+
}
|
|
463
|
+
}))
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
async tryProcessAndWatch(adminforth: IAdminForth) {
|
|
470
|
+
const spaDir = adminforth.codeInjector.spaTmpPath();
|
|
471
|
+
// messages file is in i18n-messages.json
|
|
472
|
+
const messagesFile = path.join(spaDir, '..', 'spa_tmp', 'i18n-messages.json');
|
|
473
|
+
console.log('🪲messagesFile', messagesFile);
|
|
474
|
+
this.processExtractedMessages(adminforth, messagesFile);
|
|
475
|
+
// we use watcher because file can't be yet created when we start - bundleNow can be done in build time or can be done now
|
|
476
|
+
// that is why we make attempt to process it now and then watch for changes
|
|
477
|
+
const w = chokidar.watch(messagesFile, { persistent: true });
|
|
478
|
+
w.on('change', () => {
|
|
479
|
+
this.processExtractedMessages(adminforth, messagesFile);
|
|
480
|
+
});
|
|
481
|
+
w.on('add', () => {
|
|
482
|
+
this.processExtractedMessages(adminforth, messagesFile);
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
|
|
488
|
+
// optional method where you can safely check field types after database discovery was performed
|
|
489
|
+
// ensure each trFieldName (apart from enFieldName) is nullable column of type string
|
|
490
|
+
for (const lang of this.options.supportedLanguages) {
|
|
491
|
+
if (lang === 'en') {
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
const column = resourceConfig.columns.find(c => c.name === this.trFieldNames[lang]);
|
|
495
|
+
if (!column) {
|
|
496
|
+
throw new Error(`Field ${this.trFieldNames[lang]} not found for storing translation for language ${lang}
|
|
497
|
+
in resource ${resourceConfig.resourceId}, consider adding it to columns or change trFieldNames option to remap it to existing column`);
|
|
498
|
+
}
|
|
499
|
+
if (column.required.create || column.required.edit) {
|
|
500
|
+
throw new Error(`Field ${this.trFieldNames[lang]} should be not required in resource ${resourceConfig.resourceId}`);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// ensure categoryFieldName defined and is string
|
|
505
|
+
if (!this.options.categoryFieldName) {
|
|
506
|
+
throw new Error(`categoryFieldName option is not defined. It is used to categorize translations and return only specific category e.g. to frontend`);
|
|
507
|
+
}
|
|
508
|
+
const categoryColumn = resourceConfig.columns.find(c => c.name === this.options.categoryFieldName);
|
|
509
|
+
if (!categoryColumn) {
|
|
510
|
+
throw new Error(`Field ${this.options.categoryFieldName} not found in resource ${resourceConfig.resourceId}`);
|
|
511
|
+
}
|
|
512
|
+
if (categoryColumn.type !== AdminForthDataTypes.STRING && categoryColumn.type !== AdminForthDataTypes.TEXT) {
|
|
513
|
+
throw new Error(`Field ${this.options.categoryFieldName} should be of type string in resource ${resourceConfig.resourceId}, but it is ${categoryColumn.type}`);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// in this plugin we will use plugin to fill the database with missing language messages
|
|
517
|
+
this.tryProcessAndWatch(adminforth);
|
|
518
|
+
|
|
519
|
+
adminforth.tr = async (msg: string, category: string, lang: string, params): Promise<string> => {
|
|
520
|
+
// console.log('🪲tr', msg, category, lang);
|
|
521
|
+
|
|
522
|
+
// if lang is not supported , throw
|
|
523
|
+
if (!this.options.supportedLanguages.includes(lang as LanguageCode)) {
|
|
524
|
+
throw new Error(`Language ${lang} is not entered to be supported by requested by browser in request headers accept-language`);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
let result;
|
|
528
|
+
// try to get translation from cache
|
|
529
|
+
const cacheKey = `${resourceConfig.resourceId}:${category}:${lang}:${msg}`;
|
|
530
|
+
const cached = await this.cache.get(cacheKey);
|
|
531
|
+
if (cached) {
|
|
532
|
+
result = cached;
|
|
533
|
+
}
|
|
534
|
+
if (!result) {
|
|
535
|
+
const resource = adminforth.resource(resourceConfig.resourceId);
|
|
536
|
+
const translation = await resource.get([Filters.EQ(this.enFieldName, msg), Filters.EQ(this.options.categoryFieldName, category)]);
|
|
537
|
+
if (!translation) {
|
|
538
|
+
await resource.create({
|
|
539
|
+
[this.enFieldName]: msg,
|
|
540
|
+
[this.options.categoryFieldName]: category,
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// do this check here, to faster register missing translations
|
|
545
|
+
// also not cache it - no sense to cache english strings
|
|
546
|
+
if (lang === 'en') {
|
|
547
|
+
// set to cache to return faster next time
|
|
548
|
+
result = msg;
|
|
549
|
+
} else {
|
|
550
|
+
result = translation?.[this.trFieldNames[lang]];
|
|
551
|
+
if (!result) {
|
|
552
|
+
// return english
|
|
553
|
+
result = msg;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
// cache so even if key does not exist, we will not hit database
|
|
557
|
+
await this.cache.set(cacheKey, result);
|
|
558
|
+
}
|
|
559
|
+
if (params) {
|
|
560
|
+
for (const [key, value] of Object.entries(params)) {
|
|
561
|
+
result = result.replace(`{${key}}`, value);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return result;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
instanceUniqueRepresentation(pluginOptions: any) : string {
|
|
569
|
+
// optional method to return unique string representation of plugin instance.
|
|
570
|
+
// Needed if plugin can have multiple instances on one resource
|
|
571
|
+
return `single`;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
setupEndpoints(server: IHttpServer) {
|
|
576
|
+
server.endpoint({
|
|
577
|
+
method: 'GET',
|
|
578
|
+
path: `/plugin/${this.pluginInstanceId}/frontend_messages`,
|
|
579
|
+
noAuth: true,
|
|
580
|
+
handler: async ({ query }) => {
|
|
581
|
+
const lang = query.lang;
|
|
582
|
+
|
|
583
|
+
// form map of translations
|
|
584
|
+
const resource = this.adminforth.resource(this.resourceConfig.resourceId);
|
|
585
|
+
const cacheKey = `${this.resourceConfig.resourceId}:frontend:${lang}`;
|
|
586
|
+
const cached = await this.cache.get(cacheKey);
|
|
587
|
+
if (cached) {
|
|
588
|
+
return cached;
|
|
589
|
+
}
|
|
590
|
+
const translations = {};
|
|
591
|
+
const allTranslations = await resource.list([Filters.EQ(this.options.categoryFieldName, 'frontend')]);
|
|
592
|
+
for (const tr of allTranslations) {
|
|
593
|
+
translations[tr[this.enFieldName]] = tr[this.trFieldNames[lang]];
|
|
594
|
+
}
|
|
595
|
+
await this.cache.set(cacheKey, translations);
|
|
596
|
+
return translations;
|
|
597
|
+
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@adminforth/i18n",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc && rsync -av --exclude 'node_modules' custom dist/ && npm version patch",
|
|
9
|
+
"rollout": "npm run build && npm publish --access public",
|
|
10
|
+
"prepare": "npm link adminforth"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [],
|
|
13
|
+
"author": "",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"description": "",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@aws-sdk/client-ses": "^3.654.0",
|
|
18
|
+
"chokidar": "^4.0.1",
|
|
19
|
+
"iso-639-1": "^3.1.3"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"i18n-iso-countries": "^7.13.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include*/
|
|
4
|
+
"module": "node16", /* Specify what module code is generated. */
|
|
5
|
+
"outDir": "./dist", /* Specify an output folder for all emitted files. */
|
|
6
|
+
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. */
|
|
7
|
+
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
|
8
|
+
"strict": false, /* Enable all strict type-checking options. */
|
|
9
|
+
"skipLibCheck": true, /* Skip type checking all .d.ts files. */
|
|
10
|
+
},
|
|
11
|
+
"exclude": ["node_modules", "dist", "custom"], /* Exclude files from compilation. */
|
|
12
|
+
}
|
package/types.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { CompletionAdapter, EmailAdapter } from 'adminforth';
|
|
2
|
+
import type { LanguageCode } from 'iso-639-1';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export interface PluginOptions {
|
|
6
|
+
|
|
7
|
+
/* List of ISO 639-1 language codes which you want to tsupport*/
|
|
8
|
+
supportedLanguages: LanguageCode[];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Each translation string will be stored in a separate field, you can remap it to existing columns using this option
|
|
12
|
+
* By default it will assume field are named like `${lang_code}_string` (e.g. 'en_string', 'uk_string', 'ja_string', 'fr_string')
|
|
13
|
+
*/
|
|
14
|
+
translationFieldNames: Partial<Record<LanguageCode, string>>;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Each string has a category, e.g. it might come from 'frontend' or some message from backend or column name on backend
|
|
18
|
+
* To deliver translations efficiently we need to store the category of each string.
|
|
19
|
+
* We recommend to put index on this column
|
|
20
|
+
*/
|
|
21
|
+
categoryFieldName: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Optional source field to store e.g. file name where it first was captured
|
|
25
|
+
*/
|
|
26
|
+
sourceFieldName?: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Optional field to save list of completed translations
|
|
30
|
+
* Helps to filter out strings which are not translated. If you define this field plugin will automatically
|
|
31
|
+
*/
|
|
32
|
+
completedFieldName?: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Optionally translation plugin supports LLM completion adapter (like OpenAI) for generating translations
|
|
36
|
+
* semiautomatically (creates a bulk action for generating translations)
|
|
37
|
+
*/
|
|
38
|
+
completeAdapter?: CompletionAdapter
|
|
39
|
+
}
|