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,39 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the globalize2 plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the globalize2 plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Globalize2'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
23
+
24
+ begin
25
+ require 'jeweler'
26
+ Jeweler::Tasks.new do |s|
27
+ s.name = "globalize2"
28
+ s.summary = "Rails I18n: de-facto standard library for ActiveRecord data translation"
29
+ s.description = "Rails I18n: de-facto standard library for ActiveRecord data translation"
30
+ s.email = "joshmh@gmail.com"
31
+ s.homepage = "http://github.com/joshmh/globalize2"
32
+ # s.rubyforge_project = ''
33
+ s.authors = ["Sven Fuchs, Joshua Harvey, Clemens Kofler, John-Paul Bader"]
34
+ # s.add_development_dependency ''
35
+ end
36
+ Jeweler::GemcutterTasks.new
37
+ rescue LoadError
38
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
39
+ end
@@ -0,0 +1 @@
1
+ 0.2.1
@@ -0,0 +1,25 @@
1
+ class ActsAsTaggableMigration < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :globalize_translations do |t|
4
+ t.string :locale, :null => false
5
+ t.string :key, :null => false
6
+ t.string :translation
7
+ t.timestamps
8
+ end
9
+
10
+ # TODO: FINISH DOING MIGRATION -- stopped in the middle
11
+
12
+ create_table :globalize_translations_map do |t|
13
+ t.string :key, :null => false
14
+ t.integer :translation_id, :null => false
15
+ end
16
+
17
+ add_index :taggings, :tag_id
18
+ add_index :taggings, [:taggable_id, :taggable_type]
19
+ end
20
+
21
+ def self.down
22
+ drop_table :globalize_translations
23
+ drop_table :tags
24
+ end
25
+ end
@@ -0,0 +1,81 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{globalize2}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Sven Fuchs, Joshua Harvey, Clemens Kofler, John-Paul Bader"]
12
+ s.date = %q{2010-04-22}
13
+ s.description = %q{Rails I18n: de-facto standard library for ActiveRecord data translation}
14
+ s.email = %q{joshmh@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.textile"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README.textile",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "generators/db_backend.rb",
26
+ "generators/templates/db_backend_migration.rb",
27
+ "globalize2.gemspec",
28
+ "init.rb",
29
+ "lib/globalize.rb",
30
+ "lib/globalize/active_record.rb",
31
+ "lib/globalize/active_record/adapter.rb",
32
+ "lib/globalize/active_record/attributes.rb",
33
+ "lib/globalize/active_record/migration.rb",
34
+ "lib/i18n/missing_translations_log_handler.rb",
35
+ "lib/i18n/missing_translations_raise_handler.rb",
36
+ "test/active_record/fallbacks_test.rb",
37
+ "test/active_record/migration_test.rb",
38
+ "test/active_record/sti_translated_test.rb",
39
+ "test/active_record/translates_test.rb",
40
+ "test/active_record/translation_class_test.rb",
41
+ "test/active_record/validation_tests.rb",
42
+ "test/active_record_test.rb",
43
+ "test/all.rb",
44
+ "test/data/models.rb",
45
+ "test/data/no_globalize_schema.rb",
46
+ "test/data/schema.rb",
47
+ "test/i18n/missing_translations_test.rb",
48
+ "test/test_helper.rb"
49
+ ]
50
+ s.homepage = %q{http://github.com/joshmh/globalize2}
51
+ s.rdoc_options = ["--charset=UTF-8"]
52
+ s.require_paths = ["lib"]
53
+ s.rubygems_version = %q{1.3.6}
54
+ s.summary = %q{Rails I18n: de-facto standard library for ActiveRecord data translation}
55
+ s.test_files = [
56
+ "test/active_record/fallbacks_test.rb",
57
+ "test/active_record/migration_test.rb",
58
+ "test/active_record/sti_translated_test.rb",
59
+ "test/active_record/translates_test.rb",
60
+ "test/active_record/translation_class_test.rb",
61
+ "test/active_record/validation_tests.rb",
62
+ "test/active_record_test.rb",
63
+ "test/all.rb",
64
+ "test/data/models.rb",
65
+ "test/data/no_globalize_schema.rb",
66
+ "test/data/schema.rb",
67
+ "test/i18n/missing_translations_test.rb",
68
+ "test/test_helper.rb"
69
+ ]
70
+
71
+ if s.respond_to? :specification_version then
72
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
73
+ s.specification_version = 3
74
+
75
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
76
+ else
77
+ end
78
+ else
79
+ end
80
+ end
81
+
@@ -0,0 +1 @@
1
+ require 'globalize'
@@ -0,0 +1,15 @@
1
+ module Globalize
2
+ autoload :ActiveRecord, 'globalize/active_record'
3
+
4
+ class << self
5
+ def fallbacks?
6
+ I18n.respond_to?(:fallbacks)
7
+ end
8
+
9
+ def fallbacks(locale)
10
+ fallbacks? ? I18n.fallbacks[locale] : [locale.to_sym]
11
+ end
12
+ end
13
+ end
14
+
15
+ ActiveRecord::Base.send(:include, Globalize::ActiveRecord)
@@ -0,0 +1,215 @@
1
+ module Globalize
2
+ class MigrationError < StandardError; end
3
+ class MigrationMissingTranslatedField < MigrationError; end
4
+ class BadMigrationFieldType < MigrationError; end
5
+
6
+ module ActiveRecord
7
+ autoload :Adapter, 'globalize/active_record/adapter'
8
+ autoload :Attributes, 'globalize/active_record/attributes'
9
+ autoload :Migration, 'globalize/active_record/migration'
10
+
11
+ def self.included(base)
12
+ base.extend ActMacro
13
+ end
14
+
15
+ class << self
16
+ def build_translation_class(target, options)
17
+ options[:table_name] ||= "#{target.table_name.singularize}_translations"
18
+
19
+ klass = target.const_defined?(:Translation) ?
20
+ target.const_get(:Translation) :
21
+ target.const_set(:Translation, Class.new(::ActiveRecord::Base))
22
+
23
+ klass.class_eval do
24
+ set_table_name(options[:table_name])
25
+ belongs_to target.name.underscore.gsub('/', '_')
26
+ def locale; read_attribute(:locale).to_sym; end
27
+ def locale=(locale); write_attribute(:locale, locale.to_s); end
28
+ end
29
+
30
+ klass
31
+ end
32
+ end
33
+
34
+ module ActMacro
35
+ def locale
36
+ (defined?(@@locale) && @@locale)
37
+ end
38
+
39
+ def locale=(locale)
40
+ @@locale = locale
41
+ end
42
+
43
+ def translates(*attr_names)
44
+ return if translates?
45
+ options = attr_names.extract_options!
46
+
47
+ class_inheritable_accessor :translation_class, :translated_attribute_names
48
+ class_inheritable_writer :required_attributes
49
+
50
+ (subclasses_of(self) + [self]).each do |klass|
51
+ klass.translation_class = ActiveRecord.build_translation_class(self, options)
52
+ klass.translated_attribute_names = attr_names.map(&:to_sym)
53
+ end
54
+
55
+ include InstanceMethods
56
+ extend ClassMethods, Migration
57
+
58
+ after_save :save_translations!
59
+ has_many :translations, :class_name => translation_class.name,
60
+ :foreign_key => class_name.foreign_key,
61
+ :dependent => :delete_all,
62
+ :extend => HasManyExtensions
63
+
64
+ named_scope :with_translations, lambda { |locale|
65
+ conditions = required_attributes.map do |attribute|
66
+ "#{quoted_translation_table_name}.#{attribute} IS NOT NULL"
67
+ end
68
+ conditions << "#{quoted_translation_table_name}.locale = ?"
69
+ { :include => :translations, :conditions => [conditions.join(' AND '), locale] }
70
+ }
71
+
72
+ attr_names.each { |attr_name| translated_attr_accessor(attr_name) }
73
+ end
74
+
75
+ def translates?
76
+ included_modules.include?(InstanceMethods)
77
+ end
78
+ end
79
+
80
+ module HasManyExtensions
81
+ def by_locale(locale)
82
+ first(:conditions => { :locale => locale.to_s })
83
+ end
84
+
85
+ def by_locales(locales)
86
+ all(:conditions => { :locale => locales.map(&:to_s) })
87
+ end
88
+ end
89
+
90
+ module ClassMethods
91
+ delegate :set_translation_table_name, :to => :translation_class
92
+
93
+ def with_locale(locale)
94
+ previous_locale, self.locale = self.locale, locale
95
+ result = yield
96
+ self.locale = previous_locale
97
+ result
98
+ end
99
+
100
+ def translation_table_name
101
+ translation_class.table_name
102
+ end
103
+
104
+ def quoted_translation_table_name
105
+ translation_class.quoted_table_name
106
+ end
107
+
108
+ def required_attributes
109
+ @required_attributes ||= reflect_on_all_validations.select do |validation|
110
+ validation.macro == :validates_presence_of && translated_attribute_names.include?(validation.name)
111
+ end.map(&:name)
112
+ end
113
+
114
+ def respond_to?(method, *args, &block)
115
+ method.to_s =~ /^find_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym) || super
116
+ end
117
+
118
+ def method_missing(method, *args)
119
+ if method.to_s =~ /^find_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym)
120
+ find_first_by_translated_attr_and_locales($1, args.first)
121
+ else
122
+ super
123
+ end
124
+ end
125
+
126
+ protected
127
+
128
+ def find_first_by_translated_attr_and_locales(name, value)
129
+ query = "#{translated_attr_name(name)} = ? AND #{translated_attr_name('locale')} IN (?)"
130
+ locales = Globalize.fallbacks(locale || I18n.locale).map(&:to_s)
131
+ find(
132
+ :first,
133
+ :joins => :translations,
134
+ :conditions => [query, value, locales],
135
+ :readonly => false
136
+ )
137
+ end
138
+
139
+ def translated_attr_accessor(name)
140
+ define_method "#{name}=", lambda { |value|
141
+ globalize.write(self.class.locale || I18n.locale, name, value)
142
+ self[name] = value
143
+ }
144
+ define_method name, lambda { |*args|
145
+ globalize.fetch(args.first || self.class.locale || I18n.locale, name)
146
+ }
147
+ alias_method "#{name}_before_type_cast", name
148
+ end
149
+
150
+ def translated_attr_name(name)
151
+ "#{translation_class.table_name}.#{name}"
152
+ end
153
+ end
154
+
155
+ module InstanceMethods
156
+ def globalize
157
+ @globalize ||= Adapter.new self
158
+ end
159
+
160
+ def attributes
161
+ self.attribute_names.inject({}) do |attrs, name|
162
+ attrs[name] = read_attribute(name) ||
163
+ (globalize.fetch(I18n.locale, name) rescue nil)
164
+ attrs
165
+ end
166
+ end
167
+
168
+ def attributes=(attributes, *args)
169
+ if attributes.respond_to?(:delete) && locale = attributes.delete(:locale)
170
+ self.class.with_locale(locale) { super }
171
+ else
172
+ super
173
+ end
174
+ end
175
+
176
+ def attribute_names
177
+ translated_attribute_names.map(&:to_s) + super
178
+ end
179
+
180
+ def available_locales
181
+ translations.scoped(:select => 'DISTINCT locale').map(&:locale)
182
+ end
183
+
184
+ def translated_locales
185
+ translations.map(&:locale)
186
+ end
187
+
188
+ def translated_attributes
189
+ translated_attribute_names.inject({}) do |attributes, name|
190
+ attributes.merge(name => send(name))
191
+ end
192
+ end
193
+
194
+ def set_translations(options)
195
+ options.keys.each do |locale|
196
+ translation = translations.find_by_locale(locale.to_s) ||
197
+ translations.build(:locale => locale.to_s)
198
+ translation.update_attributes!(options[locale])
199
+ end
200
+ end
201
+
202
+ def reload(options = nil)
203
+ translated_attribute_names.each { |name| @attributes.delete(name.to_s) }
204
+ globalize.reset
205
+ super(options)
206
+ end
207
+
208
+ protected
209
+
210
+ def save_translations!
211
+ globalize.save_translations!
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,80 @@
1
+ module Globalize
2
+ module ActiveRecord
3
+ class Adapter
4
+ # The cache caches attributes that already were looked up for read access.
5
+ # The stash keeps track of new or changed values that need to be saved.
6
+ attr_reader :record, :cache, :stash
7
+
8
+ def initialize(record)
9
+ @record = record
10
+ @cache = Attributes.new
11
+ @stash = Attributes.new
12
+ end
13
+
14
+ def fetch(locale, attr_name)
15
+ cache.contains?(locale, attr_name) ?
16
+ cache.read(locale, attr_name) :
17
+ cache.write(locale, attr_name, fetch_attribute(locale, attr_name))
18
+ end
19
+
20
+ def write(locale, attr_name, value)
21
+ stash.write(locale, attr_name, value)
22
+ cache.write(locale, attr_name, value)
23
+ end
24
+
25
+ def save_translations!
26
+ stash.each do |locale, attrs|
27
+ translation = record.translations.find_or_initialize_by_locale(locale.to_s)
28
+ attrs.each { |attr_name, value| translation[attr_name] = value }
29
+ translation.save!
30
+ end
31
+ stash.clear
32
+ end
33
+
34
+ def reset
35
+ cache.clear
36
+ # stash.clear
37
+ end
38
+
39
+ protected
40
+
41
+ def fetch_translation(locale)
42
+ locale = locale.to_sym
43
+ record.translations.loaded? ? record.translations.detect { |t| t.locale == locale } :
44
+ record.translations.by_locale(locale)
45
+ end
46
+
47
+ def fetch_translations(locale)
48
+ # only query if not already included with :include => translations
49
+ record.translations.loaded? ? record.translations :
50
+ record.translations.by_locales(Globalize.fallbacks(locale))
51
+ end
52
+
53
+ def fetch_attribute(locale, attr_name)
54
+ translations = fetch_translations(locale)
55
+ value, requested_locale = nil, locale
56
+
57
+ Globalize.fallbacks(locale).each do |fallback|
58
+ translation = translations.detect { |t| t.locale == fallback }
59
+ value = translation && translation.send(attr_name)
60
+ locale = fallback && break if value
61
+ end
62
+
63
+ set_metadata(value, :locale => locale, :requested_locale => requested_locale)
64
+ value
65
+ end
66
+
67
+ def set_metadata(object, metadata)
68
+ if object.respond_to?(:translation_metadata)
69
+ object.translation_metadata.merge!(meta_data)
70
+ end
71
+ end
72
+
73
+ def translation_metadata_accessor(object)
74
+ return if obj.respond_to?(:translation_metadata)
75
+ class << object; attr_accessor :translation_metadata end
76
+ object.translation_metadata ||= {}
77
+ end
78
+ end
79
+ end
80
+ end