lit 1.0 → 1.1.2
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.
- checksums.yaml +4 -4
- data/README.md +13 -5
- data/app/assets/javascripts/lit/backend/bootstrap.min.js +7 -0
- data/app/assets/javascripts/lit/backend/localizations.js.coffee +13 -6
- data/app/assets/stylesheets/lit/application.css +16 -13
- data/app/controllers/lit/api/v1/localizations_controller.rb +12 -15
- data/app/controllers/lit/cloud_translations_controller.rb +1 -1
- data/app/controllers/lit/concerns/request_info_store.rb +16 -10
- data/app/controllers/lit/concerns/request_keys_store.rb +17 -10
- data/app/controllers/lit/localization_keys_controller.rb +40 -34
- data/app/controllers/lit/localizations_controller.rb +1 -1
- data/app/controllers/lit/sources_controller.rb +1 -1
- data/app/helpers/lit/frontend_helper.rb +1 -1
- data/app/helpers/lit/localizations_helper.rb +9 -0
- data/app/models/lit/base.rb +33 -17
- data/app/models/lit/incomming_localization.rb +13 -27
- data/app/models/lit/localization.rb +6 -14
- data/app/services/remote_interactor_service.rb +3 -1
- data/app/services/synchronize_source_service.rb +4 -8
- data/app/views/layouts/lit/application.html.erb +0 -1
- data/app/views/lit/dashboard/index.html.erb +1 -1
- data/app/views/lit/incomming_localizations/index.html.erb +1 -1
- data/app/views/lit/localization_keys/_localizations_list.html.erb +19 -11
- data/app/views/lit/localization_keys/batch_touch.js.erb +1 -0
- data/app/views/lit/localization_keys/index.html.erb +2 -0
- data/app/views/lit/localization_keys/not_translated.html.erb +2 -0
- data/app/views/lit/localization_keys/visited_again.html.erb +3 -0
- data/app/views/lit/localizations/update.js.erb +1 -1
- data/config/routes.rb +1 -0
- data/lib/generators/lit/install/templates/initializer.rb +6 -3
- data/lib/lit.rb +19 -6
- data/lib/lit/adapters/hash_storage.rb +35 -1
- data/lib/lit/adapters/redis_storage.rb +42 -7
- data/lib/lit/cache.rb +66 -10
- data/lib/lit/cloud_translation/providers/google.rb +2 -0
- data/lib/lit/cloud_translation/providers/yandex.rb +2 -0
- data/lib/lit/engine.rb +12 -5
- data/lib/lit/export.rb +2 -18
- data/lib/lit/i18n_backend.rb +20 -7
- data/lib/lit/import.rb +18 -15
- data/lib/lit/loader.rb +1 -0
- data/lib/lit/middleware.rb +29 -0
- data/lib/lit/rails.rb +1 -0
- data/lib/lit/railtie.rb +6 -7
- data/lib/lit/services/localization_keys_to_hash_service.rb +23 -0
- data/lib/lit/version.rb +1 -1
- metadata +30 -263
- data/app/assets/images/lit/famfamfam_flags/ad.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ae.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/af.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ag.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ai.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/al.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/am.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/an.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ao.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ar.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/as.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/at.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/au.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/aw.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ax.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/az.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ba.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bb.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bd.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/be.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bf.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bg.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bh.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bi.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bj.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bo.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/br.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bs.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bt.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bv.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bw.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/by.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/bz.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ca.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/catalonia.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cc.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cd.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cf.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cg.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ch.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ci.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ck.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cl.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/co.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cs.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cu.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cv.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cx.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cy.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/cz.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/da.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/de.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/dj.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/dk.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/dm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/do.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/dz.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ec.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ee.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/eg.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/eh.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/en.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/england.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/er.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/es.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/et.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/europeanunion.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/fam.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/fi.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/fj.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/fk.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/fm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/fo.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/fr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ga.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gb.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gd.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ge.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gf.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gh.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gi.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gl.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gp.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gq.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gs.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gt.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gu.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gw.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/gy.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/hk.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/hm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/hn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/hr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ht.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/hu.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/id.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ie.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/il.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/in.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/io.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/iq.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ir.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/is.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/it.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ja.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/jm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/jo.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/jp.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ke.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/kg.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/kh.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ki.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/km.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/kn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/kp.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/kr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/kw.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ky.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/kz.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/la.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/lb.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/lc.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/li.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/lk.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/lr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ls.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/lt.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/lu.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/lv.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ly.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ma.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mc.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/md.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/me.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mg.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mh.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mk.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ml.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mo.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mp.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mq.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ms.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mt.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mu.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mv.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mw.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mx.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/my.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/mz.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/na.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/nc.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ne.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/nf.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ng.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ni.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/nl.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/no.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/np.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/nr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/nu.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/nz.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/om.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pa.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pe.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pf.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pg.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ph.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pk.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pl.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ps.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pt.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/pw.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/py.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/qa.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/re.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ro.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/rs.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ru.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/rw.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sa.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sb.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sc.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/scotland.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sd.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/se.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sg.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sh.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/si.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sj.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sk.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sl.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/so.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/st.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sv.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sy.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/sz.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tc.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/td.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tf.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tg.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/th.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tj.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tk.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tl.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/to.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tr.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tt.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tv.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tw.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/tz.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ua.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ug.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/um.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/us.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/uy.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/uz.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/va.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/vc.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ve.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/vg.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/vi.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/vn.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/vu.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/wales.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/wf.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ws.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/ye.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/yt.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/za.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/zm.png +0 -0
- data/app/assets/images/lit/famfamfam_flags/zw.png +0 -0
|
@@ -2,11 +2,45 @@ module Lit
|
|
|
2
2
|
class HashStorage < Hash
|
|
3
3
|
def incr(key)
|
|
4
4
|
self[key] ||= 0
|
|
5
|
-
self[key]
|
|
5
|
+
if self[key].is_a?(Integer)
|
|
6
|
+
self[key] += 1
|
|
7
|
+
else
|
|
8
|
+
subtree_keys(key).each { |k| self[k] += 1 }
|
|
9
|
+
end
|
|
6
10
|
end
|
|
7
11
|
|
|
8
12
|
def prefix
|
|
9
13
|
nil
|
|
10
14
|
end
|
|
15
|
+
|
|
16
|
+
def [](key)
|
|
17
|
+
super || subtree_of_key(key)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def subtree_of_key(key)
|
|
23
|
+
keys_of_subtree = subtree_keys(key)
|
|
24
|
+
return nil if keys_of_subtree.empty?
|
|
25
|
+
|
|
26
|
+
cache_localizations = form_cache_localizations(keys_of_subtree)
|
|
27
|
+
|
|
28
|
+
full_subtree = Lit::LocalizationKeysToHashService.call(cache_localizations)
|
|
29
|
+
requested_part = full_subtree.dig(*key.split('.'))
|
|
30
|
+
return nil if requested_part.blank?
|
|
31
|
+
return requested_part if requested_part.is_a?(String)
|
|
32
|
+
|
|
33
|
+
requested_part.deep_transform_keys(&:to_sym)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def subtree_keys(key)
|
|
37
|
+
keys.select { |k| k.match?(/\A#{key}*/) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def form_cache_localizations(keys_of_subtree)
|
|
41
|
+
self_copy = self.select { |k, _| k.in?(keys_of_subtree) }
|
|
42
|
+
values_of_subtree = keys_of_subtree.map { |k| self_copy[k] }
|
|
43
|
+
Hash[keys_of_subtree.zip(values_of_subtree)]
|
|
44
|
+
end
|
|
11
45
|
end
|
|
12
46
|
end
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
require 'redis'
|
|
2
|
+
require 'lit/services/localization_keys_to_hash_service'
|
|
3
|
+
|
|
2
4
|
module Lit
|
|
3
5
|
extend self
|
|
4
6
|
def redis
|
|
@@ -16,13 +18,25 @@ module Lit
|
|
|
16
18
|
Lit.redis
|
|
17
19
|
end
|
|
18
20
|
|
|
21
|
+
# This handles a change in the redis-rb gem that changes exists => exists?
|
|
22
|
+
def exists?(key)
|
|
23
|
+
# Use recommended binary-returning method create [with this redis-rb commit](https://github.com/redis/redis-rb/commit/bf42fc9e0db4a1719d9b1ecc65aeb20425d44427).
|
|
24
|
+
return Lit.redis.exists?(key) if Lit.redis.respond_to?(:exists?)
|
|
25
|
+
|
|
26
|
+
# Fall back with older gem
|
|
27
|
+
Lit.redis.exists(key)
|
|
28
|
+
end
|
|
29
|
+
|
|
19
30
|
def [](key)
|
|
20
|
-
if
|
|
31
|
+
if exists?(_prefixed_key_for_array(key))
|
|
21
32
|
Lit.redis.lrange(_prefixed_key(key), 0, -1)
|
|
22
|
-
elsif
|
|
33
|
+
elsif exists?(_prefixed_key_for_nil(key))
|
|
23
34
|
nil
|
|
24
35
|
else
|
|
25
|
-
Lit.redis.get(_prefixed_key(key))
|
|
36
|
+
val = Lit.redis.get(_prefixed_key(key))
|
|
37
|
+
return val if val.present?
|
|
38
|
+
|
|
39
|
+
subtree_of_key(key)
|
|
26
40
|
end
|
|
27
41
|
end
|
|
28
42
|
|
|
@@ -56,7 +70,7 @@ module Lit
|
|
|
56
70
|
end
|
|
57
71
|
|
|
58
72
|
def has_key?(key)
|
|
59
|
-
|
|
73
|
+
exists?(_prefixed_key(key))
|
|
60
74
|
end
|
|
61
75
|
alias key? has_key?
|
|
62
76
|
|
|
@@ -77,11 +91,13 @@ module Lit
|
|
|
77
91
|
private
|
|
78
92
|
|
|
79
93
|
def _prefix
|
|
80
|
-
|
|
94
|
+
return @prefix_cached if @prefix_cached.present?
|
|
95
|
+
|
|
96
|
+
@prefix_cached = 'lit:'
|
|
81
97
|
if Lit.storage_options.is_a?(Hash) && Lit.storage_options.key?(:prefix)
|
|
82
|
-
|
|
98
|
+
@prefix_cached += "#{Lit.storage_options[:prefix]}:"
|
|
83
99
|
end
|
|
84
|
-
|
|
100
|
+
@prefix_cached
|
|
85
101
|
end
|
|
86
102
|
|
|
87
103
|
def _prefixed_key(key = '')
|
|
@@ -95,5 +111,24 @@ module Lit
|
|
|
95
111
|
def _prefixed_key_for_nil(key = '')
|
|
96
112
|
_prefix + 'nil_flags:' + key.to_s
|
|
97
113
|
end
|
|
114
|
+
|
|
115
|
+
def subtree_of_key(key)
|
|
116
|
+
keys_of_subtree = Lit.redis.keys("#{_prefixed_key(key)}*")
|
|
117
|
+
return nil if keys_of_subtree.empty?
|
|
118
|
+
|
|
119
|
+
values_of_subtree = Lit.redis.mget(keys_of_subtree)
|
|
120
|
+
cache_localizations = form_cache_localizations(keys_of_subtree, values_of_subtree)
|
|
121
|
+
|
|
122
|
+
full_subtree = Lit::LocalizationKeysToHashService.call(cache_localizations)
|
|
123
|
+
requested_part = full_subtree.dig(*key.split('.'))
|
|
124
|
+
return nil if requested_part.blank?
|
|
125
|
+
return requested_part if requested_part.is_a?(String)
|
|
126
|
+
|
|
127
|
+
requested_part.deep_transform_keys(&:to_sym)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def form_cache_localizations(keys, values)
|
|
131
|
+
Hash[keys.map { |k| k.sub(_prefix, '') }.zip(values)]
|
|
132
|
+
end
|
|
98
133
|
end
|
|
99
134
|
end
|
data/lib/lit/cache.rb
CHANGED
|
@@ -18,22 +18,39 @@ end
|
|
|
18
18
|
|
|
19
19
|
module Lit
|
|
20
20
|
class Cache
|
|
21
|
+
@@last_update = nil
|
|
22
|
+
@@localization_cache = {}
|
|
23
|
+
|
|
21
24
|
def initialize
|
|
22
25
|
@hits_counter = Lit.get_key_value_engine
|
|
23
26
|
@request_info_store = Lit.get_key_value_engine
|
|
24
|
-
@hits_counter_working =
|
|
27
|
+
@hits_counter_working = Lit.hits_counter_enabled
|
|
25
28
|
@keys = nil
|
|
29
|
+
|
|
30
|
+
# current instance cache
|
|
26
31
|
@localization_object_cache = {}
|
|
27
32
|
@localization_key_object_cache = {}
|
|
33
|
+
clear_localization_cache
|
|
28
34
|
end
|
|
29
35
|
|
|
30
36
|
def [](key)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
value = nil
|
|
38
|
+
check_and_clean_if_required
|
|
39
|
+
unless localization_cache.key?(key)
|
|
40
|
+
value = localizations[key]
|
|
41
|
+
localization_cache[key] = value
|
|
42
|
+
else
|
|
43
|
+
value = localization_cache[key]
|
|
44
|
+
end
|
|
45
|
+
update_hits_count(key) if @hits_counter_working
|
|
46
|
+
|
|
47
|
+
if Lit.store_request_info ||
|
|
48
|
+
Lit.store_request_keys
|
|
49
|
+
key_without_locale = split_key(key).last
|
|
50
|
+
store_request_info(key_without_locale)
|
|
51
|
+
update_request_keys(key_without_locale, value)
|
|
52
|
+
end
|
|
53
|
+
value
|
|
37
54
|
end
|
|
38
55
|
|
|
39
56
|
def []=(key, value)
|
|
@@ -45,7 +62,8 @@ module Lit
|
|
|
45
62
|
end
|
|
46
63
|
|
|
47
64
|
def has_key?(key)
|
|
48
|
-
|
|
65
|
+
# check for instance cache first
|
|
66
|
+
localization_cache.has_key?(key) || localizations.has_key?(key)
|
|
49
67
|
end
|
|
50
68
|
|
|
51
69
|
def sync
|
|
@@ -67,12 +85,15 @@ module Lit
|
|
|
67
85
|
locale = find_locale(locale_key)
|
|
68
86
|
localization = find_localization(locale, key_without_locale, value: value, force_array: force_array, update_value: true)
|
|
69
87
|
return localization.translation if startup_process && localization.is_changed?
|
|
88
|
+
|
|
70
89
|
localizations[key] = localization.translation if localization
|
|
90
|
+
localization_cache[key] = localizations[key]
|
|
71
91
|
end
|
|
72
92
|
|
|
73
93
|
def update_cache(key, value)
|
|
74
94
|
key = key.to_s
|
|
75
95
|
localizations[key] = value
|
|
96
|
+
localization_cache[key] = value
|
|
76
97
|
end
|
|
77
98
|
|
|
78
99
|
def delete_locale(key)
|
|
@@ -83,6 +104,7 @@ module Lit
|
|
|
83
104
|
delete_localization(locale, key_without_locale)
|
|
84
105
|
@localization_key_object_cache = {}
|
|
85
106
|
@localization_object_cache = {}
|
|
107
|
+
clear_localization_cache
|
|
86
108
|
end
|
|
87
109
|
|
|
88
110
|
def load_all_translations
|
|
@@ -103,6 +125,7 @@ module Lit
|
|
|
103
125
|
@localization_object_cache.delete(key)
|
|
104
126
|
localization = find_localization(locale, key_without_locale, default_fallback: true)
|
|
105
127
|
localizations[key] = localization.translation if localization
|
|
128
|
+
clear_localization_cache
|
|
106
129
|
end
|
|
107
130
|
|
|
108
131
|
def delete_key(key)
|
|
@@ -115,10 +138,16 @@ module Lit
|
|
|
115
138
|
I18n.backend.reload!
|
|
116
139
|
end
|
|
117
140
|
|
|
118
|
-
def
|
|
141
|
+
def reset_local_cache
|
|
119
142
|
@locale_cache = {}
|
|
120
143
|
@localization_key_object_cache = {}
|
|
121
144
|
@localization_object_cache = {}
|
|
145
|
+
@localization_cache = {}
|
|
146
|
+
clear_localization_cache
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def reset
|
|
150
|
+
reset_local_cache
|
|
122
151
|
localizations.clear
|
|
123
152
|
localization_keys.clear
|
|
124
153
|
load_all_translations
|
|
@@ -128,7 +157,7 @@ module Lit
|
|
|
128
157
|
def find_locale(locale_key)
|
|
129
158
|
locale_key = locale_key.to_s
|
|
130
159
|
@locale_cache ||= {}
|
|
131
|
-
unless @locale_cache.key?(locale_key)
|
|
160
|
+
unless @locale_cache.key?(locale_key) && @locale_cache[locale_key].id
|
|
132
161
|
locale = Lit::Locale.where(locale: locale_key).first_or_create!
|
|
133
162
|
@locale_cache[locale_key] = locale
|
|
134
163
|
end
|
|
@@ -151,6 +180,29 @@ module Lit
|
|
|
151
180
|
@hits_counter_working = true
|
|
152
181
|
end
|
|
153
182
|
|
|
183
|
+
def localization_cache
|
|
184
|
+
# Thread.current[:lit_thread_cache] ||= {}
|
|
185
|
+
@@localization_cache ||= {}
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def clear_localization_cache
|
|
189
|
+
# Thread.current[:lit_thread_cache] = {}
|
|
190
|
+
@@localization_cache = {}
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def check_and_clean_if_required
|
|
194
|
+
# we want this method to run only once during a request or background job
|
|
195
|
+
return if Thread.current[:localization_cache_valid]
|
|
196
|
+
|
|
197
|
+
# get most recently updated translation and compare with what we store in class var
|
|
198
|
+
last_up = Lit::Localization.order(updated_at: :desc).limit(1).pluck(:updated_at).first.to_i
|
|
199
|
+
if last_up != @@last_update
|
|
200
|
+
clear_localization_cache
|
|
201
|
+
@@last_update = last_up
|
|
202
|
+
end
|
|
203
|
+
Thread.current[:localization_cache_valid] = true
|
|
204
|
+
end
|
|
205
|
+
|
|
154
206
|
private
|
|
155
207
|
|
|
156
208
|
def localizations
|
|
@@ -305,6 +357,7 @@ module Lit
|
|
|
305
357
|
|
|
306
358
|
def update_hits_count(key)
|
|
307
359
|
return unless @hits_counter_working
|
|
360
|
+
|
|
308
361
|
key_without_locale = split_key(key).last
|
|
309
362
|
@hits_counter.incr('hits_counter.' + key)
|
|
310
363
|
@hits_counter.incr('global_hits_counter.' + key_without_locale)
|
|
@@ -313,6 +366,7 @@ module Lit
|
|
|
313
366
|
def store_request_info(key_without_locale)
|
|
314
367
|
return unless Lit.store_request_info
|
|
315
368
|
return unless Thread.current[:lit_current_request_path].present?
|
|
369
|
+
|
|
316
370
|
info = get_request_info(key_without_locale)
|
|
317
371
|
parts = info.split(' ').push(Thread.current[:lit_current_request_path]).uniq
|
|
318
372
|
parts.shift if parts.count > 10
|
|
@@ -320,7 +374,9 @@ module Lit
|
|
|
320
374
|
end
|
|
321
375
|
|
|
322
376
|
def update_request_keys(key_without_locale, localization)
|
|
377
|
+
return unless Lit.store_request_keys
|
|
323
378
|
return if Thread.current[:lit_request_keys].nil?
|
|
379
|
+
|
|
324
380
|
Thread.current[:lit_request_keys] ||= {}
|
|
325
381
|
Thread.current[:lit_request_keys][key_without_locale] = localization
|
|
326
382
|
end
|
data/lib/lit/engine.rb
CHANGED
|
@@ -3,17 +3,18 @@ module Lit
|
|
|
3
3
|
require 'jquery-rails'
|
|
4
4
|
|
|
5
5
|
config.autoload_paths += %W[#{Lit::Engine.root}/app/controllers/lit/concerns]
|
|
6
|
+
paths.add 'lib', eager_load: true # Zeitwerk compatibility
|
|
6
7
|
|
|
7
8
|
isolate_namespace Lit
|
|
8
9
|
|
|
9
10
|
initializer 'lit.assets.precompile' do |app|
|
|
10
11
|
app.config.assets.precompile += %w[lit/application.css lit/application.js]
|
|
11
12
|
app.config.assets.precompile += %w[lit/lit_frontend.css lit/lit_frontend.js]
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
initializer 'lit.reloader' do |app|
|
|
16
|
+
config.to_prepare do
|
|
17
|
+
Lit.loader.cache.reset_local_cache if Lit.loader
|
|
17
18
|
end
|
|
18
19
|
end
|
|
19
20
|
|
|
@@ -24,5 +25,11 @@ module Lit
|
|
|
24
25
|
end
|
|
25
26
|
end
|
|
26
27
|
end
|
|
28
|
+
|
|
29
|
+
initializer :append_before_action do
|
|
30
|
+
ActionController::Base.send :before_action do
|
|
31
|
+
Thread.current[:lit_thread_cache] = {}
|
|
32
|
+
end
|
|
33
|
+
end
|
|
27
34
|
end
|
|
28
35
|
end
|
data/lib/lit/export.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'csv'
|
|
2
|
+
require 'lit/services/localization_keys_to_hash_service'
|
|
2
3
|
|
|
3
4
|
module Lit
|
|
4
5
|
class Export
|
|
@@ -17,7 +18,7 @@ module Lit
|
|
|
17
18
|
|
|
18
19
|
case format
|
|
19
20
|
when :yaml
|
|
20
|
-
exported_keys =
|
|
21
|
+
exported_keys = Lit::LocalizationKeysToHashService.call(db_localizations)
|
|
21
22
|
exported_keys.to_yaml
|
|
22
23
|
when :csv
|
|
23
24
|
relevant_locales = locale_keys.presence || I18n.available_locales.map(&:to_s)
|
|
@@ -55,23 +56,6 @@ module Lit
|
|
|
55
56
|
end
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
private_class_method def self.nested_string_keys_to_hash(db_localizations)
|
|
59
|
-
# http://subtech.g.hatena.ne.jp/cho45/20061122
|
|
60
|
-
deep_proc = proc do |_k, s, o|
|
|
61
|
-
if s.is_a?(Hash) && o.is_a?(Hash)
|
|
62
|
-
next s.merge(o, &deep_proc)
|
|
63
|
-
end
|
|
64
|
-
next o
|
|
65
|
-
end
|
|
66
|
-
nested_keys = {}
|
|
67
|
-
db_localizations.sort.each do |k, v|
|
|
68
|
-
key_parts = k.to_s.split('.')
|
|
69
|
-
converted = key_parts.reverse.reduce(v) { |a, n| { n => a } }
|
|
70
|
-
nested_keys.merge!(converted, &deep_proc)
|
|
71
|
-
end
|
|
72
|
-
nested_keys
|
|
73
|
-
end
|
|
74
|
-
|
|
75
59
|
# This is like Array#transpose but ignores size differences between inner arrays.
|
|
76
60
|
private_class_method def self.transpose(matrix)
|
|
77
61
|
maxlen = matrix.max { |x| x.length }.length
|
data/lib/lit/i18n_backend.rb
CHANGED
|
@@ -69,10 +69,20 @@ module Lit
|
|
|
69
69
|
|
|
70
70
|
parts = I18n.normalize_keys(locale, key, scope, options[:separator])
|
|
71
71
|
key_with_locale = parts.join('.')
|
|
72
|
+
|
|
73
|
+
# we might want to return content later, but we first need to check if it's in cache.
|
|
74
|
+
# it's important to rememver, that accessing non-existen key modifies cache by creating one
|
|
75
|
+
had_key = @cache.has_key?(key_with_locale)
|
|
76
|
+
|
|
72
77
|
# check in cache or in simple backend
|
|
73
78
|
content = @cache[key_with_locale] || super
|
|
79
|
+
|
|
80
|
+
# return if content is in cache - it CAN be `nil`
|
|
81
|
+
return content if had_key && !options[:default]
|
|
82
|
+
|
|
74
83
|
return content if parts.size <= 1
|
|
75
|
-
|
|
84
|
+
|
|
85
|
+
if content.nil? && should_cache?(key_with_locale, options, had_key)
|
|
76
86
|
new_content = @cache.init_key_with_value(key_with_locale, content)
|
|
77
87
|
content = new_content if content.nil? # Content can change when Lit.humanize is true for example
|
|
78
88
|
# so there is no content in cache - it might not be if ie. we're doing
|
|
@@ -106,7 +116,7 @@ module Lit
|
|
|
106
116
|
# it anyway if we return nil, but then it will wrap it also in
|
|
107
117
|
# translation_missing span.
|
|
108
118
|
# Humanizing key should be last resort
|
|
109
|
-
if content.nil? && Lit.humanize_key &&
|
|
119
|
+
if content.nil? && Lit.humanize_key && Lit.humanize_key_ignored.match(key).nil?
|
|
110
120
|
content = key.to_s.split('.').last.humanize
|
|
111
121
|
if content.present?
|
|
112
122
|
@cache[key_with_locale] = content
|
|
@@ -129,7 +139,7 @@ module Lit
|
|
|
129
139
|
# end
|
|
130
140
|
elsif data.respond_to?(:to_str) || data.is_a?(Array)
|
|
131
141
|
key = ([locale] + scope).join('.')
|
|
132
|
-
return if startup_process && @cache.keys.member?(key)
|
|
142
|
+
return if startup_process && Lit.ignore_yaml_on_startup && (Thread.current[:lit_cache_keys] || @cache.keys).member?(key)
|
|
133
143
|
@cache.update_locale(key, data, data.is_a?(Array), startup_process)
|
|
134
144
|
elsif data.nil?
|
|
135
145
|
return if startup_process
|
|
@@ -139,11 +149,13 @@ module Lit
|
|
|
139
149
|
end
|
|
140
150
|
|
|
141
151
|
def load_translations_to_cache
|
|
152
|
+
Thread.current[:lit_cache_keys] = @cache.keys
|
|
142
153
|
ActiveRecord::Base.transaction do
|
|
143
154
|
(@translations || {}).each do |locale, data|
|
|
144
155
|
store_item(locale, data, [], true) if valid_locale?(locale)
|
|
145
156
|
end
|
|
146
157
|
end
|
|
158
|
+
Thread.current[:lit_cache_keys] = nil
|
|
147
159
|
end
|
|
148
160
|
|
|
149
161
|
def init_translations
|
|
@@ -155,7 +167,7 @@ module Lit
|
|
|
155
167
|
# load translations from database to cache
|
|
156
168
|
@cache.load_all_translations
|
|
157
169
|
# load translations from @translations to cache
|
|
158
|
-
load_translations_to_cache
|
|
170
|
+
load_translations_to_cache unless Lit.ignore_yaml_on_startup
|
|
159
171
|
@initialized = true
|
|
160
172
|
end
|
|
161
173
|
|
|
@@ -179,9 +191,10 @@ module Lit
|
|
|
179
191
|
Lit.ignored_keys.any?{ |k| key_without_locale.start_with?(k) }
|
|
180
192
|
end
|
|
181
193
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
# checks if should cache. `had_key` is passed, as once cache has been accesed, it's already modified and key exists
|
|
195
|
+
def should_cache?(key_with_locale, options, had_key)
|
|
196
|
+
if had_key
|
|
197
|
+
return false unless options[:default] && !options[:default].is_a?(Array)
|
|
185
198
|
end
|
|
186
199
|
|
|
187
200
|
_, key_without_locale = ::Lit::Cache.split_key(key_with_locale)
|