haml-magic-translations-4.0.0/0000755000004100000410000000000012157374055016272 5ustar www-datawww-datahaml-magic-translations-4.0.0/haml-magic-translations.gemspec0000644000004100000410000000632012157374055024356 0ustar www-datawww-data# Generated by jeweler # DO NOT EDIT THIS FILE DIRECTLY # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = %q{haml-magic-translations} s.version = "4.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Kriss Kowalik", "potager.org"] s.date = %q{2013-05-28} s.description = %q{This plugin provides "magical translations" in your .haml files. What does it mean? It's mean that all your raw texts in templates will be automatically translated by GetText, FastGettext or Gettext backend from I18n. No more complicated translation keys and ugly translation methods in views. Now you can only write in your language, nothing more. At the end of your work you can easy find all phrases to translate and generate .po files for it. This type of files are also more readable and easier to translate, thanks to it you save your time with translations. } s.email = %q{jardiniers@potager.org} s.extra_rdoc_files = [ "LICENSE", "README.rdoc" ] s.files = [ "LICENSE", "README.rdoc", "Rakefile", "VERSION", "haml-magic-translations.gemspec", "init.rb", "lib/haml-magic-translations.rb", "lib/haml/magic_translations.rb", "lib/haml/magic_translations/tasks.rb", "lib/haml/magic_translations/xgettext/haml_parser.rb", "spec/haml/magic_translations/tasks_spec.rb", "spec/haml/magic_translations/xgettext/haml_parser_spec.rb", "spec/haml/magic_translations_spec.rb", "spec/locales/en.po", "spec/locales/pl.po", "spec/spec_helper.rb" ] s.homepage = %q{https://github.com/potager/haml-magic-translations} s.require_paths = ["lib"] s.rubygems_version = %q{1.8.23} s.summary = %q{Provides automaticaly translations in haml templates} if s.respond_to? :specification_version then s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q, ["~> 4.0"]) s.add_development_dependency(%q, [">= 1.0"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 2.3"]) s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 2"]) s.add_development_dependency(%q, [">= 2.4.2"]) s.add_development_dependency(%q, [">= 0"]) else s.add_dependency(%q, ["~> 4.0"]) s.add_dependency(%q, [">= 1.0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 2.3"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 2"]) s.add_dependency(%q, [">= 2.4.2"]) s.add_dependency(%q, [">= 0"]) end else s.add_dependency(%q, ["~> 4.0"]) s.add_dependency(%q, [">= 1.0"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 2.3"]) s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 2"]) s.add_dependency(%q, [">= 2.4.2"]) s.add_dependency(%q, [">= 0"]) end end haml-magic-translations-4.0.0/LICENSE0000644000004100000410000000210012157374055017270 0ustar www-datawww-dataCopyright (c) 2010 Kriss Kowalik Copyright (c) 2012 potager.org 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. haml-magic-translations-4.0.0/init.rb0000644000004100000410000000004212157374055017556 0ustar www-datawww-datarequire 'haml-magic-translations' haml-magic-translations-4.0.0/README.rdoc0000644000004100000410000000655412157374055020112 0ustar www-datawww-data== Magic Translations This plugin provides "magical translations" in your .haml files. What does it mean? It's mean that all your raw texts in templates will be automatically translated by GetText, FastGettext or Gettext backend from I18n. No more complicated translation keys and ugly translation methods in views. Now you can only write in your language, nothing more. At the end of your work you can easy find all phrases to translate and generate .po files for it. This type of files are also more readable and easier to translate, thanks to it you save your time with translations. === Installation You can install haml-magic-translations directly from rubygems: gem install haml-magic-translations ...or as Ruby on Rails plugin: script/plugin install git://github.com/kriss/haml-magic-translations or rails plugin install git://github.com/kriss/haml-magic-translations === Gettings started with Gettext To use automatical translations you have to using new I18n with Gettext backend, GetText or FastGettext, properly installed and configured. To enable plugin you have to do following things: Haml::MagicTranslations.enable(:i18n) # this backend is used by default Available backends are +:i18n+, +:gettext+ and +:fast_gettext+ Now you have to add path to all your .po files with locales. Eg. for i18n backend it will be something like: I18n.load_path += Dir["path/to/your/locales/*.{po}")] And that's all. Now you can enjoy automatically translations in your .haml files! === Examples Now you can write what you want, and at the end of work you will easy found all phrases to translate. Check out following example: %p This is my simple dummy text. %p And more lorem ipsum... %p= link_to _("This will be also translated"), "#" Those translations are allso allowing you to use standard Haml interpolation. You can easy write: %p This is my text with #{"interpolation".upcase}... Great, isn't it? %p This multiline string Will be also translated And text from codes above will be stored in .po files as: # File test1.haml, line 1 msgid "This is my simple dummy text" msgstr "This is my dummy translation of dummy text" # File test2.haml, line 1 msgid "This is my text with %s... Great, isn't it?" msgstr "Next one %s translation!" # File test4.haml, line 3 msgid "This multiline string" msgstr "" # File test2.haml, line 4 msgid "Will be also translated" msgstr "" Notice that in multiline strings each line is translated separatelly. Generator for .po files also includes information where your phrases are placed in filesystem. Thanks to it you don't forget about any even small word to translate. === Extracting strings and merging translations In order to extract translatable strings and merge with existing translation, this gem provides an Haml parser for GetText::Tools::XGetText. This requires gettext >= 2.3 to be available. You can either use it directly or through the provided Rake task. Here's an example on how to use the later: Haml::MagicTranslations::Tasks::UpdatePoFiles.new do |t| t.text_domain = 'my_project' t.files = Dir.glob("views/**/*.{rb,haml}") << "lib/my_project.rb" t.app_version = 'my_project 0.1' end This will add a +update_pofiles+ task that will update PO files that can be found in the +po+ directory. === Copyrights Kriss Kowalik (kriss.kowalik@gmail.com) potager.org (jardiniers@potager.org) haml-magic-translations-4.0.0/Rakefile0000644000004100000410000000432612157374055017744 0ustar www-datawww-datarequire 'rake' begin require 'jeweler' Jeweler::Tasks.new do |gem| gem.name = "haml-magic-translations" gem.summary = "Provides automaticaly translations in haml templates" gem.description = <<-DESCR This plugin provides "magical translations" in your .haml files. What does it mean? It's mean that all your raw texts in templates will be automatically translated by GetText, FastGettext or Gettext backend from I18n. No more complicated translation keys and ugly translation methods in views. Now you can only write in your language, nothing more. At the end of your work you can easy find all phrases to translate and generate .po files for it. This type of files are also more readable and easier to translate, thanks to it you save your time with translations. DESCR gem.email = "jardiniers@potager.org" gem.homepage = "https://github.com/potager/haml-magic-translations" gem.authors = ["Kriss Kowalik", "potager.org"] gem.add_dependency "haml", "~> 4.0" gem.add_development_dependency "haml-contrib", ">= 1.0" gem.add_development_dependency "actionpack" gem.add_development_dependency "gettext", ">= 2.3" gem.add_development_dependency "fast_gettext" gem.add_development_dependency "rspec", ">= 2" gem.add_development_dependency "rdoc", ">= 2.4.2" gem.add_development_dependency "maruku" end Jeweler::GemcutterTasks.new rescue LoadError puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler" end require 'rspec/core/rake_task' require 'rdoc/task' desc 'Default: run specs.' task :default => :spec desc 'Run the specs' RSpec::Core::RakeTask.new(:spec) do |t| t.rspec_opts = %w(-fs --color) end namespace :spec do desc "Run all specs with RCov" RSpec::Core::RakeTask.new(:rcov) do |t| t.rspec_opts = ['--colour --format progress --loadby mtime --reverse'] t.rcov = true t.rcov_opts = ['--exclude', 'spec,/Users/'] end end desc 'Generate documentation for the simple_navigation plugin.' Rake::RDocTask.new(:rdoc) do |rdoc| rdoc.rdoc_dir = 'rdoc' rdoc.title = 'SimpleNavigation' rdoc.options << '--line-numbers' << '--inline-source' rdoc.main = "README.rdoc" rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb") end haml-magic-translations-4.0.0/spec/0000755000004100000410000000000012157374055017224 5ustar www-datawww-datahaml-magic-translations-4.0.0/spec/locales/0000755000004100000410000000000012157374055020646 5ustar www-datawww-datahaml-magic-translations-4.0.0/spec/locales/en.po0000644000004100000410000000034312157374055021610 0ustar www-datawww-datamsgid "" msgstr "" "Content-Type: text/plain; charset=us-ascii\n" "Content-Transfer-Encoding: 8bit\n" msgid "Magic translations works!" msgstr "" msgid "Here with interpolation, and everything thanks to %s and %s" msgstr "" haml-magic-translations-4.0.0/spec/locales/pl.po0000644000004100000410000000135012157374055021620 0ustar www-datawww-datamsgid "" msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Magic translations works!" msgstr "Magiczne tłumaczenie działa!" msgid "Here with interpolation, and everything thanks to %s and %s" msgstr "A tutaj razem z interpolacją, a to wszystko dzięki połączeniu %s i %s" msgid "Now we will check multiline strings," msgstr "Kolejny wieloliniowy tekst," msgid "which should be also translated," msgstr "który powinien zostać przetłumaczony," msgid "with interpolation %s" msgstr "interpolacja %s też działa!" msgid "" "Now we will check multiline strings,\n" "which should be also translated." msgstr "" "Kolejny wieloliniowy tekst,\n" "który powinien zostać przetłumaczony." haml-magic-translations-4.0.0/spec/haml/0000755000004100000410000000000012157374055020145 5ustar www-datawww-datahaml-magic-translations-4.0.0/spec/haml/magic_translations_spec.rb0000644000004100000410000002166212157374055025374 0ustar www-datawww-data# -*- coding: UTF-8 -*- require 'spec_helper' require 'tmpdir' require 'gettext/tools' # Stolen from ActiveSupport. We have to cut and paste it here so it # does not turn the encoding back to US-ASCII. Strange issue. class String def strip_heredoc indent = scan(/^[ \t]*(?=\S)/).min.try(:size) || 0 gsub(/^[ \t]{#{indent}}/, '') end def translate_unicode gsub(/\\u([0-9a-z]{4})/) {|s| [$1.to_i(16)].pack("U")} end end module Haml describe MagicTranslations do describe '.enable' do after { Haml::MagicTranslations.disable } context 'when using :i18n as backend' do before { Haml::MagicTranslations.enable :i18n } it { Haml::MagicTranslations.should be_enabled } it { Haml::MagicTranslations::Compiler. magic_translations_helpers.should == I18n::Gettext::Helpers } end context 'when using :gettext as backend' do before { Haml::MagicTranslations.enable :gettext } it { Haml::MagicTranslations.should be_enabled } it { Haml::MagicTranslations::Compiler. magic_translations_helpers.should == GetText } end context 'when using :fast_gettext as backend' do before { Haml::MagicTranslations.enable :fast_gettext } it { Haml::MagicTranslations.should be_enabled } it { Haml::MagicTranslations::Compiler. magic_translations_helpers.should == FastGettext::Translation } end context 'when giving another backend' do it 'should raise an error' do expect { Haml::MagicTranslations.enable :whatever }.to raise_error(ArgumentError) end it { Haml::MagicTranslations.should_not be_enabled } end end describe '.disable' do it 'should set Haml::MagicTranslations.enabled to false' do Haml::MagicTranslations.disable Haml::MagicTranslations.should_not be_enabled end end shared_examples 'Haml magic translations' do it 'should translate text using existing locales' do render(<<-'HAML'.strip_heredoc).should == <<-'HTML'.strip_heredoc %p Magic translations works! %p Here with interpolation, and everything thanks to #{I18n.name} and #{GetText.name} HAML

Magiczne tłumaczenie działa!

A tutaj razem z interpolacją, a to wszystko dzięki połączeniu I18n i GetText

HTML end it 'should leave text without changes when translation is not available' do render(<<-'HAML'.strip_heredoc).should == <<-'HTML'.strip_heredoc %p Untranslated thanks to #{I18n.name} and #{GetText.name} HAML

Untranslated thanks to I18n and GetText

HTML end it 'should translate text with multiline plain text' do render(<<-'HAML'.strip_heredoc).should == <<-'HTML'.strip_heredoc %p Magic translations works! %p Now we will check multiline strings, which should be also translated, with interpolation #{'Interpolation'.upcase} HAML

Magiczne tłumaczenie działa!

Kolejny wieloliniowy tekst, który powinien zostać przetłumaczony, interpolacja INTERPOLATION też działa!

HTML end it 'should translate escaped tags' do render(<<-HAML.strip_heredoc).should == <<-HTML.strip_heredoc %p& Magic translations works! HAML

Magiczne tłumaczenie działa!

HTML end it 'should translate unescaped tags' do render(<<-HAML.strip_heredoc).should == <<-HTML.strip_heredoc %p! Magic translations works! HAML

Magiczne tłumaczenie działa!

HTML end it 'should not translate evaluated tags' do render(<<-HAML.strip_heredoc).should == <<-HTML.strip_heredoc %p= 'Magic translations works!' HAML

Magic translations works!

HTML end it 'should not translate escaped evaluated tags' do render(<<-HAML.strip_heredoc).should == <<-HTML.strip_heredoc %p&= 'Magic translations works!' HAML

Magic translations works!

HTML end it 'should not translate unescaped evaluated tags' do render(<<-HAML.strip_heredoc).should == <<-HTML.strip_heredoc %p!= 'Magic translations works!' HAML

Magic translations works!

HTML end context 'when translating strings in JavaScript' do it "should translate strings inside _('')" do render(<<-'HAML'.strip_heredoc).translate_unicode.should == <<-'HTML'.strip_heredoc.translate_unicode :javascript var text = _('Magic translations works!'); HAML HTML end it 'should translate strings inside _("")' do render(<<-'HAML'.strip_heredoc).translate_unicode.should == <<-'HTML'.strip_heredoc.translate_unicode :javascript var text = _("Magic translations works!"); HAML HTML end it 'should not choke on single-quote' do render(<<-'HAML'.strip_heredoc).should == <<-'HTML'.strip_heredoc :javascript var text = _("Don't you think?"); HAML HTML end it 'should not choke on double-quote' do render(<<-'HAML'.strip_heredoc).should == <<-'HTML'.strip_heredoc :javascript var text = _('One "quote" here'); HAML HTML end end context 'when translating strings in Markdown' do it "should translate strings inside _('')" do render(<<-'HAML'.strip_heredoc).should == <<-'HTML'.strip_heredoc :maruku Now we will check multiline strings, which should be also translated. HAML

Kolejny wieloliniowy tekst, który powinien zostać przetłumaczony.

HTML end end context 'when disabling magic translations' do it 'should leave text untranslated' do Haml::MagicTranslations.disable render(<<-'HAML'.strip_heredoc).should == <<-'HTML'.strip_heredoc %p Magic translations works! HAML

Magic translations works!

HTML end end end context 'with I18n as backend' do before(:each) do Haml::MagicTranslations.enable :i18n I18n.locale = :pl I18n.load_path += Dir[File.join(File.dirname(__FILE__), "../locales/*.po")] end it_should_behave_like 'Haml magic translations' end context 'with GetText as backend' do # set up locales file as GetText expects around do |example| Dir.mktmpdir("haml-magic-translations") do |tmpdir| src_dir = File.expand_path('../../locales', __FILE__) Dir.glob(File.join(src_dir, '*.po')).each do |src| lang = File.basename(src).gsub(/\.po$/, '') dest = File.join(tmpdir, lang, 'LC_MESSAGES', 'test.mo') FileUtils.mkdir_p(File.dirname(dest)) GetText::Tools::MsgFmt.run(src, '-o', dest) end Haml::MagicTranslations.enable :gettext GetText.bindtextdomain 'test', :path => tmpdir GetText.setlocale 'pl' example.run end end it_should_behave_like 'Haml magic translations' end context 'with FastGettext as backend' do # set up locales file as FastGettext expects around do |example| Dir.mktmpdir("haml-magic-translations") do |tmpdir| src_dir = File.expand_path('../../locales', __FILE__) Dir.glob(File.join(src_dir, '*.po')).each do |src| lang = File.basename(src).gsub(/\.po$/, '') dest = File.join(tmpdir, lang, 'test.po') FileUtils.mkdir_p(File.dirname(dest)) FileUtils.copy(src, dest) end Haml::MagicTranslations.enable :fast_gettext FastGettext.add_text_domain 'test', :path => tmpdir, :type => :po FastGettext.text_domain = 'test' FastGettext.locale = 'pl' example.run end end it_should_behave_like 'Haml magic translations' end end end haml-magic-translations-4.0.0/spec/haml/magic_translations/0000755000004100000410000000000012157374055024026 5ustar www-datawww-datahaml-magic-translations-4.0.0/spec/haml/magic_translations/xgettext/0000755000004100000410000000000012157374055025702 5ustar www-datawww-datahaml-magic-translations-4.0.0/spec/haml/magic_translations/xgettext/haml_parser_spec.rb0000644000004100000410000001616512157374055031547 0ustar www-datawww-data# -*- coding: UTF-8 -*- require 'spec_helper' require 'haml/magic_translations/xgettext/haml_parser' module Haml::MagicTranslations::XGetText describe HamlParser do describe '.target?' do subject { HamlParser } context 'when given example.rb' do it { should_not be_a_target('example.rb') } end context 'when given example.haml' do it { should be_a_target('example.haml') } end end describe '.parse' do it 'should properly instanciate a Parser' do HamlParser::XGetTextParser.should_receive(:new).with('test.haml'). and_return(mock('XGetTextParser').as_null_object) HamlParser.parse('test.haml') end it 'should run the parser' do parser = mock('XGetTextParser') parser.should_receive(:parse) HamlParser::XGetTextParser.stub!(:new).and_return(parser) HamlParser.parse('test.haml') end end describe HamlParser::XGetTextParser do describe '#initialize' do context 'when given "test.haml"' do before(:each) do File.stub!(:open).and_return(StringIO.new('It works!')) @parser = HamlParser::XGetTextParser.new('test.haml') end it 'should set file attribute' do @parser.file.should == 'test.haml' end it 'should put the file content in the content attribute' do @parser.content.should == 'It works!' end end context 'when given a IO-like object' do let (:parser) { HamlParser::XGetTextParser.new(StringIO.new('It works!')) } it { parser.file.should == '(haml)' } it { parser.content.should == 'It works!' } end end describe '#parse' do subject { HamlParser::XGetTextParser.new(StringIO.new(template)).parse } context 'for an empty content' do let(:template) { '' } it 'should return no targets' do should == [] end end context 'for a translatable plain string' do let(:template) { 'It works!' } it 'should return a target' do should == [['It works!', '(haml):1']] end end context 'for two translatable plain strings' do let(:template) do <<-HAML.strip_heredoc First line Second line HAML end it 'should return two targets (with proper lines)' do should == [['First line', '(haml):1'], ['Second line', '(haml):2']] end end context 'for a translatable tag' do let(:template) { '%p Hello!' } it 'should add its content' do should == [['Hello!', '(haml):1']] end end context 'for a translatable escaped tag' do let(:template) { '%p! Hello!' } it 'should add its content' do should == [['Hello!', '(haml):1']] end end context 'for a translatable unescaped tag' do let(:template) { '%p& Hello!' } it 'should add its content' do should == [['Hello!', '(haml):1']] end end context 'for an evaluated tag' do let(:template) { '%p= "Hello!"' } it 'should not add its content' do should == [] end end context 'for an evaluated escaped tag' do let(:template) { '%p!= Hello!' } it 'should not add its content' do should == [] end end context 'for an evaluated unescaped tag' do let(:template) { '%p&= Hello!' } it 'should not add its content' do should == [] end end context 'for an evaluated tag with an explicitely translatable string' do let(:template) { "%p= _('Hello!')" } it 'should add the content of the string' do should == [['Hello!', '(haml):1']] end end context 'for an evaluated escaped tag with an explicitely translatable string' do let(:template) { "%p!= _('Hello!')" } it 'should add the content of the string' do should == [['Hello!', '(haml):1']] end end context 'for an evaluated unescaped tag with an explicitely translatable string' do let(:template) { "%p&= _('Hello!')" } it 'should add the content of the string' do should == [['Hello!', '(haml):1']] end end context 'for an explicit translation in an attribute' do let(:template) { "%input(type=submit){ value => _('Upload') }" } it 'should appear as a target' do should == [['Upload', '(haml):1']] end end context 'for a translatable string appearing twice' do let(:template) do <<-HAML.strip_heredoc %p Hello! %span= _('Hello!') HAML end it 'should appear only once in the targets' do subject.collect { |t| t[0] }.should have(1).item end it 'should record two target locations' do should == [['Hello!', '(haml):1', '(haml):2']] end end context 'for one interpolated string' do let(:template) { '%p Hello #{name}!' } it 'should replace with %s' do should == [['Hello %s!', '(haml):1']] end end context 'for two interpolated strings' do let(:template) { '%p Hello #{name}! Welcome to #{place}.' } it 'should replace them with %s' do should == [['Hello %s! Welcome to %s.', '(haml):1']] end end context 'for translatable strings in JavaScript' do let(:template) do <<-HAML.strip_heredoc :javascript var lines = [ _('First line'), _('Second line') ] HAML end it 'should properly identify them' do should == [['First line', '(haml):2'], ['Second line', '(haml):3']] end end context 'for JavaScript strings with quotes' do let(:template) do <<-HAML.strip_heredoc :javascript var text = _('L\\'article'); HAML end it 'should properly identify them' do should == [["L'article", '(haml):2']] end end context 'for markdown block' do let(:template) do <<-HAML.strip_heredoc :markdown First paragraph Second paragraph HAML end it 'should properly add it to translations' do should == [["First paragraph\n\nSecond paragraph", '(haml):1']] end end context 'after extracting translations' do it 'should still allow Haml::Engine to build templates' do HamlParser::XGetTextParser.new(StringIO.new('test')).parse Haml::Engine.new('%p It works!').render.should == <<-'HTML'.strip_heredoc

It works!

HTML end end end end end end haml-magic-translations-4.0.0/spec/haml/magic_translations/tasks_spec.rb0000644000004100000410000000567512157374055026527 0ustar www-datawww-data# -*- coding: UTF-8 -*- require 'spec_helper' require 'haml/magic_translations/tasks' require 'gettext/tools/xgettext' module Haml::MagicTranslations::Tasks describe UpdatePoFiles do before do ::Rake.application.clear end def run ::Rake.application.tasks[0].invoke end context 'with text_domain is not set' do let(:task) { UpdatePoFiles.new } before do task.files = [ 'test' ] task.app_version = 'test 1.0' # silence abort message STDERR.stub(:write) end it 'should abort' do expect { run }.to raise_error(SystemExit) end end context 'with files is not set' do let(:task) { UpdatePoFiles.new } before do task.text_domain = 'test' task.app_version = 'test 1.0' # silence abort message STDERR.stub(:write) end it 'should abort' do expect { run }.to raise_error(SystemExit) end end context 'with app_version is not set' do let(:task) { UpdatePoFiles.new } before do task.text_domain = 'test' task.files = [ 'test' ] # silence abort message STDERR.stub(:write) end it 'should abort' do expect { run }.to raise_error(SystemExit) end end context 'with text_domain, files and app_version set' do let (:task) { UpdatePoFiles.new } before(:each) do task.text_domain = 'test' task.files = [ 'test' ] task.app_version = 'test 1.0' end it 'should call update_pofiles' do GetText.should_receive(:update_pofiles).with( task.text_domain, task.files, task.app_version, {}) run end it 'should add a parser for ".haml" files to XGetText' do GetText.stub!(:update_pofiles) GetText::Tools::XGetText.should_receive(:add_parser) do |haml_parser| haml_parser.should respond_to(:parse) haml_parser.should be_a_target('example.haml') end run end context 'with lang set' do it 'should pass lang in options' do task.lang = 'pl' GetText.should_receive(:update_pofiles).with( task.text_domain, task.files, task.app_version, hash_including(:lang => task.lang)) run end end context 'with po_root set' do it 'should pass po_root in options' do task.po_root = 'test/po' GetText.should_receive(:update_pofiles).with( task.text_domain, task.files, task.app_version, hash_including(:po_root => task.po_root)) run end end context 'with verbose set' do it 'should pass verbose in options' do task.verbose = true GetText.should_receive(:update_pofiles).with( task.text_domain, task.files, task.app_version, hash_including(:verbose => task.verbose)) run end end end end end haml-magic-translations-4.0.0/spec/spec_helper.rb0000644000004100000410000000106212157374055022041 0ustar www-datawww-data# -*- coding: UTF-8 -*- ENV["RAILS_ENV"] = "test" require 'rubygems' require 'rspec' $:.unshift File.dirname(__FILE__) $:.unshift File.join(File.dirname(__FILE__), '../lib') require 'active_support' require 'action_view' require 'haml/magic_translations' require 'haml/template' Haml::Options.defaults[:ugly] = false Haml::Options.defaults[:format] = :xhtml def render(text, options = {}, &block) scope = options.delete(:scope) || Object.new locals = options.delete(:locals) || {} Haml::Engine.new(text, options).to_html(scope, locals, &block) end haml-magic-translations-4.0.0/VERSION0000644000004100000410000000000612157374055017336 0ustar www-datawww-data4.0.0 haml-magic-translations-4.0.0/metadata.yml0000644000004100000410000001216212157374055020577 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: haml-magic-translations version: !ruby/object:Gem::Version version: 4.0.0 prerelease: platform: ruby authors: - Kriss Kowalik - potager.org autorequire: bindir: bin cert_chain: [] date: 2013-05-28 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: haml requirement: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: '4.0' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: '4.0' - !ruby/object:Gem::Dependency name: haml-contrib requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '1.0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '1.0' - !ruby/object:Gem::Dependency name: actionpack requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: gettext requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '2.3' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '2.3' - !ruby/object:Gem::Dependency name: fast_gettext requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rspec requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '2' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '2' - !ruby/object:Gem::Dependency name: rdoc requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 2.4.2 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 2.4.2 - !ruby/object:Gem::Dependency name: maruku requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' description: ! "This plugin provides \"magical translations\" in your .haml files. What does it\nmean? It's mean that all your raw texts in templates will be automatically\ntranslated by GetText, FastGettext or Gettext backend from I18n. No more \ncomplicated translation keys and ugly translation methods in views. Now you can\nonly write in your language, nothing more. At the end of your work you can easy \nfind all phrases to translate and generate .po files for it. This type of files \nare also more readable and easier to translate, thanks to it you save your \ntime with translations.\n" email: jardiniers@potager.org executables: [] extensions: [] extra_rdoc_files: - LICENSE - README.rdoc files: - LICENSE - README.rdoc - Rakefile - VERSION - haml-magic-translations.gemspec - init.rb - lib/haml-magic-translations.rb - lib/haml/magic_translations.rb - lib/haml/magic_translations/tasks.rb - lib/haml/magic_translations/xgettext/haml_parser.rb - spec/haml/magic_translations/tasks_spec.rb - spec/haml/magic_translations/xgettext/haml_parser_spec.rb - spec/haml/magic_translations_spec.rb - spec/locales/en.po - spec/locales/pl.po - spec/spec_helper.rb homepage: https://github.com/potager/haml-magic-translations licenses: [] post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 1.8.23 signing_key: specification_version: 3 summary: Provides automaticaly translations in haml templates test_files: [] haml-magic-translations-4.0.0/lib/0000755000004100000410000000000012157374055017040 5ustar www-datawww-datahaml-magic-translations-4.0.0/lib/haml/0000755000004100000410000000000012157374055017761 5ustar www-datawww-datahaml-magic-translations-4.0.0/lib/haml/magic_translations.rb0000644000004100000410000001514612157374055024176 0ustar www-datawww-data# -*- coding: UTF-8 -*- require 'haml' require 'json' ## # This plugin provides "magical translations" in your .haml files. What does it # mean? It's mean that all your raw texts in templates will be automatically # translated by GetText, FastGettext or Gettext backend from I18n. No more # complicated translation keys and ugly translation methods in views. Now you can # only write in your language, nothing more. At the end of your work you can easy # find all phrases to translate and generate .po files for it. This type of files # are also more readable and easier to translate, thanks to it you save your # time with translations. # # === Examples # # Now you can write what you want, and at the end of work you # will easy found all phrases to translate. Check out following example: # # %p This is my simple dummy text. # %p And more lorem ipsum... # %p= link_to _("This will be also translated"), "#" # # Those translations are allso allowing you to use standard Haml interpolation. # You can easy write: # # %p This is my text with #{"interpolation".upcase}... Great, isn't it? # # And text from codes above will be stored in .po files as: # # # File test1.haml, line 1 # msgid "This is my simple dummy text" # msgstr "This is my dummy translation of dummy text" # # # File test2.haml, line 1 # msgid "This is my text with %s... Great, isn't it?" # msgstr "Next one %s translation!" # # Generator for .po files also includes information where your phrases are placed # in filesystem. Thanks to it you don't forget about any even small word to # translate. # module Haml::MagicTranslations def self.included(haml) # :nodoc: if defined? Haml::Template Haml::Template.send(:extend, TemplateMethods) end end class Parser < Haml::Parser # Overriden function that parses Haml tags. Injects gettext call for all plain # text lines. def parse_tag(line) tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace, nuke_inner_whitespace, action, value, last_line = super(line) if !value.empty? unless action && action == '=' || action == '!' && value[0] == ?= || action == '&' && value[0] == ?= value, interpolation_arguments = Haml::MagicTranslations.prepare_i18n_interpolation(value) value = "\#{_('#{value.gsub(/'/, "\\\\'")}') % #{interpolation_arguments}\}\n" end end [tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace, nuke_inner_whitespace, action, value, last_line] end # Magical translations will be also used for plain text. def plain(text, escape_html = nil) value, interpolation_arguments = Haml::MagicTranslations.prepare_i18n_interpolation(text, escape_html) value = "_('#{value.gsub(/'/, "\\\\'")}') % #{interpolation_arguments}\n" script(value, !:escape_html) end end class Compiler < Haml::Compiler class << self attr_accessor :magic_translations_helpers end def compile_filter case @node.value[:name] when 'markdown', 'maruku' @node.value[:text] = "\#{_(<<-'END_OF_TRANSLATABLE_MARKDOWN'.rstrip #{@node.value[:text].rstrip.gsub(/\n/, '\n')} END_OF_TRANSLATABLE_MARKDOWN )}" when 'javascript' @node.value[:text].gsub!(/_\(('(([^']|\\')+)'|"(([^"]|\\")+)")\)/) do |m| to_parse = $1[1..-2].gsub(/"/, '\"') parsed_string = JSON.parse("[\"#{to_parse}\"]")[0] parsed_string.gsub!(/'/, "\\\\'") "\#{_('#{parsed_string}').to_json}" end end super end def compile_root @precompiled << "extend #{Compiler.magic_translations_helpers};" super end end # It discovers all fragments of code embeded in text and replacing with # simple string interpolation parameters. # # ==== Example: # # Following line... # # %p This is some #{'Interpolated'.upcase'} text # # ... will be translated to: # # [ "This is some %s text", "['Interpolated'.upcase]" ] # def self.prepare_i18n_interpolation(str, escape_html = nil) args = [] res = '' str = str. gsub(/\n/, '\n'). gsub(/\r/, '\r'). gsub(/\#/, '\#'). gsub(/\"/, '\"'). gsub(/\\/, '\\\\') rest = Haml::Util.handle_interpolation '"' + str + '"' do |scan| escapes = (scan[2].size - 1) / 2 res << scan.matched[0...-3 - escapes] if escapes % 2 == 1 res << '#{' else content = eval('"' + Haml::Util.balance(scan, ?{, ?}, 1)[0][0...-1] + '"') content = "Haml::Helpers.html_escape(#{content.to_s})" if escape_html args << content res << '%s' end end value = res+rest.gsub(/\\(.)/, '\1').chomp value = value[1..-2] unless value.to_s == '' args = "[#{args.join(', ')}]" [value, args] end def self.enabled? @enabled end # Enable magic translations using the given backend # # Supported backends: # # +:i18n+:: Use I18n::Backend::GetText and I18n::GetText::Helpers # from the 'i18n' # +:gettext+:: Use GetText from 'gettext' # +:fast_gettext+:: Use FastGettext::Translation from 'fast_gettext' def self.enable(backend = :i18n) return if @enabled case backend when :i18n require 'i18n' require 'i18n/backend/gettext' require 'i18n/gettext/helpers' I18n::Backend::Simple.send(:include, I18n::Backend::Gettext) Compiler.magic_translations_helpers = I18n::Gettext::Helpers when :gettext require 'gettext' Compiler.magic_translations_helpers = GetText when :fast_gettext require 'fast_gettext' Compiler.magic_translations_helpers = FastGettext::Translation else @enabled = false raise ArgumentError, "Backend #{backend.to_s} is not available in Haml::MagicTranslations" end @original_parser = Haml::Options.defaults[:parser_class] Haml::Options.defaults[:parser_class] = Parser @original_compiler = Haml::Options.defaults[:compiler_class] Haml::Options.defaults[:compiler_class] = Compiler @enabled = true end # Disable magic translations def self.disable return unless @enabled @enabled = false Haml::Options.defaults[:compiler_class] = @original_compiler @original_compiler = nil Haml::Options.defaults[:parser_class] = @original_parser @original_parser = nil Compiler.magic_translations_helpers = nil end module TemplateMethods # :nodoc:all # backward compatibility with versions < 0.3 def enable_magic_translations(backend = :i18n) Haml::MagicTranslations.enable backend end end end Haml::Engine.send(:include, Haml::MagicTranslations) haml-magic-translations-4.0.0/lib/haml/magic_translations/0000755000004100000410000000000012157374055023642 5ustar www-datawww-datahaml-magic-translations-4.0.0/lib/haml/magic_translations/xgettext/0000755000004100000410000000000012157374055025516 5ustar www-datawww-datahaml-magic-translations-4.0.0/lib/haml/magic_translations/xgettext/haml_parser.rb0000644000004100000410000001027212157374055030342 0ustar www-datawww-data# -*- coding: UTF-8 -*- require 'json' require 'haml' require 'haml/magic_translations' module Haml::MagicTranslations::XGetText # :nodoc: # XGetText parser for Haml files # # === Example # # GetText::Tools::XGetText.add_parser(Haml::MagicTranslations::XGetText::HamlParser) # GetText.update_pofiles(text_domain, files, app_version, options) # module HamlParser module_function def target?(file) # :nodoc: File.extname(file) == '.haml' end def parse(file) # :nodoc: XGetTextParser.new(file).parse end class XGetTextParser # :nodoc:all attr_reader :file attr_reader :content def initialize(file) if file.respond_to? :read @file = '(haml)' @content = file.read else @file = file @content = File.open(file).read end end def parse # Engine#initialize parses and compiles HamlEngineCompiler.filename = @file Haml::Engine.new( content, :filename => @file, :parser_class => HamlEngineParser, :compiler_class => HamlEngineCompiler) targets = HamlEngineCompiler.targets HamlEngineCompiler.reset_targets targets end end class HamlEngineParser < Haml::Parser def tag(line) tag_name, attributes, attributes_hashes, object_ref, nuke_outer_whitespace, nuke_inner_whitespace, action, value, last_line = parse_tag(line) if action && (action == '=' || (action == '!' && value[0] == ?=) || (action == '&' && value[0] == ?=)) parsed_tag = true else parsed_tag = false end node = super(line) node[:value][:parsed_tag] = parsed_tag node end end class HamlEngineCompiler < Haml::Compiler class << self attr_accessor :filename def add_target(text, lineno) @targets = {} if @targets.nil? unless text.empty? @targets[text] = [] unless @targets[text] @targets[text].push("#{filename}:#{lineno}") end end def reset_targets @targets = {} end def targets (@targets || {}).keys.sort.collect do |k| [k] + @targets[k] end end end def compile(node) super(node) end def compile_plain HamlEngineCompiler.add_target(@node.value[:text], @node.line) end def compile_doctype # do nothing end def compile_script yield if block_given? end def compile_silent_script yield if block_given? end def compile_tag if @node.value[:parsed_tag] # Search for explicitely translated strings @node.value[:value].gsub(/_\('(([^']|\\')+)'\)/) do |m| parsed_string = "#{$1}" HamlEngineCompiler.add_target(parsed_string, @node.line) end else value = @node.value[:value] if value # strip quotes if needed value = value[1..-2] if @node.value[:parse] value, args = Haml::MagicTranslations.prepare_i18n_interpolation(value) HamlEngineCompiler.add_target(value, @node.line) end end # handle explicit translations in attributes @node.value[:attributes_hashes].each do |hash_string| hash_string.gsub(/_\('(([^']|\\')+)'\)/) do |m| HamlEngineCompiler.add_target($1, @node.line) end end yield if @node.value[:value].nil? && block_given? end def compile_filter case @node.value[:name] when 'markdown', 'maruku' HamlEngineCompiler.add_target(@node.value[:text].rstrip, @node.line) when 'javascript' lineno = 0 @node.value[:text].split(/\r\n|\r|\n/).each do |line| lineno += 1 line.gsub(/_\('(([^']|\\')+)'\)/) do |m| parsed_string = JSON.parse("[\"#{$1}\"]")[0] HamlEngineCompiler.add_target(parsed_string, @node.line + lineno) end end end end end end end haml-magic-translations-4.0.0/lib/haml/magic_translations/tasks.rb0000644000004100000410000000443712157374055025324 0ustar www-datawww-data# -*- coding: UTF-8 -*- require 'rake' require 'rake/tasklib' require 'gettext' require 'gettext/tools' require 'gettext/tools/xgettext' require 'haml/magic_translations/xgettext/haml_parser' module Haml::MagicTranslations::Tasks # :nodoc: # Rake task to generate and update PO files for a project using # Haml::MagicTranslations # # === Example # # Rakefile excerpt: # # Haml::MagicTranslations::Tasks::UpdatePoFiles.new do |t| # t.text_domain = 'my_project' # t.files = Dir.glob("views/**/*.{rb,haml}") << "lib/my_project.rb" # t.app_version = 'my_project 0.1' # end # # Updating PO files in the ++po++ directory will be done by issuing: # # rake update_pofiles # class UpdatePoFiles < ::Rake::TaskLib # The name of the task attr_accessor :name # the textdomain name (see GetText.update_pofiles) attr_accessor :text_domain # an Array of target files, that should be parsed for messages attr_accessor :files # the application information which appears "Project-Id-Version: #app_version" in the pot/po-files attr_accessor :app_version # update files only for one language - the language specified by this option attr_accessor :lang # the root directory of po-files attr_accessor :po_root # an array with the options, passed through to the gnu msgmerge tool # # Symbols are automatically translated to options with dashes, # example: ++[:no_wrap, :no_fuzzy_matching, :sort_output]++ translated to # ++--no-fuzzy-matching --sort-output++. attr_accessor :msgmerge # true to show verbose messages. default is false attr_accessor :verbose def initialize(name = :update_pofiles) @name = name yield self if block_given? define end protected def define desc "Update PO files" task(name) do [ :text_domain, :files, :app_version ].each do |opt| abort "`#{opt}` needs to be set." if send(opt).nil? end options = {} [ :lang, :po_root, :verbose ].each do |opt| options[opt] = send(opt) if send(opt) end GetText::Tools::XGetText.add_parser(Haml::MagicTranslations::XGetText::HamlParser) GetText.update_pofiles(text_domain, files, app_version, options) end end end end haml-magic-translations-4.0.0/lib/haml-magic-translations.rb0000644000004100000410000000004412157374055024101 0ustar www-datawww-datarequire 'haml/magic_translations'