lit 0.4.0.pre.alpha.4 → 1.1.0

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.
Files changed (292) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +89 -5
  3. data/Rakefile +9 -15
  4. data/app/assets/javascripts/lit/backend/bootstrap.min.js +7 -0
  5. data/app/controllers/lit/api/v1/localizations_controller.rb +7 -2
  6. data/app/controllers/lit/cloud_translations_controller.rb +26 -0
  7. data/app/controllers/lit/localization_keys_controller.rb +6 -0
  8. data/app/controllers/lit/localizations_controller.rb +3 -2
  9. data/app/controllers/lit/sources_controller.rb +1 -1
  10. data/app/helpers/lit/frontend_helper.rb +1 -1
  11. data/app/helpers/lit/localizations_helper.rb +13 -0
  12. data/app/models/lit/base.rb +33 -17
  13. data/app/models/lit/incomming_localization.rb +2 -2
  14. data/app/services/remote_interactor_service.rb +1 -0
  15. data/app/views/layouts/lit/application.html.erb +0 -1
  16. data/app/views/lit/cloud_translations/show.js.erb +14 -0
  17. data/app/views/lit/dashboard/index.html.erb +1 -1
  18. data/app/views/lit/incomming_localizations/index.html.erb +1 -1
  19. data/app/views/lit/localization_keys/_localizations_list.html.erb +1 -1
  20. data/app/views/lit/localization_keys/index.html.erb +2 -0
  21. data/app/views/lit/localization_keys/not_translated.html.erb +2 -0
  22. data/app/views/lit/localization_keys/visited_again.html.erb +3 -0
  23. data/app/views/lit/localizations/_form.html.erb +27 -0
  24. data/config/routes.rb +2 -0
  25. data/db/migrate/20181129103819_lit_add_localization_key_locale_unique_index_to_localizations.rb +7 -0
  26. data/lib/generators/lit/install/templates/initializer.rb +6 -3
  27. data/lib/lit.rb +19 -6
  28. data/lib/lit/adapters/hash_storage.rb +35 -1
  29. data/lib/lit/adapters/redis_storage.rb +41 -7
  30. data/lib/lit/cache.rb +47 -13
  31. data/lib/lit/cloud_translation.rb +53 -0
  32. data/lib/lit/cloud_translation/providers/base.rb +66 -0
  33. data/lib/lit/cloud_translation/providers/google.rb +117 -0
  34. data/lib/lit/cloud_translation/providers/yandex.rb +84 -0
  35. data/lib/lit/engine.rb +11 -5
  36. data/lib/lit/export.rb +2 -18
  37. data/lib/lit/i18n_backend.rb +20 -7
  38. data/lib/lit/import.rb +15 -14
  39. data/lib/lit/loader.rb +3 -1
  40. data/lib/lit/services/localization_keys_to_hash_service.rb +23 -0
  41. data/lib/lit/version.rb +1 -1
  42. metadata +125 -268
  43. data/app/assets/images/lit/famfamfam_flags/ad.png +0 -0
  44. data/app/assets/images/lit/famfamfam_flags/ae.png +0 -0
  45. data/app/assets/images/lit/famfamfam_flags/af.png +0 -0
  46. data/app/assets/images/lit/famfamfam_flags/ag.png +0 -0
  47. data/app/assets/images/lit/famfamfam_flags/ai.png +0 -0
  48. data/app/assets/images/lit/famfamfam_flags/al.png +0 -0
  49. data/app/assets/images/lit/famfamfam_flags/am.png +0 -0
  50. data/app/assets/images/lit/famfamfam_flags/an.png +0 -0
  51. data/app/assets/images/lit/famfamfam_flags/ao.png +0 -0
  52. data/app/assets/images/lit/famfamfam_flags/ar.png +0 -0
  53. data/app/assets/images/lit/famfamfam_flags/as.png +0 -0
  54. data/app/assets/images/lit/famfamfam_flags/at.png +0 -0
  55. data/app/assets/images/lit/famfamfam_flags/au.png +0 -0
  56. data/app/assets/images/lit/famfamfam_flags/aw.png +0 -0
  57. data/app/assets/images/lit/famfamfam_flags/ax.png +0 -0
  58. data/app/assets/images/lit/famfamfam_flags/az.png +0 -0
  59. data/app/assets/images/lit/famfamfam_flags/ba.png +0 -0
  60. data/app/assets/images/lit/famfamfam_flags/bb.png +0 -0
  61. data/app/assets/images/lit/famfamfam_flags/bd.png +0 -0
  62. data/app/assets/images/lit/famfamfam_flags/be.png +0 -0
  63. data/app/assets/images/lit/famfamfam_flags/bf.png +0 -0
  64. data/app/assets/images/lit/famfamfam_flags/bg.png +0 -0
  65. data/app/assets/images/lit/famfamfam_flags/bh.png +0 -0
  66. data/app/assets/images/lit/famfamfam_flags/bi.png +0 -0
  67. data/app/assets/images/lit/famfamfam_flags/bj.png +0 -0
  68. data/app/assets/images/lit/famfamfam_flags/bm.png +0 -0
  69. data/app/assets/images/lit/famfamfam_flags/bn.png +0 -0
  70. data/app/assets/images/lit/famfamfam_flags/bo.png +0 -0
  71. data/app/assets/images/lit/famfamfam_flags/br.png +0 -0
  72. data/app/assets/images/lit/famfamfam_flags/bs.png +0 -0
  73. data/app/assets/images/lit/famfamfam_flags/bt.png +0 -0
  74. data/app/assets/images/lit/famfamfam_flags/bv.png +0 -0
  75. data/app/assets/images/lit/famfamfam_flags/bw.png +0 -0
  76. data/app/assets/images/lit/famfamfam_flags/by.png +0 -0
  77. data/app/assets/images/lit/famfamfam_flags/bz.png +0 -0
  78. data/app/assets/images/lit/famfamfam_flags/ca.png +0 -0
  79. data/app/assets/images/lit/famfamfam_flags/catalonia.png +0 -0
  80. data/app/assets/images/lit/famfamfam_flags/cc.png +0 -0
  81. data/app/assets/images/lit/famfamfam_flags/cd.png +0 -0
  82. data/app/assets/images/lit/famfamfam_flags/cf.png +0 -0
  83. data/app/assets/images/lit/famfamfam_flags/cg.png +0 -0
  84. data/app/assets/images/lit/famfamfam_flags/ch.png +0 -0
  85. data/app/assets/images/lit/famfamfam_flags/ci.png +0 -0
  86. data/app/assets/images/lit/famfamfam_flags/ck.png +0 -0
  87. data/app/assets/images/lit/famfamfam_flags/cl.png +0 -0
  88. data/app/assets/images/lit/famfamfam_flags/cm.png +0 -0
  89. data/app/assets/images/lit/famfamfam_flags/cn.png +0 -0
  90. data/app/assets/images/lit/famfamfam_flags/co.png +0 -0
  91. data/app/assets/images/lit/famfamfam_flags/cr.png +0 -0
  92. data/app/assets/images/lit/famfamfam_flags/cs.png +0 -0
  93. data/app/assets/images/lit/famfamfam_flags/cu.png +0 -0
  94. data/app/assets/images/lit/famfamfam_flags/cv.png +0 -0
  95. data/app/assets/images/lit/famfamfam_flags/cx.png +0 -0
  96. data/app/assets/images/lit/famfamfam_flags/cy.png +0 -0
  97. data/app/assets/images/lit/famfamfam_flags/cz.png +0 -0
  98. data/app/assets/images/lit/famfamfam_flags/da.png +0 -0
  99. data/app/assets/images/lit/famfamfam_flags/de.png +0 -0
  100. data/app/assets/images/lit/famfamfam_flags/dj.png +0 -0
  101. data/app/assets/images/lit/famfamfam_flags/dk.png +0 -0
  102. data/app/assets/images/lit/famfamfam_flags/dm.png +0 -0
  103. data/app/assets/images/lit/famfamfam_flags/do.png +0 -0
  104. data/app/assets/images/lit/famfamfam_flags/dz.png +0 -0
  105. data/app/assets/images/lit/famfamfam_flags/ec.png +0 -0
  106. data/app/assets/images/lit/famfamfam_flags/ee.png +0 -0
  107. data/app/assets/images/lit/famfamfam_flags/eg.png +0 -0
  108. data/app/assets/images/lit/famfamfam_flags/eh.png +0 -0
  109. data/app/assets/images/lit/famfamfam_flags/en.png +0 -0
  110. data/app/assets/images/lit/famfamfam_flags/england.png +0 -0
  111. data/app/assets/images/lit/famfamfam_flags/er.png +0 -0
  112. data/app/assets/images/lit/famfamfam_flags/es.png +0 -0
  113. data/app/assets/images/lit/famfamfam_flags/et.png +0 -0
  114. data/app/assets/images/lit/famfamfam_flags/europeanunion.png +0 -0
  115. data/app/assets/images/lit/famfamfam_flags/fam.png +0 -0
  116. data/app/assets/images/lit/famfamfam_flags/fi.png +0 -0
  117. data/app/assets/images/lit/famfamfam_flags/fj.png +0 -0
  118. data/app/assets/images/lit/famfamfam_flags/fk.png +0 -0
  119. data/app/assets/images/lit/famfamfam_flags/fm.png +0 -0
  120. data/app/assets/images/lit/famfamfam_flags/fo.png +0 -0
  121. data/app/assets/images/lit/famfamfam_flags/fr.png +0 -0
  122. data/app/assets/images/lit/famfamfam_flags/ga.png +0 -0
  123. data/app/assets/images/lit/famfamfam_flags/gb.png +0 -0
  124. data/app/assets/images/lit/famfamfam_flags/gd.png +0 -0
  125. data/app/assets/images/lit/famfamfam_flags/ge.png +0 -0
  126. data/app/assets/images/lit/famfamfam_flags/gf.png +0 -0
  127. data/app/assets/images/lit/famfamfam_flags/gh.png +0 -0
  128. data/app/assets/images/lit/famfamfam_flags/gi.png +0 -0
  129. data/app/assets/images/lit/famfamfam_flags/gl.png +0 -0
  130. data/app/assets/images/lit/famfamfam_flags/gm.png +0 -0
  131. data/app/assets/images/lit/famfamfam_flags/gn.png +0 -0
  132. data/app/assets/images/lit/famfamfam_flags/gp.png +0 -0
  133. data/app/assets/images/lit/famfamfam_flags/gq.png +0 -0
  134. data/app/assets/images/lit/famfamfam_flags/gr.png +0 -0
  135. data/app/assets/images/lit/famfamfam_flags/gs.png +0 -0
  136. data/app/assets/images/lit/famfamfam_flags/gt.png +0 -0
  137. data/app/assets/images/lit/famfamfam_flags/gu.png +0 -0
  138. data/app/assets/images/lit/famfamfam_flags/gw.png +0 -0
  139. data/app/assets/images/lit/famfamfam_flags/gy.png +0 -0
  140. data/app/assets/images/lit/famfamfam_flags/hk.png +0 -0
  141. data/app/assets/images/lit/famfamfam_flags/hm.png +0 -0
  142. data/app/assets/images/lit/famfamfam_flags/hn.png +0 -0
  143. data/app/assets/images/lit/famfamfam_flags/hr.png +0 -0
  144. data/app/assets/images/lit/famfamfam_flags/ht.png +0 -0
  145. data/app/assets/images/lit/famfamfam_flags/hu.png +0 -0
  146. data/app/assets/images/lit/famfamfam_flags/id.png +0 -0
  147. data/app/assets/images/lit/famfamfam_flags/ie.png +0 -0
  148. data/app/assets/images/lit/famfamfam_flags/il.png +0 -0
  149. data/app/assets/images/lit/famfamfam_flags/in.png +0 -0
  150. data/app/assets/images/lit/famfamfam_flags/io.png +0 -0
  151. data/app/assets/images/lit/famfamfam_flags/iq.png +0 -0
  152. data/app/assets/images/lit/famfamfam_flags/ir.png +0 -0
  153. data/app/assets/images/lit/famfamfam_flags/is.png +0 -0
  154. data/app/assets/images/lit/famfamfam_flags/it.png +0 -0
  155. data/app/assets/images/lit/famfamfam_flags/ja.png +0 -0
  156. data/app/assets/images/lit/famfamfam_flags/jm.png +0 -0
  157. data/app/assets/images/lit/famfamfam_flags/jo.png +0 -0
  158. data/app/assets/images/lit/famfamfam_flags/jp.png +0 -0
  159. data/app/assets/images/lit/famfamfam_flags/ke.png +0 -0
  160. data/app/assets/images/lit/famfamfam_flags/kg.png +0 -0
  161. data/app/assets/images/lit/famfamfam_flags/kh.png +0 -0
  162. data/app/assets/images/lit/famfamfam_flags/ki.png +0 -0
  163. data/app/assets/images/lit/famfamfam_flags/km.png +0 -0
  164. data/app/assets/images/lit/famfamfam_flags/kn.png +0 -0
  165. data/app/assets/images/lit/famfamfam_flags/kp.png +0 -0
  166. data/app/assets/images/lit/famfamfam_flags/kr.png +0 -0
  167. data/app/assets/images/lit/famfamfam_flags/kw.png +0 -0
  168. data/app/assets/images/lit/famfamfam_flags/ky.png +0 -0
  169. data/app/assets/images/lit/famfamfam_flags/kz.png +0 -0
  170. data/app/assets/images/lit/famfamfam_flags/la.png +0 -0
  171. data/app/assets/images/lit/famfamfam_flags/lb.png +0 -0
  172. data/app/assets/images/lit/famfamfam_flags/lc.png +0 -0
  173. data/app/assets/images/lit/famfamfam_flags/li.png +0 -0
  174. data/app/assets/images/lit/famfamfam_flags/lk.png +0 -0
  175. data/app/assets/images/lit/famfamfam_flags/lr.png +0 -0
  176. data/app/assets/images/lit/famfamfam_flags/ls.png +0 -0
  177. data/app/assets/images/lit/famfamfam_flags/lt.png +0 -0
  178. data/app/assets/images/lit/famfamfam_flags/lu.png +0 -0
  179. data/app/assets/images/lit/famfamfam_flags/lv.png +0 -0
  180. data/app/assets/images/lit/famfamfam_flags/ly.png +0 -0
  181. data/app/assets/images/lit/famfamfam_flags/ma.png +0 -0
  182. data/app/assets/images/lit/famfamfam_flags/mc.png +0 -0
  183. data/app/assets/images/lit/famfamfam_flags/md.png +0 -0
  184. data/app/assets/images/lit/famfamfam_flags/me.png +0 -0
  185. data/app/assets/images/lit/famfamfam_flags/mg.png +0 -0
  186. data/app/assets/images/lit/famfamfam_flags/mh.png +0 -0
  187. data/app/assets/images/lit/famfamfam_flags/mk.png +0 -0
  188. data/app/assets/images/lit/famfamfam_flags/ml.png +0 -0
  189. data/app/assets/images/lit/famfamfam_flags/mm.png +0 -0
  190. data/app/assets/images/lit/famfamfam_flags/mn.png +0 -0
  191. data/app/assets/images/lit/famfamfam_flags/mo.png +0 -0
  192. data/app/assets/images/lit/famfamfam_flags/mp.png +0 -0
  193. data/app/assets/images/lit/famfamfam_flags/mq.png +0 -0
  194. data/app/assets/images/lit/famfamfam_flags/mr.png +0 -0
  195. data/app/assets/images/lit/famfamfam_flags/ms.png +0 -0
  196. data/app/assets/images/lit/famfamfam_flags/mt.png +0 -0
  197. data/app/assets/images/lit/famfamfam_flags/mu.png +0 -0
  198. data/app/assets/images/lit/famfamfam_flags/mv.png +0 -0
  199. data/app/assets/images/lit/famfamfam_flags/mw.png +0 -0
  200. data/app/assets/images/lit/famfamfam_flags/mx.png +0 -0
  201. data/app/assets/images/lit/famfamfam_flags/my.png +0 -0
  202. data/app/assets/images/lit/famfamfam_flags/mz.png +0 -0
  203. data/app/assets/images/lit/famfamfam_flags/na.png +0 -0
  204. data/app/assets/images/lit/famfamfam_flags/nc.png +0 -0
  205. data/app/assets/images/lit/famfamfam_flags/ne.png +0 -0
  206. data/app/assets/images/lit/famfamfam_flags/nf.png +0 -0
  207. data/app/assets/images/lit/famfamfam_flags/ng.png +0 -0
  208. data/app/assets/images/lit/famfamfam_flags/ni.png +0 -0
  209. data/app/assets/images/lit/famfamfam_flags/nl.png +0 -0
  210. data/app/assets/images/lit/famfamfam_flags/no.png +0 -0
  211. data/app/assets/images/lit/famfamfam_flags/np.png +0 -0
  212. data/app/assets/images/lit/famfamfam_flags/nr.png +0 -0
  213. data/app/assets/images/lit/famfamfam_flags/nu.png +0 -0
  214. data/app/assets/images/lit/famfamfam_flags/nz.png +0 -0
  215. data/app/assets/images/lit/famfamfam_flags/om.png +0 -0
  216. data/app/assets/images/lit/famfamfam_flags/pa.png +0 -0
  217. data/app/assets/images/lit/famfamfam_flags/pe.png +0 -0
  218. data/app/assets/images/lit/famfamfam_flags/pf.png +0 -0
  219. data/app/assets/images/lit/famfamfam_flags/pg.png +0 -0
  220. data/app/assets/images/lit/famfamfam_flags/ph.png +0 -0
  221. data/app/assets/images/lit/famfamfam_flags/pk.png +0 -0
  222. data/app/assets/images/lit/famfamfam_flags/pl.png +0 -0
  223. data/app/assets/images/lit/famfamfam_flags/pm.png +0 -0
  224. data/app/assets/images/lit/famfamfam_flags/pn.png +0 -0
  225. data/app/assets/images/lit/famfamfam_flags/pr.png +0 -0
  226. data/app/assets/images/lit/famfamfam_flags/ps.png +0 -0
  227. data/app/assets/images/lit/famfamfam_flags/pt.png +0 -0
  228. data/app/assets/images/lit/famfamfam_flags/pw.png +0 -0
  229. data/app/assets/images/lit/famfamfam_flags/py.png +0 -0
  230. data/app/assets/images/lit/famfamfam_flags/qa.png +0 -0
  231. data/app/assets/images/lit/famfamfam_flags/re.png +0 -0
  232. data/app/assets/images/lit/famfamfam_flags/ro.png +0 -0
  233. data/app/assets/images/lit/famfamfam_flags/rs.png +0 -0
  234. data/app/assets/images/lit/famfamfam_flags/ru.png +0 -0
  235. data/app/assets/images/lit/famfamfam_flags/rw.png +0 -0
  236. data/app/assets/images/lit/famfamfam_flags/sa.png +0 -0
  237. data/app/assets/images/lit/famfamfam_flags/sb.png +0 -0
  238. data/app/assets/images/lit/famfamfam_flags/sc.png +0 -0
  239. data/app/assets/images/lit/famfamfam_flags/scotland.png +0 -0
  240. data/app/assets/images/lit/famfamfam_flags/sd.png +0 -0
  241. data/app/assets/images/lit/famfamfam_flags/se.png +0 -0
  242. data/app/assets/images/lit/famfamfam_flags/sg.png +0 -0
  243. data/app/assets/images/lit/famfamfam_flags/sh.png +0 -0
  244. data/app/assets/images/lit/famfamfam_flags/si.png +0 -0
  245. data/app/assets/images/lit/famfamfam_flags/sj.png +0 -0
  246. data/app/assets/images/lit/famfamfam_flags/sk.png +0 -0
  247. data/app/assets/images/lit/famfamfam_flags/sl.png +0 -0
  248. data/app/assets/images/lit/famfamfam_flags/sm.png +0 -0
  249. data/app/assets/images/lit/famfamfam_flags/sn.png +0 -0
  250. data/app/assets/images/lit/famfamfam_flags/so.png +0 -0
  251. data/app/assets/images/lit/famfamfam_flags/sr.png +0 -0
  252. data/app/assets/images/lit/famfamfam_flags/st.png +0 -0
  253. data/app/assets/images/lit/famfamfam_flags/sv.png +0 -0
  254. data/app/assets/images/lit/famfamfam_flags/sy.png +0 -0
  255. data/app/assets/images/lit/famfamfam_flags/sz.png +0 -0
  256. data/app/assets/images/lit/famfamfam_flags/tc.png +0 -0
  257. data/app/assets/images/lit/famfamfam_flags/td.png +0 -0
  258. data/app/assets/images/lit/famfamfam_flags/tf.png +0 -0
  259. data/app/assets/images/lit/famfamfam_flags/tg.png +0 -0
  260. data/app/assets/images/lit/famfamfam_flags/th.png +0 -0
  261. data/app/assets/images/lit/famfamfam_flags/tj.png +0 -0
  262. data/app/assets/images/lit/famfamfam_flags/tk.png +0 -0
  263. data/app/assets/images/lit/famfamfam_flags/tl.png +0 -0
  264. data/app/assets/images/lit/famfamfam_flags/tm.png +0 -0
  265. data/app/assets/images/lit/famfamfam_flags/tn.png +0 -0
  266. data/app/assets/images/lit/famfamfam_flags/to.png +0 -0
  267. data/app/assets/images/lit/famfamfam_flags/tr.png +0 -0
  268. data/app/assets/images/lit/famfamfam_flags/tt.png +0 -0
  269. data/app/assets/images/lit/famfamfam_flags/tv.png +0 -0
  270. data/app/assets/images/lit/famfamfam_flags/tw.png +0 -0
  271. data/app/assets/images/lit/famfamfam_flags/tz.png +0 -0
  272. data/app/assets/images/lit/famfamfam_flags/ua.png +0 -0
  273. data/app/assets/images/lit/famfamfam_flags/ug.png +0 -0
  274. data/app/assets/images/lit/famfamfam_flags/um.png +0 -0
  275. data/app/assets/images/lit/famfamfam_flags/us.png +0 -0
  276. data/app/assets/images/lit/famfamfam_flags/uy.png +0 -0
  277. data/app/assets/images/lit/famfamfam_flags/uz.png +0 -0
  278. data/app/assets/images/lit/famfamfam_flags/va.png +0 -0
  279. data/app/assets/images/lit/famfamfam_flags/vc.png +0 -0
  280. data/app/assets/images/lit/famfamfam_flags/ve.png +0 -0
  281. data/app/assets/images/lit/famfamfam_flags/vg.png +0 -0
  282. data/app/assets/images/lit/famfamfam_flags/vi.png +0 -0
  283. data/app/assets/images/lit/famfamfam_flags/vn.png +0 -0
  284. data/app/assets/images/lit/famfamfam_flags/vu.png +0 -0
  285. data/app/assets/images/lit/famfamfam_flags/wales.png +0 -0
  286. data/app/assets/images/lit/famfamfam_flags/wf.png +0 -0
  287. data/app/assets/images/lit/famfamfam_flags/ws.png +0 -0
  288. data/app/assets/images/lit/famfamfam_flags/ye.png +0 -0
  289. data/app/assets/images/lit/famfamfam_flags/yt.png +0 -0
  290. data/app/assets/images/lit/famfamfam_flags/za.png +0 -0
  291. data/app/assets/images/lit/famfamfam_flags/zm.png +0 -0
  292. data/app/assets/images/lit/famfamfam_flags/zw.png +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8731e7911097d0e6c8b3cdbf164d5a4dfb7d9c45
4
- data.tar.gz: c478524af6694e7cf55272ae7d2f83381d05b161
2
+ SHA256:
3
+ metadata.gz: ecbd506c6be8279728e5da85a4857dd542c75cdc752efac9745dd7e2ba022a5c
4
+ data.tar.gz: 45bf91076203d8be22b2da854886657ddb85f07acbc42cd287b9246883e0955d
5
5
  SHA512:
6
- metadata.gz: b096959dfb69f64ff171173026d4c582042e8409593cfc76e522aee75ecf016ecfb13ca794e5d93588594a4428b50d30f55fd0dcd7b0b378c609efc25c4ce244
7
- data.tar.gz: 7171984114ea8cc6d546e5e1530cf89f6d5acb46e7b9a1fc8f38256dc4a74886ccbded8aaeb7a8729afd90dbf34e6a93e8fdd47b4747f81b02d083633abc66f0
6
+ metadata.gz: b78bb6b6ef52a2010d0725165a0e898d72dbf5fcf843b4ae756291f5648032e12ac1c6ded47a90418b258627c5ea1521e956dbd3e1387f428d623ec144a0c9cc
7
+ data.tar.gz: ce87f326e76dce205a987bbb1474a154406afd5fda42a9f3b92017cd8912f621a54ef36a16bd1f0861e6193341a0db24220341a8d1c5120cdfbbb3d2438473c5
data/README.md CHANGED
@@ -7,7 +7,7 @@ translating app by non-technicals.
7
7
 
8
8
  Highly inspired by Copycopter by thoughtbot.
9
9
 
10
- ![travis status](https://travis-ci.org/prograils/lit.svg)
10
+ [![travis status](https://travis-ci.org/prograils/lit.svg)](https://travis-ci.org/prograils/lit)
11
11
 
12
12
  ### Features
13
13
 
@@ -39,7 +39,7 @@ gem 'lit'
39
39
 
40
40
  3. run installation generator `bundle exec rails g lit:install`
41
41
  (for production/staging environment `redis` is suggested as key value engine. `hash` will not work in multi process environment)
42
-
42
+
43
43
  4. Add `config.i18n.available_locales = [...]` to `application.rb` - it's required to precompile appropriate language flags in lit backend.
44
44
 
45
45
  5. After doing above and restarting app, point your browser to `http://app/lit`
@@ -107,6 +107,86 @@ Keys marked as deleted (i.e. still existing but deleted from the Lit UI) are *no
107
107
 
108
108
  Deleted keys whose translations are encountered during import are restored automatically.
109
109
 
110
+ ### Cloud translation services
111
+
112
+ Lit can use external translation services such as [Google Cloud Translation API](https://cloud.google.com/translate/) and [Yandex.Translate API](https://translate.yandex.com/developers) to tentatively translate localizations to a given language.
113
+ Currently, Google and Yandex translation providers are supported, but extending it to any other translation provider of your choice is as easy as subclassing `Lit::CloudTranslation::Providers::Base`; see classes in `lib/lit/cloud_translation/providers` for reference.
114
+
115
+ #### Usage
116
+
117
+ Configure your translation provider using one of routines described below. When a translation provider is configured, each localization in Lit web UI will have a "Translate using _Provider Name_" button next to it, which by default translates to the localization's language from the localization currently saved for the app's `I18n.default_locale`.
118
+ Next to the button, there is a dropdown that allows translating from the key's localization in a language different than the default one.
119
+
120
+ #### Google Cloud Translation API
121
+
122
+ Insert this into your Lit initializer:
123
+ ```
124
+ require 'lit/cloud_translation/providers/google'
125
+
126
+ Lit::CloudTranslation.provider = Lit::CloudTranslation::Providers::Google
127
+ ```
128
+
129
+ ...and make sure you have this in your Gemfile:
130
+ ```
131
+ gem 'google-cloud-translate', '~> 1.2.4'
132
+ ```
133
+
134
+ To use translation via Google, you need to obtain a [service account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) containing all the credentials required by the API.
135
+
136
+ These credentials can be given in three ways:
137
+ * via a `.json` keyfile, the path to which should be stored in the `GOOGLE_TRANSLATE_API_KEYFILE` environment variable,
138
+ * programmatically, in the initializer - be sure to use secrets in all the sensitive fields so you don't expose private credentials in the code:
139
+ ```
140
+ Lit::CloudTranslation.configure do |config|
141
+ config.keyfile_hash = {
142
+ 'type' => 'service_account',
143
+ 'project_id' => 'foo',
144
+ 'private_key_id' => 'keyid',
145
+ ... # see Google docs link above for reference
146
+ }
147
+ end
148
+
149
+ # For example, for Rails 6, from encrypted credentials file (HashWithIndifferentAccess is used, because the keys in
150
+ the credentials.config could be strings or, as well, symbols):
151
+
152
+ Lit::CloudTranslation.configure do |config|
153
+ config.keyfile_hash = HashWithIndifferentAccess.new(Rails.application.credentials.config[:google_translate_api])
154
+ end
155
+ ```
156
+ * directly via `GOOGLE_TRANSLATE_API_<element>` environment variables, where e.g. the `GOOGLE_TRANSLATE_API_PROJECT_ID` variable corresponds to the `project_id` element of a JSON keyfile. Typically, only the following variables are mandatory:
157
+ * `GOOGLE_TRANSLATE_API_PROJECT_ID`
158
+ * `GOOGLE_TRANSLATE_API_PRIVATE_KEY` (make sure that it contains correct line breaks and markers of the private key's begin and end)
159
+ * `GOOGLE_TRANSLATE_API_CLIENT_EMAIL`
160
+
161
+ #### Yandex.Translate API
162
+
163
+ Insert this into your Lit initializer:
164
+ ```
165
+ require 'lit/cloud_translation/providers/yandex'
166
+
167
+ Lit::CloudTranslation.provider = Lit::CloudTranslation::Providers::Yandex
168
+ ```
169
+
170
+ To use Yandex translation, an [API key must be obtained](https://translate.yandex.com/developers/keys). Then, you can pass it to your application via the `YANDEX_TRANSLATE_API_KEY` environment variable.
171
+
172
+ The API key can also be set programmatically in your Lit initializer (again, be sure to use secrets if you choose to do so):
173
+ ```
174
+ Lit::CloudTranslation.configure do |config|
175
+ config.api_key = 'the_api_key'
176
+ end
177
+ ```
178
+
179
+ ### 0.3 -> 1.0 upgrade guide
180
+
181
+ Also applies to upgrading from `0.4.pre.alpha` versions.
182
+
183
+ 1. Specify `gem 'lit', '~> 1.0'` in your Gemfile and run `bundle update lit`.
184
+ 2. Run Lit migrations - `rails db:migrate`.
185
+ * __Caution:__ One of the new migrations adds a unique index in `lit_localizations` on `(localization_key_id, locale_id)`, which may cause constraint violations in some cases. If you encounter such errors during running this migration - in this case you'll need to enter Rails console and remove duplicates manually. The following query might be helpful to determine duplicate locale/localization key ID pairs:
186
+ ```
187
+ Lit::Localization.group(:locale_id, :localization_key_id).having('count(*) > 1').count
188
+ ```
189
+
110
190
  ### 0.2 -> 0.3 upgrade guide
111
191
 
112
192
  1. Specify exact lit version in your Gemfile: `gem 'lit', '~> 0.3.0'`
@@ -197,10 +277,14 @@ Lit.store_request_info = true
197
277
 
198
278
  ### Testing
199
279
 
200
- For local testing [Appraisal](https://github.com/thoughtbot/appraisal) gem comes into play, run tests via: `bundle exec appraisal rails-4.2 rake test`.
201
-
202
- Please remember to edit `test/dummy/config/database.yml` file
280
+ 1. `gem install bundler && bundle install` - ensure Bundler and all required gems are installed
281
+ 2. `bundle exec appraisal install` - install gems from appraisal's gemfiles
282
+ 3. `cp test/dummy/config/database.yml.sample test/dummy/config/database.yml` - move a database.yml in place (remember to fill your DB credentials in it)
283
+ 4. `RAILS_ENV=test bundle exec appraisal rails-5.2 rake db:setup` - setup lit DB (see test/config/database.yml); do it
284
+ only once, it does not matter which Rails version you use for `appraisal`
285
+ 5. `bundle exec appraisal rake` - run the tests!
203
286
 
204
287
  ### License
205
288
 
206
289
  Lit is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
290
+
data/Rakefile CHANGED
@@ -1,10 +1,7 @@
1
- #!/usr/bin/env rake
2
- require 'rubygems'
3
- begin
4
- require 'bundler/setup'
5
- rescue LoadError
6
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
- end
1
+ require "bundler/gem_tasks"
2
+
3
+ APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
4
+ load 'rails/tasks/engine.rake'
8
5
 
9
6
  begin
10
7
  require 'rdoc/task'
@@ -22,17 +19,14 @@ RDoc::Task.new(:rdoc) do |rdoc|
22
19
  rdoc.rdoc_files.include('lib/**/*.rb')
23
20
  end
24
21
 
25
- APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
26
- load 'rails/tasks/engine.rake'
27
-
28
- Bundler::GemHelper.install_tasks
29
-
30
- require 'rake/testtask'
31
-
22
+ require "rake/testtask"
32
23
  Rake::TestTask.new(:test) do |t|
33
24
  puts "Storage: #{ENV['LIT_STORAGE'] || 'redis'}"
34
- t.libs << 'lib'
35
25
  t.libs << 'test'
26
+ t.libs << 'lib'
36
27
  t.pattern = 'test/**/*_test.rb'
37
28
  t.verbose = false
38
29
  end
30
+
31
+ task :default => :test
32
+
@@ -0,0 +1,7 @@
1
+ /*!
2
+ * Bootstrap v3.0.3 (http://getbootstrap.com)
3
+ * Copyright 2013 Twitter, Inc.
4
+ * Licensed under http://www.apache.org/licenses/LICENSE-2.0
5
+ */
6
+
7
+ if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]'),b=!0;if(a.length){var c=this.$element.find("input");"radio"===c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?b=!1:a.find(".active").removeClass("active")),b&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}b&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.load(this.options.remote)};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show(),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focus",i="hover"==g?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show),void 0):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide),void 0):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d="function"==typeof this.options.placement?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m="body"==this.options.container?window.innerWidth:j.outerWidth(),n="body"==this.options.container?window.innerHeight:j.outerHeight(),o="body"==this.options.container?0:j.offset().left;d="bottom"==d&&g.top+g.height+i-l>n?"top":"top"==d&&g.top-l-i<0?"bottom":"right"==d&&g.right+h>m?"left":"left"==d&&g.left-h<o?"right":d,c.removeClass(k).addClass(d)}var p=this.getCalculatedOffset(d,g,h,i);this.applyPlacement(p,d),this.$element.trigger("shown.bs."+this.type)}},b.prototype.applyPlacement=function(a,b){var c,d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),a.top=a.top+g,a.left=a.left+h,d.offset(a).addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;if("top"==b&&j!=f&&(c=!0,a.top=a.top+f-j),/bottom|top/.test(b)){var k=0;a.left<0&&(k=-2*a.left,a.left=0,d.offset(a),i=d[0].offsetWidth,j=d[0].offsetHeight),this.replaceArrow(k-e+i,i,"left")}else this.replaceArrow(j-f,j,"top");c&&d.offset(a)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach()}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.$element.trigger("hidden.bs."+this.type),this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery);
@@ -22,12 +22,17 @@ module Lit
22
22
  private
23
23
 
24
24
  def fetch_localizations
25
+ scope = Localization.includes(
26
+ :locale,
27
+ :localization_key
28
+ )
29
+
25
30
  if params[:after].present?
26
31
  after_date = Time.parse("#{params[:after]} #{Time.zone.name}")
27
32
  .in_time_zone
28
- Localization.after(after_date).to_a
33
+ scope.after(after_date).to_a
29
34
  else
30
- Localization.all
35
+ scope.all
31
36
  end
32
37
  end
33
38
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lit
4
+ class CloudTranslationsController < ::Lit::ApplicationController
5
+ def show
6
+ params.delete(:from) if params[:from] == 'auto'
7
+ @target_localization = Localization.find(params[:localization_id])
8
+ @localization_key = @target_localization.localization_key
9
+ if params[:from]
10
+ @localization = @localization_key.localizations.joins(:locale)
11
+ .find_by!(lit_locales: { locale: params[:from] })
12
+ end
13
+ opts =
14
+ {
15
+ # if :from was auto, translate from the target localization's
16
+ # current text itself
17
+ text: (@localization || @target_localization).value,
18
+ from: params[:from],
19
+ to: @target_localization.locale.locale
20
+ }.compact
21
+ @translated_text = Lit::CloudTranslation.translate(opts)
22
+ rescue Lit::CloudTranslation::TranslationError => e
23
+ @error_message = "Translation failed. #{e.message}"
24
+ end
25
+ end
26
+ end
@@ -37,6 +37,10 @@ module Lit
37
37
  @scope.respond_to?(Kaminari.config.page_method_name)
38
38
  @scope = @scope.send(Kaminari.config.page_method_name, params[:page])
39
39
  end
40
+ if defined?(WillPaginate) &&
41
+ @scope.respond_to?(:paginate)
42
+ @scope = @scope.paginate(page: params[:page])
43
+ end
40
44
  get_localization_keys
41
45
  render action: :index
42
46
  end
@@ -88,6 +92,8 @@ module Lit
88
92
  end
89
93
  if defined?(Kaminari) and @scope.respond_to?(Kaminari.config.page_method_name)
90
94
  @localization_keys = @scope.send(Kaminari.config.page_method_name, params[:page])
95
+ elsif defined?(WillPaginate) and @scope.respond_to?(:paginate)
96
+ @localization_keys = @scope.paginate(page: params[:page])
91
97
  else
92
98
  @localization_keys = @scope
93
99
  end
@@ -20,7 +20,7 @@ module Lit
20
20
  # #after_update_operations. So it'll first set :is_changed to true
21
21
  # and then it will be properly read in the cache setting routine.
22
22
  @localization.transaction do
23
- after_update_operations if @localization.update_attributes(clear_params)
23
+ after_update_operations if @localization.update(clear_params)
24
24
  end
25
25
  respond_to do |f|
26
26
  f.js
@@ -48,7 +48,8 @@ module Lit
48
48
  end
49
49
 
50
50
  def find_localization
51
- @localization = @localization_key.localizations.find(params[:id])
51
+ @localization =
52
+ @localization_key.localizations.includes(:locale).find(params[:id])
52
53
  end
53
54
 
54
55
  def after_update_operations
@@ -40,7 +40,7 @@ module Lit
40
40
  end
41
41
 
42
42
  def update
43
- if @source.update_attributes(clear_params)
43
+ if @source.update(clear_params)
44
44
  redirect_to @source, notice: 'Source was successfully updated.'
45
45
  else
46
46
  render action: 'edit'
@@ -9,7 +9,7 @@ module Lit
9
9
  key = scope_key_by_partial(key)
10
10
  key = pluralized_key(key, count) if count
11
11
 
12
- content = super(key, options)
12
+ content = super(key, options.symbolize_keys)
13
13
  if !options[:skip_lit] && lit_authorized?
14
14
  content = get_translateable_span(key, content)
15
15
  end
@@ -9,8 +9,21 @@ module Lit
9
9
  escape_javascript val.to_s
10
10
  end
11
11
 
12
+ def locale_flag locale
13
+ locale = locale.to_s.upcase[0,2]
14
+ locale = case locale
15
+ when 'EN' then 'GB'
16
+ else locale
17
+ end
18
+ locale.tr('A-Z', "\u{1F1E6}-\u{1F1FF}")
19
+ end
20
+
12
21
  def allow_wysiwyg_editor?(key)
13
22
  Lit.all_translations_are_html_safe || key.to_s =~ /(\b|_|\.)html$/
14
23
  end
24
+
25
+ def available_locales_with_default_first
26
+ I18n.available_locales.sort_by { |l| l == I18n.default_locale ? 0 : 1 }
27
+ end
15
28
  end
16
29
  end
@@ -1,38 +1,54 @@
1
1
  class Lit::Base < ActiveRecord::Base
2
2
  self.abstract_class = true
3
3
 
4
- before_save :mark_for_retry_on_create, on: :create
5
- before_save :mark_for_retry_on_update, on: :update
4
+ before_save :mark_for_retry
6
5
 
7
6
  attr_accessor :retried_created, :retried_updated
8
7
 
9
- def mark_for_retry_on_create
8
+ def mark_for_retry
10
9
  @will_retry_create = true
11
10
  end
12
11
 
13
- def mark_for_retry_on_update
14
- @will_retry_update = true
12
+ after_rollback :retry_lit_model_save
13
+
14
+ def rolledback_after_insert?
15
+ persisted? && @was_saved_with_insert && @was_rolled_back
15
16
  end
16
17
 
17
- after_rollback :retry_lit_model_save
18
+ def rolledback_after_update?
19
+ persisted? && @was_saved_with_update && @was_rolled_back
20
+ end
18
21
 
19
22
  private
20
23
 
21
- def retry_lit_model_save
22
- retry_on_create if instance_variable_defined?(:@will_retry_create) && @will_retry_create
23
- retry_on_update if instance_variable_defined?(:@will_retry_update) && @will_retry_update
24
+ def create_or_update(*args, &block)
25
+ @was_saved_with_insert = true if new_record?
26
+ @was_saved_with_update = true if persisted?
27
+
28
+ super
24
29
  end
25
30
 
26
- def retry_on_create
27
- return if self.retried_created
28
- self.retried_created = true
29
- self.class.create! attributes.merge(retried_created: true)
31
+ def retry_lit_model_save
32
+ return if @was_rolled_back
33
+ @was_rolled_back = true
34
+ do_retry if instance_variable_defined?(:@will_retry_create) && @will_retry_create
30
35
  end
31
36
 
32
- def retry_on_update
33
- return if self.retried_updated
34
- self.retried_updated = true
35
- update! attributes.merge(retried_updated: true)
37
+ def do_retry
38
+ if !retried_created
39
+ self.retried_created = true
40
+ if rolledback_after_insert?
41
+ self.class.create! attributes.merge(retried_created: true)
42
+ end
43
+ elsif !retried_updated
44
+ # Why elsif and not just if? Because if a record object was first saved
45
+ # with INSERT and then with UPDATE (still being the same Ruby object),
46
+ # it makes no sense to retry both create and upadte. Let's only retry create.
47
+ self.retried_updated = true
48
+ if rolledback_after_update?
49
+ update_columns(attributes)
50
+ end
51
+ end
36
52
  end
37
53
 
38
54
  end
@@ -59,14 +59,14 @@ module Lit
59
59
  end
60
60
 
61
61
  def update_existing_localization_data
62
- localization.update_attributes!(
62
+ localization.update!(
63
63
  translated_value: translated_value,
64
64
  is_changed: true
65
65
  )
66
66
  end
67
67
 
68
68
  def update_existing_localization_key_data
69
- localization_key.update_attributes!(
69
+ localization_key.update!(
70
70
  is_deleted: localization_key_is_deleted
71
71
  )
72
72
  end
@@ -11,6 +11,7 @@ class RemoteInteractorService
11
11
  rescue => e
12
12
  return unless defined?(Rails)
13
13
  ::Rails.logger.error { "Lit remote error: #{e}" }
14
+ nil # Return nil to be consistent with checks for .nil? otherwise returns True
14
15
  end
15
16
 
16
17
  private
@@ -10,7 +10,6 @@
10
10
  <%= stylesheet_link_tag '//netdna.bootstrapcdn.com/bootswatch/3.0.3/yeti/bootstrap.min.css', media: 'all' %>
11
11
  <%= stylesheet_link_tag 'lit/application', media: 'all' %>
12
12
  <%= javascript_include_tag 'lit/application' %>
13
- <%= javascript_include_tag '//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js' %>
14
13
  <%= csrf_meta_tags %>
15
14
  </head>
16
15
  <body class="<%= params[:controller] %>">
@@ -0,0 +1,14 @@
1
+ <% if @translated_text.is_a?(String) %>
2
+ $('.localization_row[data-id="<%= @target_localization.id %>"] textarea').val("<%= j @translated_text %>");
3
+ <% elsif @translated_text.is_a?(Array) %>
4
+ $inputs = $('.localization_row[data-id="<%= @target_localization.id %>"] input[type=text]');
5
+ var translated_elements = JSON.parse("<%= j @translated_text.to_json.html_safe %>");
6
+ for (i in $inputs.toArray()) {
7
+ $input = $($inputs[i]);
8
+ $input.val(translated_elements[i]);
9
+ }
10
+ <% elsif @error_message.present? %>
11
+ alert("<%= j @error_message %>")
12
+ <% else %>
13
+ alert("An unknown error has occurred while translating.")
14
+ <% end %>
@@ -1,5 +1,5 @@
1
1
  <strong>All localization keys</strong> <%= Lit::LocalizationKey.active.count(:id) %><br/>
2
2
  <% @locales.each do |l| %>
3
- <strong><%= image_tag "lit/famfamfam_flags/#{l.locale[0,2]}.png" %> <%= I18n.t("lit.locale_to_languages.#{l.locale}", :default=>l.locale) %>:</strong> <span title="<%= "#{l.changed_localizations_count}/#{l.all_localizations_count}" %>"><%= l.translated_percentage %>%</span><br/>
3
+ <strong><%= EmojiFlag.new(l.locale) %> <%= I18n.t("lit.locale_to_languages.#{l.locale}", :default=>l.locale) %>:</strong> <span title="<%= "#{l.changed_localizations_count}/#{l.all_localizations_count}" %>"><%= l.translated_percentage %>%</span><br/>
4
4
  <% end %>
5
5
 
@@ -25,7 +25,7 @@
25
25
  <% @incomming_localizations.each do |il| %>
26
26
  <tr data-id="<%= il.id %>">
27
27
  <td colspan="3">
28
- <%= image_tag "lit/famfamfam_flags/#{il.locale_str[0,2]}.png" %>
28
+ <%= image_tag EmojiFlag.new(il.locale_str) %>
29
29
  <strong><%= il.full_key %></strong>
30
30
  </td>
31
31
  </tr>