radiant-globalize2-extension 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (318) hide show
  1. data/Rakefile +136 -0
  2. data/app/views/admin/shared/_change_locale.html.haml +22 -0
  3. data/app/views/admin/shared/_change_locale_admin.html.haml +7 -0
  4. data/app/views/admin/shared/_globalize_td.html.haml +4 -0
  5. data/app/views/admin/shared/_globalize_th.html.haml +2 -0
  6. data/config/routes.rb +4 -0
  7. data/cucumber.yml +1 -0
  8. data/db/migrate/20090728084238_create_translation_tables.rb +23 -0
  9. data/db/migrate/20090728114627_populate_translations.rb +21 -0
  10. data/db/migrate/20090729085422_remove_translated_attributes.rb +16 -0
  11. data/features/globalize_layouts.feature +19 -0
  12. data/features/globalize_pages.feature +58 -0
  13. data/features/globalize_snippets.feature +19 -0
  14. data/features/step_definitions/admin_steps.rb +58 -0
  15. data/features/step_definitions/webrat_steps.rb +119 -0
  16. data/features/support/env.rb +30 -0
  17. data/features/support/paths.rb +26 -0
  18. data/globalize2_extension.rb +93 -0
  19. data/lib/globalize2/compatibility/archive/archive_page_extensions.rb +21 -0
  20. data/lib/globalize2/compatibility/copy_move/copy_move_model_extensions.rb +22 -0
  21. data/lib/globalize2/compatibility/paginate/globalize_tags.rb +19 -0
  22. data/lib/globalize2/compatibility/paginate/page_extensions.rb +9 -0
  23. data/lib/globalize2/compatibility/vhost/page_extensions.rb +9 -0
  24. data/lib/globalize2/form_builder_extensions.rb +21 -0
  25. data/lib/globalize2/globalize_tags.rb +203 -0
  26. data/lib/globalize2/globalized_fields_controller_extension.rb +22 -0
  27. data/lib/globalize2/page_extensions.rb +88 -0
  28. data/lib/globalize2/page_part_extensions.rb +21 -0
  29. data/lib/globalize2/pages_controller_extensions.rb +9 -0
  30. data/lib/globalize2/site_controller_extensions.rb +24 -0
  31. data/lib/tasks/globalize2_extension_tasks.rake +28 -0
  32. data/public/images/admin/ad.gif +0 -0
  33. data/public/images/admin/ae.gif +0 -0
  34. data/public/images/admin/af.gif +0 -0
  35. data/public/images/admin/ag.gif +0 -0
  36. data/public/images/admin/ai.gif +0 -0
  37. data/public/images/admin/al.gif +0 -0
  38. data/public/images/admin/am.gif +0 -0
  39. data/public/images/admin/an.gif +0 -0
  40. data/public/images/admin/ao.gif +0 -0
  41. data/public/images/admin/ar.gif +0 -0
  42. data/public/images/admin/as.gif +0 -0
  43. data/public/images/admin/at.gif +0 -0
  44. data/public/images/admin/au.gif +0 -0
  45. data/public/images/admin/aw.gif +0 -0
  46. data/public/images/admin/ax.gif +0 -0
  47. data/public/images/admin/az.gif +0 -0
  48. data/public/images/admin/ba.gif +0 -0
  49. data/public/images/admin/bb.gif +0 -0
  50. data/public/images/admin/bd.gif +0 -0
  51. data/public/images/admin/be.gif +0 -0
  52. data/public/images/admin/bf.gif +0 -0
  53. data/public/images/admin/bg.gif +0 -0
  54. data/public/images/admin/bh.gif +0 -0
  55. data/public/images/admin/bi.gif +0 -0
  56. data/public/images/admin/bj.gif +0 -0
  57. data/public/images/admin/bm.gif +0 -0
  58. data/public/images/admin/bn.gif +0 -0
  59. data/public/images/admin/bo.gif +0 -0
  60. data/public/images/admin/br.gif +0 -0
  61. data/public/images/admin/bs.gif +0 -0
  62. data/public/images/admin/bt.gif +0 -0
  63. data/public/images/admin/bv.gif +0 -0
  64. data/public/images/admin/bw.gif +0 -0
  65. data/public/images/admin/by.gif +0 -0
  66. data/public/images/admin/bz.gif +0 -0
  67. data/public/images/admin/ca.gif +0 -0
  68. data/public/images/admin/catalonia.gif +0 -0
  69. data/public/images/admin/cc.gif +0 -0
  70. data/public/images/admin/cd.gif +0 -0
  71. data/public/images/admin/cf.gif +0 -0
  72. data/public/images/admin/cg.gif +0 -0
  73. data/public/images/admin/ch.gif +0 -0
  74. data/public/images/admin/ci.gif +0 -0
  75. data/public/images/admin/ck.gif +0 -0
  76. data/public/images/admin/cl.gif +0 -0
  77. data/public/images/admin/cm.gif +0 -0
  78. data/public/images/admin/cn.gif +0 -0
  79. data/public/images/admin/co.gif +0 -0
  80. data/public/images/admin/cr.gif +0 -0
  81. data/public/images/admin/cs.gif +0 -0
  82. data/public/images/admin/cu.gif +0 -0
  83. data/public/images/admin/cv.gif +0 -0
  84. data/public/images/admin/cx.gif +0 -0
  85. data/public/images/admin/cy.gif +0 -0
  86. data/public/images/admin/cz.gif +0 -0
  87. data/public/images/admin/de.gif +0 -0
  88. data/public/images/admin/dj.gif +0 -0
  89. data/public/images/admin/dk.gif +0 -0
  90. data/public/images/admin/dm.gif +0 -0
  91. data/public/images/admin/do.gif +0 -0
  92. data/public/images/admin/dz.gif +0 -0
  93. data/public/images/admin/ec.gif +0 -0
  94. data/public/images/admin/ee.gif +0 -0
  95. data/public/images/admin/eg.gif +0 -0
  96. data/public/images/admin/eh.gif +0 -0
  97. data/public/images/admin/en.gif +0 -0
  98. data/public/images/admin/england.gif +0 -0
  99. data/public/images/admin/er.gif +0 -0
  100. data/public/images/admin/es.gif +0 -0
  101. data/public/images/admin/et.gif +0 -0
  102. data/public/images/admin/europeanunion.gif +0 -0
  103. data/public/images/admin/fam.gif +0 -0
  104. data/public/images/admin/fi.gif +0 -0
  105. data/public/images/admin/fj.gif +0 -0
  106. data/public/images/admin/fk.gif +0 -0
  107. data/public/images/admin/fm.gif +0 -0
  108. data/public/images/admin/fo.gif +0 -0
  109. data/public/images/admin/fr.gif +0 -0
  110. data/public/images/admin/ga.gif +0 -0
  111. data/public/images/admin/gb.gif +0 -0
  112. data/public/images/admin/gd.gif +0 -0
  113. data/public/images/admin/ge.gif +0 -0
  114. data/public/images/admin/gf.gif +0 -0
  115. data/public/images/admin/gh.gif +0 -0
  116. data/public/images/admin/gi.gif +0 -0
  117. data/public/images/admin/gl.gif +0 -0
  118. data/public/images/admin/gm.gif +0 -0
  119. data/public/images/admin/gn.gif +0 -0
  120. data/public/images/admin/gp.gif +0 -0
  121. data/public/images/admin/gq.gif +0 -0
  122. data/public/images/admin/gr.gif +0 -0
  123. data/public/images/admin/gs.gif +0 -0
  124. data/public/images/admin/gt.gif +0 -0
  125. data/public/images/admin/gu.gif +0 -0
  126. data/public/images/admin/gw.gif +0 -0
  127. data/public/images/admin/gy.gif +0 -0
  128. data/public/images/admin/hk.gif +0 -0
  129. data/public/images/admin/hm.gif +0 -0
  130. data/public/images/admin/hn.gif +0 -0
  131. data/public/images/admin/hr.gif +0 -0
  132. data/public/images/admin/ht.gif +0 -0
  133. data/public/images/admin/hu.gif +0 -0
  134. data/public/images/admin/id.gif +0 -0
  135. data/public/images/admin/ie.gif +0 -0
  136. data/public/images/admin/il.gif +0 -0
  137. data/public/images/admin/in.gif +0 -0
  138. data/public/images/admin/io.gif +0 -0
  139. data/public/images/admin/iq.gif +0 -0
  140. data/public/images/admin/ir.gif +0 -0
  141. data/public/images/admin/is.gif +0 -0
  142. data/public/images/admin/it.gif +0 -0
  143. data/public/images/admin/jm.gif +0 -0
  144. data/public/images/admin/jo.gif +0 -0
  145. data/public/images/admin/jp.gif +0 -0
  146. data/public/images/admin/ke.gif +0 -0
  147. data/public/images/admin/kg.gif +0 -0
  148. data/public/images/admin/kh.gif +0 -0
  149. data/public/images/admin/ki.gif +0 -0
  150. data/public/images/admin/km.gif +0 -0
  151. data/public/images/admin/kn.gif +0 -0
  152. data/public/images/admin/kp.gif +0 -0
  153. data/public/images/admin/kr.gif +0 -0
  154. data/public/images/admin/kw.gif +0 -0
  155. data/public/images/admin/ky.gif +0 -0
  156. data/public/images/admin/kz.gif +0 -0
  157. data/public/images/admin/la.gif +0 -0
  158. data/public/images/admin/lb.gif +0 -0
  159. data/public/images/admin/lc.gif +0 -0
  160. data/public/images/admin/li.gif +0 -0
  161. data/public/images/admin/lk.gif +0 -0
  162. data/public/images/admin/lr.gif +0 -0
  163. data/public/images/admin/ls.gif +0 -0
  164. data/public/images/admin/lt.gif +0 -0
  165. data/public/images/admin/lu.gif +0 -0
  166. data/public/images/admin/lv.gif +0 -0
  167. data/public/images/admin/ly.gif +0 -0
  168. data/public/images/admin/ma.gif +0 -0
  169. data/public/images/admin/mc.gif +0 -0
  170. data/public/images/admin/md.gif +0 -0
  171. data/public/images/admin/me.gif +0 -0
  172. data/public/images/admin/mg.gif +0 -0
  173. data/public/images/admin/mh.gif +0 -0
  174. data/public/images/admin/mk.gif +0 -0
  175. data/public/images/admin/ml.gif +0 -0
  176. data/public/images/admin/mm.gif +0 -0
  177. data/public/images/admin/mn.gif +0 -0
  178. data/public/images/admin/mo.gif +0 -0
  179. data/public/images/admin/mp.gif +0 -0
  180. data/public/images/admin/mq.gif +0 -0
  181. data/public/images/admin/mr.gif +0 -0
  182. data/public/images/admin/ms.gif +0 -0
  183. data/public/images/admin/mt.gif +0 -0
  184. data/public/images/admin/mu.gif +0 -0
  185. data/public/images/admin/mv.gif +0 -0
  186. data/public/images/admin/mw.gif +0 -0
  187. data/public/images/admin/mx.gif +0 -0
  188. data/public/images/admin/my.gif +0 -0
  189. data/public/images/admin/mz.gif +0 -0
  190. data/public/images/admin/na.gif +0 -0
  191. data/public/images/admin/nc.gif +0 -0
  192. data/public/images/admin/ne.gif +0 -0
  193. data/public/images/admin/nf.gif +0 -0
  194. data/public/images/admin/ng.gif +0 -0
  195. data/public/images/admin/ni.gif +0 -0
  196. data/public/images/admin/nl.gif +0 -0
  197. data/public/images/admin/no.gif +0 -0
  198. data/public/images/admin/np.gif +0 -0
  199. data/public/images/admin/nr.gif +0 -0
  200. data/public/images/admin/nu.gif +0 -0
  201. data/public/images/admin/nz.gif +0 -0
  202. data/public/images/admin/om.gif +0 -0
  203. data/public/images/admin/pa.gif +0 -0
  204. data/public/images/admin/pe.gif +0 -0
  205. data/public/images/admin/pf.gif +0 -0
  206. data/public/images/admin/pg.gif +0 -0
  207. data/public/images/admin/ph.gif +0 -0
  208. data/public/images/admin/pk.gif +0 -0
  209. data/public/images/admin/pl.gif +0 -0
  210. data/public/images/admin/pm.gif +0 -0
  211. data/public/images/admin/pn.gif +0 -0
  212. data/public/images/admin/pr.gif +0 -0
  213. data/public/images/admin/ps.gif +0 -0
  214. data/public/images/admin/pt.gif +0 -0
  215. data/public/images/admin/pw.gif +0 -0
  216. data/public/images/admin/py.gif +0 -0
  217. data/public/images/admin/qa.gif +0 -0
  218. data/public/images/admin/re.gif +0 -0
  219. data/public/images/admin/ro.gif +0 -0
  220. data/public/images/admin/rs.gif +0 -0
  221. data/public/images/admin/ru.gif +0 -0
  222. data/public/images/admin/rw.gif +0 -0
  223. data/public/images/admin/sa.gif +0 -0
  224. data/public/images/admin/sb.gif +0 -0
  225. data/public/images/admin/sc.gif +0 -0
  226. data/public/images/admin/scotland.gif +0 -0
  227. data/public/images/admin/sd.gif +0 -0
  228. data/public/images/admin/se.gif +0 -0
  229. data/public/images/admin/sg.gif +0 -0
  230. data/public/images/admin/sh.gif +0 -0
  231. data/public/images/admin/si.gif +0 -0
  232. data/public/images/admin/sj.gif +0 -0
  233. data/public/images/admin/sk.gif +0 -0
  234. data/public/images/admin/sl.gif +0 -0
  235. data/public/images/admin/sm.gif +0 -0
  236. data/public/images/admin/sn.gif +0 -0
  237. data/public/images/admin/so.gif +0 -0
  238. data/public/images/admin/sr.gif +0 -0
  239. data/public/images/admin/st.gif +0 -0
  240. data/public/images/admin/sv.gif +0 -0
  241. data/public/images/admin/sy.gif +0 -0
  242. data/public/images/admin/sz.gif +0 -0
  243. data/public/images/admin/tc.gif +0 -0
  244. data/public/images/admin/td.gif +0 -0
  245. data/public/images/admin/tf.gif +0 -0
  246. data/public/images/admin/tg.gif +0 -0
  247. data/public/images/admin/th.gif +0 -0
  248. data/public/images/admin/tj.gif +0 -0
  249. data/public/images/admin/tk.gif +0 -0
  250. data/public/images/admin/tl.gif +0 -0
  251. data/public/images/admin/tm.gif +0 -0
  252. data/public/images/admin/tn.gif +0 -0
  253. data/public/images/admin/to.gif +0 -0
  254. data/public/images/admin/tr.gif +0 -0
  255. data/public/images/admin/tt.gif +0 -0
  256. data/public/images/admin/tv.gif +0 -0
  257. data/public/images/admin/tw.gif +0 -0
  258. data/public/images/admin/tz.gif +0 -0
  259. data/public/images/admin/ua.gif +0 -0
  260. data/public/images/admin/ug.gif +0 -0
  261. data/public/images/admin/um.gif +0 -0
  262. data/public/images/admin/us.gif +0 -0
  263. data/public/images/admin/uy.gif +0 -0
  264. data/public/images/admin/uz.gif +0 -0
  265. data/public/images/admin/va.gif +0 -0
  266. data/public/images/admin/vc.gif +0 -0
  267. data/public/images/admin/ve.gif +0 -0
  268. data/public/images/admin/vg.gif +0 -0
  269. data/public/images/admin/vi.gif +0 -0
  270. data/public/images/admin/vn.gif +0 -0
  271. data/public/images/admin/vu.gif +0 -0
  272. data/public/images/admin/wales.gif +0 -0
  273. data/public/images/admin/wf.gif +0 -0
  274. data/public/images/admin/ws.gif +0 -0
  275. data/public/images/admin/ye.gif +0 -0
  276. data/public/images/admin/yt.gif +0 -0
  277. data/public/images/admin/za.gif +0 -0
  278. data/public/images/admin/zm.gif +0 -0
  279. data/public/images/admin/zw.gif +0 -0
  280. data/public/stylesheets/sass/admin/globalize2.sass +59 -0
  281. data/readme.md +159 -0
  282. data/spec/controllers/admin/pages_controller_spec.rb +22 -0
  283. data/spec/controllers/site_controller_spec.rb +40 -0
  284. data/spec/factories.rb +39 -0
  285. data/spec/models/globalize_tags_spec.rb +155 -0
  286. data/spec/models/page_spec.rb +91 -0
  287. data/spec/spec.opts +6 -0
  288. data/spec/spec_helper.rb +34 -0
  289. data/vendor/plugins/globalize2/.gitignore +5 -0
  290. data/vendor/plugins/globalize2/LICENSE +21 -0
  291. data/vendor/plugins/globalize2/README.textile +86 -0
  292. data/vendor/plugins/globalize2/Rakefile +39 -0
  293. data/vendor/plugins/globalize2/VERSION +1 -0
  294. data/vendor/plugins/globalize2/generators/db_backend.rb +0 -0
  295. data/vendor/plugins/globalize2/generators/templates/db_backend_migration.rb +25 -0
  296. data/vendor/plugins/globalize2/globalize2.gemspec +81 -0
  297. data/vendor/plugins/globalize2/init.rb +1 -0
  298. data/vendor/plugins/globalize2/lib/globalize.rb +15 -0
  299. data/vendor/plugins/globalize2/lib/globalize/active_record.rb +215 -0
  300. data/vendor/plugins/globalize2/lib/globalize/active_record/adapter.rb +80 -0
  301. data/vendor/plugins/globalize2/lib/globalize/active_record/attributes.rb +25 -0
  302. data/vendor/plugins/globalize2/lib/globalize/active_record/migration.rb +44 -0
  303. data/vendor/plugins/globalize2/lib/i18n/missing_translations_log_handler.rb +41 -0
  304. data/vendor/plugins/globalize2/lib/i18n/missing_translations_raise_handler.rb +25 -0
  305. data/vendor/plugins/globalize2/test/active_record/fallbacks_test.rb +102 -0
  306. data/vendor/plugins/globalize2/test/active_record/migration_test.rb +118 -0
  307. data/vendor/plugins/globalize2/test/active_record/sti_translated_test.rb +61 -0
  308. data/vendor/plugins/globalize2/test/active_record/translates_test.rb +96 -0
  309. data/vendor/plugins/globalize2/test/active_record/translation_class_test.rb +30 -0
  310. data/vendor/plugins/globalize2/test/active_record/validation_tests.rb +75 -0
  311. data/vendor/plugins/globalize2/test/active_record_test.rb +467 -0
  312. data/vendor/plugins/globalize2/test/all.rb +2 -0
  313. data/vendor/plugins/globalize2/test/data/models.rb +62 -0
  314. data/vendor/plugins/globalize2/test/data/no_globalize_schema.rb +11 -0
  315. data/vendor/plugins/globalize2/test/data/schema.rb +55 -0
  316. data/vendor/plugins/globalize2/test/i18n/missing_translations_test.rb +36 -0
  317. data/vendor/plugins/globalize2/test/test_helper.rb +76 -0
  318. metadata +409 -0
@@ -0,0 +1,25 @@
1
+ # Helper class for storing values per locale. Used by Globalize::Adapter
2
+ # to stash and cache attribute values.
3
+ module Globalize
4
+ module ActiveRecord
5
+ class Attributes < Hash
6
+ def [](locale)
7
+ locale = locale.to_sym
8
+ self[locale] = {} unless has_key?(locale)
9
+ self.fetch(locale)
10
+ end
11
+
12
+ def contains?(locale, attr_name)
13
+ self[locale].has_key?(attr_name)
14
+ end
15
+
16
+ def read(locale, attr_name)
17
+ self[locale][attr_name]
18
+ end
19
+
20
+ def write(locale, attr_name, value)
21
+ self[locale][attr_name] = value
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,44 @@
1
+ module Globalize
2
+ module ActiveRecord
3
+ module Migration
4
+ def create_translation_table!(fields)
5
+ translated_attribute_names.each do |f|
6
+ raise MigrationMissingTranslatedField, "Missing translated field #{f}" unless fields[f]
7
+ end
8
+
9
+ fields.each do |name, type|
10
+ if translated_attribute_names.include?(name) && ![:string, :text].include?(type)
11
+ raise BadMigrationFieldType, "Bad field type for #{name}, should be :string or :text"
12
+ end
13
+ end
14
+
15
+ self.connection.create_table(translation_table_name) do |t|
16
+ t.references table_name.sub(/^#{table_name_prefix}/, "").singularize
17
+ t.string :locale
18
+ fields.each do |name, type|
19
+ t.column name, type
20
+ end
21
+ t.timestamps
22
+ end
23
+
24
+ self.connection.add_index(
25
+ translation_table_name,
26
+ "#{table_name.sub(/^#{table_name_prefix}/, "").singularize}_id",
27
+ :name => translation_index_name
28
+ )
29
+ end
30
+
31
+ def translation_index_name
32
+ require 'digest/sha1'
33
+ # FIXME what's the max size of an index name?
34
+ index_name = "index_#{translation_table_name}_on_#{self.table_name.singularize}_id"
35
+ index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}"
36
+ end
37
+
38
+ def drop_translation_table!
39
+ self.connection.remove_index(translation_table_name, :name => translation_index_name) rescue nil
40
+ self.connection.drop_table(translation_table_name)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,41 @@
1
+ # A simple exception handler that behaves like the default exception handler
2
+ # but additionally logs missing translations to a given log.
3
+ #
4
+ # Useful for identifying missing translations during testing.
5
+ #
6
+ # E.g.
7
+ #
8
+ # require 'globalize/i18n/missing_translations_log_handler'
9
+ # I18n.missing_translations_logger = RAILS_DEFAULT_LOGGER
10
+ # I18n.exception_handler = :missing_translations_log_handler
11
+ #
12
+ # To set up a different log file:
13
+ #
14
+ # logger = Logger.new("#{RAILS_ROOT}/log/missing_translations.log")
15
+ # I18n.missing_translations_logger = logger
16
+
17
+ module I18n
18
+ @@missing_translations_logger = nil
19
+
20
+ class << self
21
+ def missing_translations_logger
22
+ @@missing_translations_logger ||= begin
23
+ require 'logger' unless defined?(Logger)
24
+ Logger.new(STDOUT)
25
+ end
26
+ end
27
+
28
+ def missing_translations_logger=(logger)
29
+ @@missing_translations_logger = logger
30
+ end
31
+
32
+ def missing_translations_log_handler(exception, locale, key, options)
33
+ if MissingTranslationData === exception
34
+ missing_translations_logger.warn(exception.message)
35
+ return exception.message
36
+ else
37
+ raise exception
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,25 @@
1
+ # A simple exception handler that behaves like the default exception handler
2
+ # but also raises on missing translations.
3
+ #
4
+ # Useful for identifying missing translations during testing.
5
+ #
6
+ # E.g.
7
+ #
8
+ # require 'globalize/i18n/missing_translations_raise_handler'
9
+ # I18n.exception_handler = :missing_translations_raise_handler
10
+ module I18n
11
+ class << self
12
+ def missing_translations_raise_handler(exception, locale, key, options)
13
+ raise exception
14
+ end
15
+ end
16
+ end
17
+
18
+ I18n.exception_handler = :missing_translations_raise_handler
19
+
20
+ ActionView::Helpers::TranslationHelper.module_eval do
21
+ def translate(key, options = {})
22
+ I18n.translate(key, options)
23
+ end
24
+ alias :t :translate
25
+ end
@@ -0,0 +1,102 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../data/models')
3
+
4
+ if I18n.respond_to?(:fallbacks)
5
+ class TranslatedTest < ActiveSupport::TestCase
6
+ def setup
7
+ I18n.locale = :'en-US'
8
+ I18n.fallbacks.clear
9
+ reset_db!
10
+ ActiveRecord::Base.locale = nil
11
+ end
12
+
13
+ def teardown
14
+ I18n.fallbacks.clear
15
+ end
16
+
17
+ test "keeping one field in new locale when other field is changed" do
18
+ I18n.fallbacks.map 'de-DE' => [ 'en-US' ]
19
+ post = Post.create :subject => 'foo'
20
+ I18n.locale = 'de-DE'
21
+ post.content = 'bar'
22
+ assert_equal 'foo', post.subject
23
+ end
24
+
25
+ test "modifying non-required field in a new locale" do
26
+ I18n.fallbacks.map 'de-DE' => [ 'en-US' ]
27
+ post = Post.create :subject => 'foo'
28
+ I18n.locale = 'de-DE'
29
+ post.content = 'bar'
30
+ assert post.save
31
+ end
32
+
33
+ test "resolves a simple fallback" do
34
+ I18n.locale = 'de-DE'
35
+ post = Post.create :subject => 'foo'
36
+ I18n.locale = 'de'
37
+ post.subject = 'baz'
38
+ post.content = 'bar'
39
+ post.save
40
+ I18n.locale = 'de-DE'
41
+ assert_equal 'foo', post.subject
42
+ assert_equal 'bar', post.content
43
+ end
44
+
45
+ test "resolves a simple fallback without reloading" do
46
+ I18n.locale = 'de-DE'
47
+ post = Post.new :subject => 'foo'
48
+ I18n.locale = 'de'
49
+ post.subject = 'baz'
50
+ post.content = 'bar'
51
+ I18n.locale = 'de-DE'
52
+ assert_equal 'foo', post.subject
53
+ assert_equal 'bar', post.content
54
+ end
55
+
56
+ test "resolves a complex fallback without reloading" do
57
+ I18n.fallbacks.map 'de' => %w(en he)
58
+ I18n.locale = 'de'
59
+ post = Post.new
60
+ I18n.locale = 'en'
61
+ post.subject = 'foo'
62
+ I18n.locale = 'he'
63
+ post.subject = 'baz'
64
+ post.content = 'bar'
65
+ I18n.locale = 'de'
66
+ assert_equal 'foo', post.subject
67
+ assert_equal 'bar', post.content
68
+ end
69
+
70
+ test 'fallbacks with lots of locale switching' do
71
+ I18n.fallbacks.map :'de-DE' => [ :'en-US' ]
72
+ post = Post.create :subject => 'foo'
73
+
74
+ I18n.locale = :'de-DE'
75
+ assert_equal 'foo', post.subject
76
+
77
+ I18n.locale = :'en-US'
78
+ post.update_attribute :subject, 'bar'
79
+
80
+ I18n.locale = :'de-DE'
81
+ assert_equal 'bar', post.subject
82
+ end
83
+
84
+ test 'fallbacks with lots of locale switching' do
85
+ I18n.fallbacks.map :'de-DE' => [ :'en-US' ]
86
+ child = Child.create :content => 'foo'
87
+
88
+ I18n.locale = :'de-DE'
89
+ assert_equal 'foo', child.content
90
+
91
+ I18n.locale = :'en-US'
92
+ child.update_attribute :content, 'bar'
93
+
94
+ I18n.locale = :'de-DE'
95
+ assert_equal 'bar', child.content
96
+ end
97
+ end
98
+ end
99
+
100
+ # TODO should validate_presence_of take fallbacks into account? maybe we need
101
+ # an extra validation call, or more options for validate_presence_of.
102
+
@@ -0,0 +1,118 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../data/models')
3
+
4
+ class MigrationTest < ActiveSupport::TestCase
5
+ def setup
6
+ reset_db!
7
+ Post.drop_translation_table!
8
+ end
9
+
10
+ test 'globalize table added' do
11
+ assert !Post.connection.table_exists?(:post_translations)
12
+ assert !Post.connection.index_exists?(:post_translations, :post_id)
13
+
14
+ Post.create_translation_table!(:subject => :string, :content => :text)
15
+ assert Post.connection.table_exists?(:post_translations)
16
+ assert Post.connection.index_exists?(:post_translations, :post_id)
17
+
18
+ columns = Post.connection.columns(:post_translations)
19
+ assert locale = columns.detect { |c| c.name == 'locale' }
20
+ assert_equal :string, locale.type
21
+ assert subject = columns.detect { |c| c.name == 'subject' }
22
+ assert_equal :string, subject.type
23
+ assert content = columns.detect { |c| c.name == 'content' }
24
+ assert_equal :text, content.type
25
+ assert post_id = columns.detect { |c| c.name == 'post_id' }
26
+ assert_equal :integer, post_id.type
27
+ assert created_at = columns.detect { |c| c.name == 'created_at' }
28
+ assert_equal :datetime, created_at.type
29
+ assert updated_at = columns.detect { |c| c.name == 'updated_at' }
30
+ assert_equal :datetime, updated_at.type
31
+ end
32
+
33
+ test 'globalize table dropped' do
34
+ assert !Post.connection.table_exists?( :post_translations )
35
+ assert !Post.connection.index_exists?( :post_translations, :post_id )
36
+ Post.create_translation_table! :subject => :string, :content => :text
37
+ assert Post.connection.table_exists?( :post_translations )
38
+ assert Post.connection.index_exists?( :post_translations, :post_id )
39
+ Post.drop_translation_table!
40
+ assert !Post.connection.table_exists?( :post_translations )
41
+ assert !Post.connection.index_exists?( :post_translations, :post_id )
42
+ end
43
+
44
+ test 'exception on missing field inputs' do
45
+ assert_raise Globalize::MigrationMissingTranslatedField do
46
+ Post.create_translation_table! :content => :text
47
+ end
48
+ end
49
+
50
+ test 'exception on bad input type' do
51
+ assert_raise Globalize::BadMigrationFieldType do
52
+ Post.create_translation_table! :subject => :string, :content => :integer
53
+ end
54
+ end
55
+
56
+ test "exception on bad input type isn't raised for untranslated fields" do
57
+ assert_nothing_raised do
58
+ Post.create_translation_table! :subject => :string, :content => :string, :views_count => :integer
59
+ end
60
+ end
61
+
62
+ test 'create_translation_table! should not be called on non-translated models' do
63
+ assert_raise NoMethodError do
64
+ Blog.create_translation_table! :name => :string
65
+ end
66
+ end
67
+
68
+ test 'drop_translation_table! should not be called on non-translated models' do
69
+ assert_raise NoMethodError do
70
+ Blog.drop_translation_table!
71
+ end
72
+ end
73
+
74
+ test "translation_index_name returns a readable index name when it's not longer than 50 characters" do
75
+ assert_equal 'index_post_translations_on_post_id', Post.send(:translation_index_name)
76
+ end
77
+
78
+ test "translation_index_name returns a hashed index name when it's longer than 50 characters" do
79
+ class UltraLongModelNameWithoutProper < ActiveRecord::Base
80
+ translates :foo
81
+ end
82
+ name = UltraLongModelNameWithoutProper.send(:translation_index_name)
83
+ assert_match /^index_[a-z0-9]{40}$/, name
84
+ end
85
+
86
+ test 'globalize table added when table has long name' do
87
+ UltraLongModelNameWithoutProper.create_translation_table!(
88
+ :subject => :string, :content => :text
89
+ )
90
+
91
+ assert UltraLongModelNameWithoutProper.connection.table_exists?(
92
+ :ultra_long_model_name_without_proper_translations
93
+ )
94
+ assert UltraLongModelNameWithoutProper.connection.index_exists?(
95
+ :ultra_long_model_name_without_proper_translations,
96
+ :name => UltraLongModelNameWithoutProper.send(
97
+ :translation_index_name
98
+ )
99
+ )
100
+ end
101
+
102
+ test 'globalize table dropped when table has long name' do
103
+ UltraLongModelNameWithoutProper.drop_translation_table!
104
+ UltraLongModelNameWithoutProper.create_translation_table!(
105
+ :subject => :string, :content => :text
106
+ )
107
+ UltraLongModelNameWithoutProper.drop_translation_table!
108
+
109
+ assert !UltraLongModelNameWithoutProper.connection.table_exists?(
110
+ :ultra_long_model_name_without_proper_translations
111
+ )
112
+ assert !UltraLongModelNameWithoutProper.connection.index_exists?(
113
+ :ultra_long_model_name_without_proper_translations,
114
+ :ultra_long_model_name_without_proper_id
115
+ )
116
+ end
117
+
118
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../data/models')
3
+
4
+ class StiTranslatedTest < ActiveSupport::TestCase
5
+ def setup
6
+ I18n.locale = :'en-US'
7
+ reset_db!
8
+ end
9
+
10
+ test "works with simple dynamic finders" do
11
+ foo = Child.create :content => 'foo'
12
+ Child.create :content => 'bar'
13
+ child = Child.find_by_content('foo')
14
+ assert_equal foo, child
15
+ end
16
+
17
+ test 'change attribute on globalized model' do
18
+ child = Child.create :content => 'foo'
19
+ assert_equal [], child.changed
20
+ child.content = 'bar'
21
+ assert_equal [ 'content' ], child.changed
22
+ child.content = 'baz'
23
+ assert_member 'content', child.changed
24
+ end
25
+
26
+ test 'change attribute on globalized model after locale switching' do
27
+ child = Child.create :content => 'foo'
28
+ assert_equal [], child.changed
29
+ child.content = 'bar'
30
+ I18n.locale = :de
31
+ assert_equal [ 'content' ], child.changed
32
+ end
33
+
34
+ test "saves all locales, even after locale switching" do
35
+ child = Child.new :content => 'foo'
36
+ I18n.locale = 'de-DE'
37
+ child.content = 'bar'
38
+ I18n.locale = 'he-IL'
39
+ child.content = 'baz'
40
+ child.save
41
+ I18n.locale = 'en-US'
42
+ child = Child.first
43
+ assert_equal 'foo', child.content
44
+ I18n.locale = 'de-DE'
45
+ assert_equal 'bar', child.content
46
+ I18n.locale = 'he-IL'
47
+ assert_equal 'baz', child.content
48
+ end
49
+
50
+ test "works when STI class is defined before globalize is applied" do
51
+ child = EarlyChild.create :content => 'foo'
52
+ I18n.locale = 'de-DE'
53
+ child.content = 'bar'
54
+ child.save
55
+ I18n.locale = 'en-US'
56
+ child = EarlyChild.first
57
+ assert_equal 'foo', child.content
58
+ I18n.locale = 'de-DE'
59
+ assert_equal 'bar', child.content
60
+ end
61
+ end
@@ -0,0 +1,96 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/../data/models')
3
+
4
+ class TranslatesTest < ActiveSupport::TestCase
5
+ def setup
6
+ I18n.locale = nil
7
+ ActiveRecord::Base.locale = nil
8
+ reset_db!
9
+ end
10
+
11
+ test 'defines a :locale accessors on ActiveRecord::Base' do
12
+ ActiveRecord::Base.locale = :de
13
+ assert_equal :de, ActiveRecord::Base.locale
14
+ end
15
+
16
+ test 'the :locale reader on ActiveRecord::Base does not default to I18n.locale (anymore)' do
17
+ I18n.locale = :en
18
+ assert_nil ActiveRecord::Base.locale
19
+ end
20
+
21
+ test 'ActiveRecord::Base.with_locale temporarily sets the given locale and yields the block' do
22
+ I18n.locale = :en
23
+ post = Post.with_locale(:de) do
24
+ Post.create!(:subject => 'Titel', :content => 'Inhalt')
25
+ end
26
+ assert_nil Post.locale
27
+ assert_equal :en, I18n.locale
28
+
29
+ I18n.locale = :de
30
+ assert_equal 'Titel', post.subject
31
+ end
32
+
33
+ test 'translation_class returns the Translation class' do
34
+ assert_equal Post::Translation, Post.translation_class
35
+ end
36
+
37
+ test 'defines a has_many association on the model class' do
38
+ assert_has_many Post, :translations
39
+ end
40
+
41
+ test 'defines a scope for retrieving locales that have complete translations' do
42
+ post = Post.create!(:subject => 'subject', :content => 'content')
43
+ assert_equal [:en], post.translated_locales
44
+ end
45
+
46
+ test 'sets the given attributes to translated_attribute_names' do
47
+ assert_equal [:subject, :content], Post.translated_attribute_names
48
+ end
49
+
50
+ test 'defines accessors for the translated attributes' do
51
+ post = Post.new
52
+ assert post.respond_to?(:subject)
53
+ assert post.respond_to?(:subject=)
54
+ end
55
+
56
+ test 'attribute reader without arguments will use the current locale on ActiveRecord::Base or I18n' do
57
+ post = Post.with_locale(:de) do
58
+ Post.create!(:subject => 'Titel', :content => 'Inhalt')
59
+ end
60
+ I18n.locale = :de
61
+ assert_equal 'Titel', post.subject
62
+
63
+ I18n.locale = :en
64
+ ActiveRecord::Base.locale = :de
65
+ assert_equal 'Titel', post.subject
66
+ end
67
+
68
+ test 'attribute reader when passed a locale will use the given locale' do
69
+ post = Post.with_locale(:de) do
70
+ Post.create!(:subject => 'Titel', :content => 'Inhalt')
71
+ end
72
+ assert_equal 'Titel', post.subject(:de)
73
+ end
74
+
75
+ test 'attribute reader will use the current locale on ActiveRecord::Base or I18n' do
76
+ post = Post.with_locale(:en) do
77
+ Post.create!(:subject => 'title', :content => 'content')
78
+ end
79
+ I18n.locale = :de
80
+ post.subject = 'Titel'
81
+ assert_equal 'Titel', post.subject
82
+
83
+ ActiveRecord::Base.locale = :en
84
+ post.subject = 'title'
85
+ assert_equal 'title', post.subject
86
+ end
87
+
88
+ test "find_by_xx records have writable attributes" do
89
+ Post.create :subject => "change me"
90
+ p = Post.find_by_subject("change me")
91
+ p.subject = "changed"
92
+ assert_nothing_raised(ActiveRecord::ReadOnlyRecord) do
93
+ p.save
94
+ end
95
+ end
96
+ end