lit 1.0 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|