po-to-json-1.0.1/0000755000175000017500000000000013122202046014774 5ustar balasankarcbalasankarcpo-to-json-1.0.1/po_to_json.gemspec0000644000175000017500000000446213122202046020520 0ustar balasankarcbalasankarc######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: po_to_json 1.0.1 ruby lib Gem::Specification.new do |s| s.name = "po_to_json".freeze s.version = "1.0.1" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Thomas Boerger".freeze, "Nubis".freeze] s.date = "2015-11-03" s.description = " Convert gettext PO files to JSON objects so that you can use it in your\n application.\n".freeze s.email = ["thomas@webhippie.de".freeze, "nubis@woobiz.com.ar".freeze] s.files = ["CHANGELOG.md".freeze, "LICENSE".freeze, "README.md".freeze, "lib/po_to_json.rb".freeze, "lib/po_to_json/version.rb".freeze, "spec/fixtures/test.po".freeze, "spec/po_to_json_spec.rb".freeze, "spec/spec_helper.rb".freeze] s.homepage = "https://github.com/webhippie/po_to_json".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 1.9.3".freeze) s.rubygems_version = "2.5.2".freeze s.summary = "Convert gettext PO files to JSON".freeze s.test_files = ["spec/fixtures/test.po".freeze, "spec/po_to_json_spec.rb".freeze, "spec/spec_helper.rb".freeze] if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q.freeze, [">= 0"]) s.add_runtime_dependency(%q.freeze, [">= 1.6.0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) s.add_development_dependency(%q.freeze, [">= 0"]) else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 1.6.0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end else s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 1.6.0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) s.add_dependency(%q.freeze, [">= 0"]) end end po-to-json-1.0.1/CHANGELOG.md0000644000175000017500000000104513122202046016605 0ustar balasankarcbalasankarc# Changelog ## [1.0.1](https://github.com/webhippie/po_to_json/releases/tag/v1.0.1) - 2015-11-03 * Stop using bundler within the core lib (@tboerger) ## [1.0.0](https://github.com/webhippie/po_to_json/releases/tag/v1.0.0) - 2015-03-19 * BREAKING: Made result compatible to current Jed (#4) ## [0.1.0](https://github.com/webhippie/po_to_json/releases/tag/v0.1.0) - 2015-02-19 * Transfer from github.com/nubis/po_to_json (@tboerger) * Added TravisCI, Rubocop and Coveralls (@tboerger) * Updated structure to my opinionated gem style (@tboerger) po-to-json-1.0.1/README.md0000644000175000017500000000457313122202046016264 0ustar balasankarcbalasankarc# PoToJson [![Gem Version](http://img.shields.io/gem/v/po_to_json.svg)](https://rubygems.org/gems/po_to_json) [![Build Status](https://secure.travis-ci.org/webhippie/po_to_json.svg)](https://travis-ci.org/webhippie/po_to_json) [![Code Climate](https://codeclimate.com/github/webhippie/po_to_json.svg)](https://codeclimate.com/github/webhippie/po_to_json) [![Test Coverage](https://codeclimate.com/github/webhippie/po_to_json/badges/coverage.svg)](https://codeclimate.com/github/webhippie/po_to_json) [![Dependency Status](https://gemnasium.com/webhippie/po_to_json.svg)](https://gemnasium.com/webhippie/po_to_json) Convert gettext PO files to JSON to use in your javascript app, based on po2json.pl by [DuckDuckGo, Inc.](http://duckduckgo.com/). Ideally you'll use this on a Rake task that creates JSON versions of your PO files, which can later be used from javascript with [Jed](http://slexaxton.github.io/Jed/) ## Versions This gem is tested on the following versions automated through TravisCI: * Ruby * 1.9.3 * 2.0.0 * 2.1.0 * Json * 1.6.8 * 1.7.7 * 1.8.2 ## Installation ```ruby gem "po_to_json", "~> 0.1.0" ``` ## Usage Most common use would be to generate a Jed ready javascript file. For example, in a Rails project: ```ruby require "po_to_json" json = PoToJson.new( Rails.root.join("locale", "de", "app.po") ).generate_for_jed("de") Rails.root.join("app", "assets", "javascripts", "locale", "de", "app.js").write(json) ``` If you need a pretty json, add `pretty: true` to `generate_for_jed`, like the following example: ```ruby require "po_to_json" json = PoToJson.new( Rails.root.join("locale", "de", "app.po") ).generate_for_jed("de", pretty: true) Rails.root.join("app", "assets", "javascripts", "locale", "de", "app.js").write(json) ``` The javascript file generated has a global "locales" object with an attribute corresponding to the generated language: ```javascript i18n = new Jed(locales["de"]) i18n.gettext("Hello World") // Should evaluate to "Hallo Welt" ``` ## Contributing Fork -> Patch -> Spec -> Push -> Pull Request ## Authors * [Thomas Boerger](https://github.com/tboerger) * [Nubis](https://github.com/nubis) * [Other contributors](https://github.com/webhippie/po_to_json/graphs/contributors) ## License MIT ## Copyright ``` Copyright (c) 2012-2015 Dropmysite.com Copyright (c) 2015 Webhippie ``` po-to-json-1.0.1/spec/0000755000175000017500000000000013122202046015726 5ustar balasankarcbalasankarcpo-to-json-1.0.1/spec/fixtures/0000755000175000017500000000000013122202046017577 5ustar balasankarcbalasankarcpo-to-json-1.0.1/spec/fixtures/test.po0000644000175000017500000000337313122202046021124 0ustar balasankarcbalasankarc# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. msgid "" msgstr "" "Project-Id-Version: version 0.0.1\n" "POT-Creation-Date: 2009-02-26 19:50+0100\n" "PO-Revision-Date: 2011-12-04 18:54+0900\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: app/helpers/translation_helper.rb:3 msgid "%{relative_time} ago" msgstr "vor %{relative_time}" #: app/views/cars/show.html.erb:5 msgid "1 Axis" msgid_plural "%{num} Axis" msgstr[0] "1 Achse" msgstr[1] "%{num} Achsen" #: app/controllers/cars_controller.rb:47 msgid "Car was successfully created." msgstr "Auto wurde erfolgreich gespeichert" #: app/controllers/cars_controller.rb:64 msgid "Car was successfully updated." msgstr "Auto wurde erfolgreich aktualisiert" #: app/views/cars/show.html.erb:1 locale/model_attributes.rb:3 msgid "Car|Model" msgstr "Modell" msgid "Untranslated" msgstr "" #: app/views/cars/show.html.erb:3 locale/model_attributes.rb:4 msgid "Car|Wheels count" msgstr "Räderzahl" #: app/views/cars/show.html.erb:7 msgid "Created" msgstr "Erstellt" #: app/views/cars/show.html.erb:9 msgid "Month" msgstr "Monat" #: locale/model_attributes.rb:2 msgid "car" msgstr "Auto" #: locale/testlog_phrases.rb:2 msgid "this is a dynamic translation which was found!" msgstr "" "Dies ist eine dynamische Übersetzung, die " "gefunden wurde!" #: locale/test_escape.rb:2 msgid "You should escape '\\' as '\\\\'." msgstr "Du solltest '\\' als '\\\\' escapen." msgid "Umläüte" msgstr "Umlaute" po-to-json-1.0.1/spec/po_to_json_spec.rb0000644000175000017500000001205713122202046021443 0ustar balasankarcbalasankarc# -*- coding: UTF-8 -*- # # Copyright (c) 2012-2015 Dropmysite.com # Copyright (c) 2015 Webhippie # # 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. # require "spec_helper" describe PoToJson do let(:po_to_json) do @subject = PoToJson.new( File.expand_path("../fixtures/test.po", __FILE__) ) end describe "parsing" do subject do po_to_json.parse_document end it "should find the last author" do expect(subject[""]["Last-Translator"]).to( eq("FULL NAME ") ) end it "should parse embedded variables" do expect(subject["%{relative_time} ago"]).to( eq(["vor %{relative_time}"]) ) end it "should match pluralizations" do expect(subject["1 Axis"]).to( eq(["1 Achse", "%{num} Achsen"]) ) end it "should match glued values" do expect(subject["Car|Model"]).to( eq(["Modell"]) ) end it "should match embedded glue" do expect(subject["Car|Wheels count"]).to( eq(["Räderzahl"]) ) end it "should return empty strings as well" do expect(subject["Untranslated"]).to( eq([""]) ) end it "should match german umlauts" do expect(subject["Umläüte"]).to( eq(["Umlaute"]) ) end it "should match escaped values" do expect(subject["You should escape '\\\\' as '\\\\\\\\'."]).to( eq(["Du solltest '\\\\' als '\\\\\\\\' escapen."]) ) end it "should match multiline translations" do expect(subject["this is a dynamic translation which was found!"]).to( eq(["Dies ist eine dynamische Übersetzung, die gefunden wurde!"]) ) end it "should match simple strings" do expect(subject["Car was successfully created."]).to( eq(["Auto wurde erfolgreich gespeichert"]) ) expect(subject["Car was successfully updated."]).to( eq(["Auto wurde erfolgreich aktualisiert"]) ) expect(subject["Created"]).to( eq(["Erstellt"]) ) expect(subject["Month"]).to( eq(["Monat"]) ) expect(subject["car"]).to( eq(["Auto"]) ) end end describe "generate jed compatible" do describe "with minified output" do subject do po_to_json.generate_for_jed("de") end it "should output the var definition" do expect( subject.include?("var locales = locales || {}; locales['de'] = ") ).to be_truthy end it "should include domain string" do expect( subject.include?('"domain":"app"') ).to be_truthy end it "should include lang string" do expect( subject.include?('"lang":"de"') ).to be_truthy end it "should include pluralization" do val = '"plural_forms":"nplurals=2; plural=(n != 1);"' expect( subject.include? val ).to be_truthy end it "should include a single line break" do expect( subject.count("\n") ).to be < 1 end end context "with pretty output" do subject do po_to_json.generate_for_jed("de", pretty: true) end it "should output the var definition" do expect( subject.include?("var locales = locales || {}; locales['de'] = ") ).to be_truthy end it "should include domain string" do expect( subject.include?('"domain": "app"') ).to be_truthy end it "should include lang string" do expect( subject.include?('"lang": "de"') ).to be_truthy end it "should include pluralization" do val = '"plural_forms": "nplurals=2; plural=(n != 1);"' expect( subject.include? val ).to be_truthy end it "should include multiple line breaks" do expect( subject.count("\n") ).to be > 0 end end end # describe "generate simple hashes" do # pending "have to be implemented" # end end po-to-json-1.0.1/spec/spec_helper.rb0000644000175000017500000000330313122202046020543 0ustar balasankarcbalasankarc# -*- coding: UTF-8 -*- # # Copyright (c) 2012-2015 Dropmysite.com # Copyright (c) 2015 Webhippie # # 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. # require "simplecov" if ENV["CODECLIMATE_REPO_TOKEN"] require "coveralls" require "codeclimate-test-reporter" Coveralls.wear! CodeClimate::TestReporter.start SimpleCov.start do add_filter "/spec" formatter SimpleCov::Formatter::MultiFormatter[ SimpleCov::Formatter::HTMLFormatter, CodeClimate::TestReporter::Formatter ] end else SimpleCov.start do add_filter "/spec" end end require "po_to_json" require "rspec" RSpec.configure do |config| config.mock_with :rspec end po-to-json-1.0.1/lib/0000755000175000017500000000000013122202046015542 5ustar balasankarcbalasankarcpo-to-json-1.0.1/lib/po_to_json/0000755000175000017500000000000013122202046017713 5ustar balasankarcbalasankarcpo-to-json-1.0.1/lib/po_to_json/version.rb0000644000175000017500000000260713122202046021732 0ustar balasankarcbalasankarc# -*- coding: UTF-8 -*- # # Copyright (c) 2012-2015 Dropmysite.com # Copyright (c) 2015 Webhippie # # 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. # class PoToJson class Version MAJOR = 1 MINOR = 0 PATCH = 1 PRE = nil class << self def to_s [MAJOR, MINOR, PATCH, PRE].compact.join(".") end end end end po-to-json-1.0.1/lib/po_to_json.rb0000644000175000017500000001500713122202046020243 0ustar balasankarcbalasankarc# -*- coding: UTF-8 -*- # # Copyright (c) 2012-2015 Dropmysite.com # Copyright (c) 2015 Webhippie # # 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. # gem "json", version: ">= 1.6.0" require "json" class PoToJson autoload :Version, File.expand_path("../po_to_json/version", __FILE__) attr_accessor :files attr_accessor :glue attr_accessor :options attr_accessor :errors attr_accessor :values attr_accessor :buffer attr_accessor :lastkey attr_accessor :trans def initialize(files, glue = "|") @files = files @glue = glue end def generate_for_jed(language, overwrite = {}) @options = parse_options(overwrite.merge(language: language)) @parsed ||= inject_meta(parse_document) generated = build_json_for(build_jed_for(@parsed)) [ "var #{@options[:variable]} = #{@options[:variable]} || {};", "#{@options[:variable]}['#{@options[:language]}'] = #{generated};" ].join(" ") end def generate_for_json(language, overwrite = {}) @options = parse_options(overwrite.merge(language: language)) @parsed ||= inject_meta(parse_document) generated = build_json_for(build_json_for(@parsed)) fail "Not implemented yet, current value is #{generated}!" end def parse_document reset_buffer reset_result File.foreach(files) do |line| matches_values_for(line.chomp) end flush_buffer parse_header values end def flush_buffer return unless buffer[:msgid] build_trans assign_trans reset_buffer end def parse_header return if reject_header values[""][0].split("\\n").each do |line| next if line.empty? build_header_for(line) end values[""] = headers end def reject_header if values[""].nil? || values[""][0].nil? values[""] = {} true else false end end protected def trans @trans ||= [] end def errors @errors ||= [] end def values @values ||= {} end def buffer @buffer ||= {} end def headers @headers ||= {} end def lastkey @lastkey ||= "" end def reset_result @values = {} @errors = [] end def reset_buffer @buffer = {} @trans = [] @lastkey = "" end def detect_ctxt msgctxt = buffer[:msgctxt] msgid = buffer[:msgid] if msgctxt && msgctxt.size > 0 [msgctxt, glue, msgid].join("") else msgid end end def detect_plural plural = buffer[:msgid_plural] plural if plural && plural.size > 0 end def build_trans buffer.each do |key, string| trans[$1.to_i] = string if key.to_s.match(/^msgstr_(\d+)/) end # trans.unshift(detect_plural) if detect_plural end def assign_trans values[detect_ctxt] = trans if trans.size > 0 end def push_buffer(value, key = nil) value = $1 if value =~ /^"(.*)"/ value.gsub(/\\"/, "\"") if key.nil? buffer[lastkey] = [ buffer[lastkey], value ].join("") else buffer[key] = value @lastkey = key end end def parse_options(options) defaults = { pretty: false, domain: "app", variable: "locales" } defaults.merge(options) end def inject_meta(hash) hash[""]["lang"] ||= options[:language] hash[""]["domain"] ||= options[:domain] hash[""]["plural_forms"] ||= hash[""]["Plural-Forms"] hash end def build_header_for(line) if line =~ /(.*?):(.*)/ key, value = $1, $2 if headers.key? key errors.push "Duplicate header: #{line}" elsif key =~ /#-#-#-#-#/ errors.push "Marked header: #{line}" else headers[key] = value.strip end else errors.push "Malformed header: #{line}" end end def build_json_for(hash) if options[:pretty] JSON.pretty_generate(hash) else JSON.generate(hash) end end def build_jed_for(hash) { domain: options[:domain], locale_data: { options[:domain] => hash } } end def matches_values_for(line) return if generic_rejects? line return if generic_detects? line return if iterate_detects_for(line) errors.push "Strange line #{line}" end def iterate_detects_for(line) specific_detects.each do |detect| match = line.match(detect[:regex]) if match if detect[:index] push_buffer(match[detect[:index]], detect[:key].call(match)) else push_buffer(line) end return true end end false end def generic_rejects?(line) if line.match(/^$/) || line.match(/^(#[^~]|[#]$)/) flush_buffer && true else false end end def generic_detects?(line) match = line.match(/^(?:#~ )?msgctxt\s+(.*)/) if match push_buffer( match[1], :msgctxt ) return true end false end def specific_detects [{ regex: /^(?:#~ )?msgctxt\s+(.*)/, index: 1, key: proc { :msgctxt } }, { regex: /^(?:#~ )?msgid\s+(.*)/, index: 1, key: proc { :msgid } }, { regex: /^(?:#~ )?msgid_plural\s+(.*)/, index: 1, key: proc { :msgid_plural } }, { regex: /^(?:#~ )?msgstr\s+(.*)/, index: 1, key: proc { :msgstr_0 } }, { regex: /^(?:#~ )?msgstr\[0\]\s+(.*)/, index: 1, key: proc { :msgstr_0 } }, { regex: /^(?:#~ )?msgstr\[(\d+)\]\s+(.*)/, index: 2, key: proc { |m| "msgstr_#{m[1]}".to_sym } }, { regex: /^(?:#~ )?"/, index: nil }] end end po-to-json-1.0.1/LICENSE0000644000175000017500000000221713122202046016003 0ustar balasankarcbalasankarcThe MIT License (MIT) Copyright (c) 2012-2015 Dropmysite.com Copyright (c) 2015 Webhippie 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.