Permalink
Browse files

added i18n to the merb book

  • Loading branch information...
1 parent f924deb commit 331383c66c1aa2da7eea455f2de9fb72e6f1e793 @mattetti committed Dec 2, 2008
Showing with 849 additions and 15 deletions.
  1. 0 .gitignore
  2. +8 −2 README.markdown
  3. +3 −0 app/controllers/application.rb
  4. +10 −2 app/controllers/pages.rb
  5. +6 −0 app/helpers/global_helpers.rb
  6. +8 −2 app/views/exceptions/not_found.html.erb
  7. +1 −1 app/views/layout/application.html.erb
  8. 0 book-content/{ → en}/0-front-matter/0-foreword.markdown
  9. 0 book-content/{ → en}/0-front-matter/1-preface.markdown
  10. 0 book-content/{ → en}/0-front-matter/2-contributors.markdown
  11. 0 book-content/{ → en}/1-introduction/1-ruby.markdown
  12. 0 book-content/{ → en}/1-introduction/2-merb.markdown
  13. 0 book-content/{ → en}/1-introduction/3-datamapper.markdown
  14. 0 book-content/{ → en}/1-introduction/4-rspec.markdown
  15. +1 −1 app/views/pages/index.html.erb → book-content/en/toc.markdown
  16. +28 −0 book-content/fr/toc.markdown
  17. +7 −3 config/init.rb
  18. +3 −3 config/router.rb
  19. BIN gems/cache/merb_babel-0.1.0.gem
  20. +20 −0 gems/gems/merb_babel-0.1.0/LICENSE
  21. +1 −0 gems/gems/merb_babel-0.1.0/README
  22. +61 −0 gems/gems/merb_babel-0.1.0/Rakefile
  23. +5 −0 gems/gems/merb_babel-0.1.0/TODO
  24. +49 −0 gems/gems/merb_babel-0.1.0/lib/merb_babel.rb
  25. +29 −0 gems/gems/merb_babel-0.1.0/lib/merb_babel/core_ext.rb
  26. +29 −0 gems/gems/merb_babel-0.1.0/lib/merb_babel/m_i18n.rb
  27. +118 −0 gems/gems/merb_babel-0.1.0/lib/merb_babel/m_l10n.rb
  28. +76 −0 gems/gems/merb_babel-0.1.0/lib/merb_babel/m_locale.rb
  29. +6 −0 gems/gems/merb_babel-0.1.0/lib/merb_babel/merbtasks.rb
  30. +13 −0 gems/gems/merb_babel-0.1.0/spec/lang/en-UK.yml
  31. +13 −0 gems/gems/merb_babel-0.1.0/spec/lang/en-US.yml
  32. +16 −0 gems/gems/merb_babel-0.1.0/spec/lang/en.yml
  33. +49 −0 gems/gems/merb_babel-0.1.0/spec/m_i18n_spec.rb
  34. +51 −0 gems/gems/merb_babel-0.1.0/spec/m_l10n_spec.rb
  35. +127 −0 gems/gems/merb_babel-0.1.0/spec/merb_babel_spec.rb
  36. +14 −0 gems/gems/merb_babel-0.1.0/spec/other_lang_dir/fr.yml
  37. +49 −0 gems/gems/merb_babel-0.1.0/spec/spec_helper.rb
  38. +33 −0 gems/specifications/merb_babel-0.1.0.gemspec
  39. +0 −1 log/merb.4000.pid
  40. +15 −0 public/stylesheets/master.css
View
No changes.
View
@@ -16,11 +16,17 @@ A static HTML and a PDF version will soon be available online.
* Modify, fix, add content
* send me a pull request
-For the moment, the content of the book is located inside ./book-content/ and is organized by chapters and pages.
+For the moment, the content of the book is located inside ./book-content/ and is organized by languages, chapters and pages.
Chapters and pages must be lowercase and start by a digit followed by a dash and the chapter/page title without spaces or any non ascii characters.
-All content files are markdown files and the merb app uses [maruku](http://maruku.rubyforge.org) to render the markdown files. Check the [supported syntax](http://maruku.rubyforge.org/markdown_syntax.html) or check ./book-content/1-introduction/1-ruby.markdown for a good example of how to use images, quotes and css selectors.
+All content files are markdown files and the merb app uses [maruku](http://maruku.rubyforge.org) to render the markdown files. Check the [supported syntax](http://maruku.rubyforge.org/markdown_syntax.html) or check ./book-content/en/1-introduction/1-ruby.markdown for a good example of how to use images, quotes and css selectors.
+
+The book supports multiple languages, each language needs to replicate the English folder structure with the same file names.
+
+If you are copying a page or chapter to your language folder and want to mark a section of your text as requiring translation, just add the to-translate class to the css selector of your content as shown below:
+
+ {: .to-translate}
## Legal
@@ -1,2 +1,5 @@
class Application < Merb::Controller
+
+ before :set_language
+
end
View
@@ -1,7 +1,11 @@
class Pages < Application
def index
- render
+ page_file = find_toc
+ raise NotFound unless page_file
+
+ text = File.open(page_file).read
+ render Maruku::new(text).to_html
end
def show
@@ -18,7 +22,11 @@ def show
private
# If no page name is being passed, the first page is being returned
def find_page_file(chapter, page_name, format="markdown")
- Dir["#{Merb.root}/book-content/*-#{chapter}/*-#{page_name||"*"}.#{format}"].entries.first
+ Dir["#{Merb.root}/book-content/#{language}/*-#{chapter}/*-#{page_name||"*"}.#{format}"].entries.first
+ end
+
+ def find_toc(format="markdown")
+ Dir["#{Merb.root}/book-content/#{language}/toc.#{format}"].entries.first
end
end
@@ -1,5 +1,11 @@
module Merb
module GlobalHelpers
# helpers defined here available to all views.
+
+ def same_url_but_in_english
+ named_route = params[:chapter] ? :page : :toc
+ url(named_route, :language => 'en', :chapter => params[:chapter], :page_name => params[:page_name])
+ end
+
end
end
@@ -1,3 +1,9 @@
-<div class="error">we couldn't find the page you requested, you might want to check on the index</div>
+<div class="error">The page you requested doesn't seem to exist</div>
-<%= link_to "Table of Content", url(:toc) %>
+<% if language != 'en' -%>
+ <p>You required a page with the language code <strong><%= language %></strong>, it might not be available yet, click on the following link to see the requested page in English.</p>
+
+ <p><%= link_to "Same page but in English", same_url_but_in_english %></p>
+<% end -%>
+
+Otherwise, check the <%= link_to "Table of Contents", url(:toc, :language => language) %>
@@ -11,7 +11,7 @@
<div id="book-title"><a href="/">The Merb Open Source Book</a></div>
<div id="book">
- <div class="toc-link"><a href="/">table of contents</a></div>
+ <div class="toc-link"><a href="<%= url(:toc, :language => language) %>">table of contents</a></div>
<div id="table-of-contents">
<%= catch_content :toc %>
@@ -1,4 +1,4 @@
-<h1>Table of Contents</h1>
+#Table of Contents
<div id="intro">
<p>Welcome to the Merb Open Source Book. The purpose of this book is simple: guide beginner and advance users through the Merb Framework.</p>
@@ -0,0 +1,28 @@
+#Table des matières
+
+<div id="intro" class="to-translate">
+ <p>Welcome to the Merb Open Source Book. The purpose of this book is simple: guide beginner and advance users through the Merb Framework.</p>
+ <p>In all honesty, This book won't answer all your questions about Merb, Ruby and unfortunately won't cover all the use case. However will the help of the Ruby Community, we will be able to cover most of what you need to use Merb on a daily basis.</p>
+ <p>If you are learning through this material, or if already use Merb frequently, <strong>please consider helping improve the content of this book</strong></p>
+</div>
+
+<ul id="toc" class="to-translate">
+ <li>
+ <a href="/front-matter">Front Matter</a>
+ <ul>
+ <li><a href="/front-matter/foreword">Foreword by Yehuda Katz</a></li>
+ <li><a href="/front-matter/preface">Preface par Matt Aimonetti</a></li>
+ <li><a href="/front-matter/contributors">Contributeurs</a></li>
+ </ul>
+ </li>
+ <li>
+ <a href="/introduction">Introduction</a>
+ <ul>
+ <li><a href="/introduction/ruby">Ruby</a></li>
+ <li><a href="/introduction/merb">Merb web framework</a></li>
+ <li><a href="/introduction/datamapper">DataMapper ORM</a></li>
+ <li><a href="/introduction/rspec">RSpec testing framework</a></li>
+ </ul>
+ </li>
+
+</ul>
View
@@ -5,22 +5,26 @@
dependency "maruku", ">= 0.5.9"
dependency "merb-assets", "~> 1.0"
+dependency "merb_babel", ">= 0.1.0"
# use_orm :none
use_test :rspec
use_template_engine :erb
Merb::Config.use do |c|
c[:use_mutex] = false
- #c[:session_store] = 'cookie' # can also be 'memory', 'memcache', 'container', 'datamapper
+ c[:session_store] = 'cookie' # can also be 'memory', 'memcache', 'container', 'datamapper
# cookie session store configuration
- #c[:session_secret_key] = '8cea7e76dcb6c428521f22c4943b4e69430a85fa' # required for cookie session store
- #c[:session_id_key] = '_merb-book_session_id' # cookie session id key, defaults to "_session_id"
+ c[:session_secret_key] = '8cea7e76dcb6c428521f22c4943b4e69430a85fa' # required for cookie session store
+ c[:session_id_key] = '_merb-book_session_id' # cookie session id key, defaults to "_session_id"
end
Merb::BootLoader.before_app_loads do
# This will get executed after dependencies have been loaded but before your app's classes have loaded.
+ Merb::Plugins.config[:Merb_babel] = {
+ :default_language => 'en'
+ }
end
Merb::BootLoader.after_app_loads do
View
@@ -1,9 +1,9 @@
Merb.logger.info("Compiling routes...")
Merb::Router.prepare do
- match('/table-of-content').to(:controller => 'pages', :action => 'index').name(:toc)
- match("/:chapter(/:page_name)").to(:controller => 'pages', :action => 'show').name(:page)
+ match('(/:language)/table-of-contents', :language => /^[a-z]{2}$/).to(:controller => 'pages', :action => 'index').name(:toc)
+ match("(/:language)/:chapter(/:page_name)", :language => /^[a-z]{2}$/, :chapter => /.{3,}/).to(:controller => 'pages', :action => 'show').name(:page)
#default_routes
- match('/').to(:controller => 'pages', :action => 'index')
+ match('/(:language)', :language => /^[a-z]{2}$/).to(:controller => 'pages', :action => 'index')
end
Binary file not shown.
@@ -0,0 +1,20 @@
+Copyright (c) 2008 Matt Aimonetti
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
+see README.markdown
@@ -0,0 +1,61 @@
+require 'rubygems'
+require 'rake/gempackagetask'
+require 'rubygems/specification'
+require 'date'
+require "spec/rake/spectask"
+
+PLUGIN = "merb_babel"
+NAME = "merb_babel"
+GEM_VERSION = "0.1.0"
+AUTHOR = "Matt Aimonetti"
+EMAIL = "mattaimonetti@gmail.com"
+HOMEPAGE = "http://github.com/mattetti/merb_babel/"
+SUMMARY = "Merb plugin that provides simple localization/internationalisation"
+
+spec = Gem::Specification.new do |s|
+ s.name = NAME
+ s.version = GEM_VERSION
+ s.platform = Gem::Platform::RUBY
+ s.has_rdoc = true
+ s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
+ s.summary = SUMMARY
+ s.description = s.summary
+ s.author = AUTHOR
+ s.email = EMAIL
+ s.homepage = HOMEPAGE
+ s.add_dependency('merb-core', '~> 1.0.0')
+ s.require_path = 'lib'
+ s.autorequire = PLUGIN
+ s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,spec}/**/*")
+end
+
+Rake::GemPackageTask.new(spec) do |pkg|
+ pkg.gem_spec = spec
+end
+
+desc "install the plugin locally"
+task :install => [:package] do
+ sh %{sudo gem install pkg/#{NAME}-#{VERSION} --no-update-sources}
+end
+
+desc "create a gemspec file"
+task :make_spec do
+ File.open("#{GEM}.gemspec", "w") do |file|
+ file.puts spec.to_ruby
+ end
+end
+
+namespace :jruby do
+
+ desc "Run :package and install the resulting .gem with jruby"
+ task :install => :package do
+ sh %{#{SUDO} jruby -S gem install pkg/#{NAME}-#{Merb::VERSION}.gem --no-rdoc --no-ri}
+ end
+
+end
+
+desc "Run the specs"
+Spec::Rake::SpecTask.new("specs") do |t|
+ t.spec_opts = ["--format", "specdoc", "--colour"]
+ t.spec_files = Dir["spec/**/*_spec.rb"].sort
+end
@@ -0,0 +1,5 @@
+TODO:
+Fix LICENSE with your name
+Fix Rakefile with your name and contact info
+Add your code to lib/merb_abel.rb
+Add your Merb rake tasks to lib/merb_abel/merbtasks.rb
@@ -0,0 +1,49 @@
+require File.join(File.dirname(__FILE__) / "merb_babel" / "core_ext")
+
+# make sure we're running inside Merb
+if defined?(Merb::Plugins)
+
+ # Merb gives you a Merb::Plugins.config hash...feel free to put your stuff in your piece of it
+ Merb::Plugins.config[:merb_babel] = {
+ :default_locale => 'en-US',
+ :default_language => 'en',
+ :default_country => 'US',
+ :localization_dirs => ["#{Merb.root}/lang"]
+ }
+
+ require File.join(File.dirname(__FILE__) / "merb_babel" / "m_locale")
+ require File.join(File.dirname(__FILE__) / "merb_babel" / "m_l10n")
+ require File.join(File.dirname(__FILE__) / "merb_babel" / "m_i18n")
+
+ Merb::BootLoader.before_app_loads do
+ # require code that must be loaded before the application
+ module Merb
+ module GlobalHelpers
+ include ML10n
+
+ # Used to translate words using localizations
+ def babelize(key, *args)
+ options = args.first
+ options ||= {}
+ options.merge!(:key => key)
+ options.merge!(:language => language) unless options.has_key?(:language)
+ options.merge!(:country => country) unless options.has_key?(:country)
+ MI18n.lookup(options)
+ end
+ alias :translate :babelize
+ alias :t :babelize
+ alias :_ :babelize
+
+ end
+ end
+
+ Merb::Controller.send(:include, MLocale)
+ Merb::Controller.send(:include, ML10n)
+ end
+
+ Merb::BootLoader.after_app_loads do
+ # code that can be required after the application loads
+ end
+
+ Merb::Plugins.add_rakefiles "merb_babel/merbtasks"
+end
@@ -0,0 +1,29 @@
+module MerbBabel
+
+ module HashExtension
+
+ def symbolize_keys
+ inject({}) do |options, (key, value)|
+ options[key.to_sym || key] = value
+ options
+ end
+ end
+
+ def symbolize_keys!
+ self.replace(self.symbolize_keys)
+ end
+
+ def valid_localization_hash?
+ self.has_key?(:mloc_language_code)
+ end
+
+ def localization_hash_with_locale?
+ self.has_key?(:mloc_country_code)
+ end
+
+ end
+
+end
+
+
+Hash.send :include, MerbBabel::HashExtension
@@ -0,0 +1,29 @@
+module MI18n
+
+ def self.lookup(options)
+ key = options[:key]
+ language = options[:language]
+ country = options[:country]
+ raise ArgumentError, "You need to pass a language reference" unless language
+ raise ArgumentError, "You need to pass a localization key" unless key
+ raise ArgumentError, "language: #{language} not found" unless ML10n.localizations[language]
+
+ full_location = nil
+ full_location = lookup_with_full_locale(key, language, country) if country
+
+ if full_location
+ return full_location
+ else
+ return ML10n.localizations[language][key]
+ end
+ end
+
+ def self.lookup_with_full_locale(key, language, country)
+ if ML10n.localizations.has_key?(language)
+ ML10n.localizations[language].has_key?(country) ? ML10n.localizations[language][country][key] : nil
+ else
+ nil
+ end
+ end
+
+end
Oops, something went wrong.

0 comments on commit 331383c

Please sign in to comment.