├── .ruby-version ├── spec ├── lib │ ├── files │ │ └── .gitkeep │ ├── yamlfile_spec.rb │ ├── cache_spec.rb │ ├── utils_spec.rb │ ├── sourcefiles_spec.rb │ └── keys_spec.rb ├── internal │ ├── tmp │ │ └── .gitkeep │ ├── log │ │ └── .gitignore │ ├── public │ │ └── favicon.ico │ ├── app │ │ ├── views │ │ │ ├── categories │ │ │ │ ├── category.html │ │ │ │ ├── category.html.erb │ │ │ │ └── category.rhtml │ │ │ └── application │ │ │ │ └── index.html.erb │ │ ├── assets │ │ │ ├── stylesheets │ │ │ │ └── application.css │ │ │ └── javascripts │ │ │ │ └── application.js │ │ ├── controllers │ │ │ └── application_controller.rb │ │ └── models │ │ │ └── article.rb │ ├── config │ │ ├── database.yml │ │ └── routes.rb │ └── db │ │ ├── combustion_test.sqlite │ │ └── schema.rb ├── selenium │ ├── translation_spec.rb │ ├── nav_spec.rb │ └── sauce.rb ├── requests │ └── search_spec.rb ├── spec_helper.rb └── controllers │ └── translate_controller_spec.rb ├── app ├── assets │ ├── images │ │ └── rails_i18nterface │ │ │ └── .gitkeep │ ├── javascripts │ │ └── rails_i18nterface │ │ │ ├── application.js │ │ │ ├── base.js │ │ │ └── ender.min.js │ └── stylesheets │ │ └── rails_i18nterface │ │ └── application.css ├── views │ ├── rails_i18nterface │ │ └── translate │ │ │ ├── _namespaces.html.erb │ │ │ ├── _pagination.html.erb │ │ │ └── index.html.erb │ └── layouts │ │ └── rails_i18nterface │ │ └── translate.html.erb ├── controllers │ └── rails_i18nterface │ │ ├── application_controller.rb │ │ └── translate_controller.rb └── helpers │ └── rails_i18nterface │ └── translate_helper.rb ├── .rubocop.yml ├── .rspec ├── Gemfile ├── .coveralls.yml ├── .travis.yml ├── lib ├── rails-i18nterface │ ├── version.rb │ ├── engine.rb │ ├── cache.rb │ ├── yamlfile.rb │ ├── translation.rb │ ├── utils.rb │ ├── sourcefiles.rb │ └── keys.rb ├── tasks │ └── rails-i18nterface.rake └── rails-i18nterface.rb ├── .gitignore ├── config.ru ├── config ├── routes.rb └── initializers │ └── missing_translation.rb ├── Rakefile ├── MIT-LICENSE ├── rails-i18nterface.gemspec ├── changelog.md └── README.md /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.3 2 | -------------------------------------------------------------------------------- /spec/lib/files/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/internal/tmp/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/internal/log/.gitignore: -------------------------------------------------------------------------------- 1 | *.log -------------------------------------------------------------------------------- /spec/internal/public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/images/rails_i18nterface/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | LineLength: 2 | Enabled: true 3 | Max: 120 -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --colour 2 | #--format documentation 3 | #--profile 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | gemspec 4 | 5 | -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | repo_token: H32sdgiIgE6YtfVPsnVl9P44umeilO7RH 2 | -------------------------------------------------------------------------------- /app/views/rails_i18nterface/translate/_namespaces.html.erb: -------------------------------------------------------------------------------- 1 |

Namespaces

-------------------------------------------------------------------------------- /spec/internal/app/views/categories/category.html: -------------------------------------------------------------------------------- 1 | t(:'category_html.key1') 2 | -------------------------------------------------------------------------------- /spec/internal/app/views/categories/category.html.erb: -------------------------------------------------------------------------------- 1 | <%= t(:'category_html_erb.key1') %> 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | cache: bundler 3 | rvm: 4 | - 2.1.5 5 | - 2.3.3 6 | sudo: false 7 | -------------------------------------------------------------------------------- /spec/internal/app/views/application/index.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | index 4 | 5 | -------------------------------------------------------------------------------- /spec/internal/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | *= require rails_i18nterface/application 3 | */ -------------------------------------------------------------------------------- /spec/internal/config/database.yml: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: sqlite3 3 | database: db/combustion_test.sqlite 4 | -------------------------------------------------------------------------------- /spec/internal/app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | //= require rails_i18nterface/application 2 | I18n.t('js.alert') -------------------------------------------------------------------------------- /lib/rails-i18nterface/version.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module RailsI18nterface 4 | VERSION = '0.3.0' 5 | end 6 | -------------------------------------------------------------------------------- /spec/internal/db/combustion_test.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mose/rails-i18nterface/HEAD/spec/internal/db/combustion_test.sqlite -------------------------------------------------------------------------------- /lib/tasks/rails-i18nterface.rake: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # desc "Explaining what the task does" 3 | # task :translate do 4 | # # Task goes here 5 | # end 6 | -------------------------------------------------------------------------------- /spec/internal/app/views/categories/category.rhtml: -------------------------------------------------------------------------------- 1 | 4 | 5 | <%= t(:'category_rhtml.key1') %> 6 | -------------------------------------------------------------------------------- /spec/internal/config/routes.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | Rails.application.routes.draw do 4 | root to: 'application#index' 5 | mount RailsI18nterface::Engine => '/translate', as: 'translate_engine' 6 | end 7 | -------------------------------------------------------------------------------- /lib/rails-i18nterface/engine.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'rails' 4 | 5 | module RailsI18nterface 6 | class Engine < ::Rails::Engine 7 | isolate_namespace RailsI18nterface 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/internal/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | class ApplicationController < ActionController::Base 4 | 5 | def index 6 | @title = I18n.t 'title' 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/rails_i18nterface/application_controller.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module RailsI18nterface 4 | class ApplicationController < ActionController::Base 5 | protect_from_forgery with: :exception 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Gemfile.lock 2 | .rvmrc 3 | /node_modules 4 | *.gem 5 | /coverage/ 6 | /tmp 7 | 8 | /spec/internal/tmp/cache/ 9 | /spec/internal/tmp/translation_strings 10 | /spec/internal/log/* 11 | 12 | /vendor/ 13 | /.bundle/ 14 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler' 3 | 4 | #Bundler.require :default, :development 5 | require 'combustion' 6 | require 'rails-i18nterface' 7 | #require 'sqlite3' 8 | 9 | Combustion.initialize! :action_controller, :action_view, :sprockets 10 | Combustion::Application.config.name = 'c' 11 | 12 | run Combustion::Application 13 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | RailsI18nterface::Engine.routes.draw do 4 | root to: 'translate#index' 5 | 6 | put '/translate' => 'translate#update' 7 | get '/reload' => 'translate#reload', as: 'translate_reload' 8 | get '/export' => 'translate#export', as: 'translate_export' 9 | post '/delete/*del' => 'translate#destroy', format: false 10 | end 11 | -------------------------------------------------------------------------------- /lib/rails-i18nterface.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'rails-i18nterface/engine' 4 | require 'rails-i18nterface/utils' 5 | require 'rails-i18nterface/cache' 6 | require 'rails-i18nterface/yamlfile' 7 | require 'rails-i18nterface/sourcefiles' 8 | require 'rails-i18nterface/keys' 9 | require 'rails-i18nterface/translation' 10 | 11 | module RailsI18nterface 12 | end 13 | -------------------------------------------------------------------------------- /config/initializers/missing_translation.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module RailsI18nterface 4 | module UseKeyForMissing 5 | def call(exception, locale, key, options) 6 | if exception.is_a?(I18n::MissingTranslation) 7 | ("\x00" + key.to_s.split(/\./)[-1] + "\x0b").html_safe 8 | else 9 | super 10 | end 11 | end 12 | end 13 | end 14 | 15 | I18n.exception_handler.extend RailsI18nterface::UseKeyForMissing 16 | -------------------------------------------------------------------------------- /app/views/layouts/rails_i18nterface/translate.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%= @page_title %> 6 | <%= stylesheet_link_tag 'rails_i18nterface/application' %> 7 | <%= javascript_include_tag 'rails_i18nterface/application' %> 8 | 9 | 10 |
11 | <%= yield %> 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /app/assets/javascripts/rails_i18nterface/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into including all the files listed below. 2 | // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically 3 | // be included in the compiled file accessible from http://example.com/assets/application.js 4 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 5 | // the compiled file. 6 | // 7 | //= require rails_i18nterface/ender 8 | //= require rails_i18nterface/base 9 | -------------------------------------------------------------------------------- /spec/internal/app/models/article.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | class Article 4 | 5 | def validate 6 | # rubocop : disable all 7 | something([t(:'article.key1') + "#{t('article.key2')}"]) 8 | I18n.t 'article.key3' 9 | I18n.t 'article.key3' 10 | I18n.t :'article.key4', count: 3 11 | I18n.translate :'article.key5' 12 | 'bla bla t("blubba bla") foobar' 13 | 'bla bla t ' + "blubba bla" + ' foobar' 14 | I18n.t :'article.key6', :count => 3 15 | I18n.t :symbol_key 16 | # rubocop : enable all 17 | end 18 | 19 | def something 20 | end 21 | 22 | end 23 | -------------------------------------------------------------------------------- /spec/internal/db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | ActiveRecord::Schema.define do 4 | # rubocop : disable all 5 | 6 | create_table "article", force: true do |t| 7 | t.string "title", :null => false 8 | t.string "body" 9 | t.datetime "created_at" 10 | t.datetime "updated_at" 11 | t.boolean "active", default: true 12 | end 13 | 14 | create_table "topics", force: true do |t| 15 | t.string "title", :null => false 16 | t.datetime "created_at" 17 | t.datetime "updated_at" 18 | end 19 | # rubocop : enable all 20 | 21 | end 22 | -------------------------------------------------------------------------------- /spec/selenium/translation_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'spec_helper' 4 | require 'selenium/sauce' 5 | 6 | describe 'translation' do 7 | 8 | it 'phase 1', js: true do 9 | visit 'http://localhost:3000/translate' 10 | expect(page.first(:xpath, "/html/body/div/div[2]/form/div[3]/div/div/span").text).to eq 'activerecord.attributes.article.active' 11 | link = page.first(:xpath, "/html/body/div/div/ul/li/span") 12 | link.click 13 | expect(page.first(:xpath, "/html/body/div/div[2]/form/div[3]/div/div/span").text).to eq 'title' 14 | end 15 | 16 | it 'phase 2', js: true do 17 | end 18 | 19 | end 20 | -------------------------------------------------------------------------------- /lib/rails-i18nterface/cache.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module RailsI18nterface 4 | module Cache 5 | 6 | def cache_save(obj, uri) 7 | FileUtils.rm uri if File.exists? uri 8 | File.open(uri, 'wb') do |f| 9 | Marshal.dump(obj, f) 10 | end 11 | obj 12 | end 13 | 14 | def cache_load(uri, options = {}, &process) 15 | if File.exists? uri 16 | load uri 17 | elsif block_given? 18 | cache_save(yield(options), uri) 19 | else 20 | nil 21 | end 22 | end 23 | 24 | private 25 | 26 | def load(uri) 27 | File.open(uri) do |f| 28 | Marshal.load f 29 | end 30 | end 31 | 32 | 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/rails-i18nterface/yamlfile.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'fileutils' 4 | 5 | module RailsI18nterface 6 | class Yamlfile 7 | 8 | include Utils 9 | 10 | attr_reader :path 11 | 12 | def initialize(root_dir, locale) 13 | @root_dir = root_dir 14 | @locale = locale 15 | @file_path = File.join(@root_dir, 'config', 'locales', "#{locale}.yml") 16 | end 17 | 18 | def write(hash) 19 | FileUtils.mkdir_p File.dirname(@file_path) 20 | File.open(@file_path, 'w') do |file| 21 | file.puts keys_to_yaml(hash) 22 | end 23 | end 24 | 25 | def read 26 | File.exists?(@file_path) ? YAML.load(IO.read(@file_path)) : {} 27 | end 28 | 29 | def write_to_file 30 | keys = { @locale => I18n.backend.send(:translations)[@locale] } 31 | write remove_blanks(keys) 32 | end 33 | 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | begin 3 | require 'bundler/setup' 4 | rescue LoadError 5 | puts 'You must `gem install bundler` and `bundle install` to run rake tasks' 6 | end 7 | require 'bundler/setup' 8 | 9 | require "bundler/gem_tasks" 10 | #Bundler::GemHelper.install_tasks 11 | 12 | require "rake/testtask" 13 | 14 | require "rspec/core/rake_task" # RSpec 2.0 15 | 16 | desc "launch rspec tests" 17 | task :spec do 18 | RSpec::Core::RakeTask.new(:spec) do |t| 19 | t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"] 20 | t.pattern = 'spec/{controllers,lib,requests}/*_spec.rb' 21 | end 22 | end 23 | 24 | desc "launch selenium tests on SauceLabs" 25 | task :sauce do 26 | RSpec::Core::RakeTask.new(:sauce) do |t| 27 | t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"] 28 | t.pattern = 'spec/selenium/*_spec.rb' 29 | end 30 | end 31 | 32 | task :default => :spec 33 | 34 | 35 | -------------------------------------------------------------------------------- /lib/rails-i18nterface/translation.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module RailsI18nterface 4 | class Translation 5 | 6 | attr_accessor :files, :persisted 7 | attr_reader :key, :from_text, :to_text, :lines, :id 8 | 9 | def initialize(key, from, to) 10 | @key = key 11 | @from_text = lookup(from, key) 12 | @to_text = lookup(to, key) 13 | @lines = n_lines(@to_text) 14 | @id = key.gsub(/\./, '_') 15 | @files = [] 16 | @persisted = true 17 | end 18 | 19 | def lookup(locale, key) 20 | I18n.backend.send(:lookup, locale, key) 21 | end 22 | 23 | def n_lines(text) 24 | n_lines = 1 25 | line_size = 100 26 | if text.present? 27 | n_lines = text.to_s.split("\n").size 28 | n_lines = text.to_s.length / line_size + 1 if n_lines == 1 && text.to_s.length > line_size 29 | end 30 | n_lines 31 | end 32 | 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/selenium/nav_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'spec_helper' 4 | require 'selenium/sauce' 5 | 6 | describe 'What about the navigation' do 7 | 8 | it 'unfold an item when clicked', js: true do 9 | visit 'http://localhost:3000/translate' 10 | expect(page).to have_selector(:xpath, "/html/body/div/div/ul/li") 11 | expect(page.first(:xpath, "/html/body/div/div/ul/li/ul")).to be_nil 12 | page.first(:xpath, "/html/body/div/div/ul/li").click 13 | expect(page.first(:xpath, "/html/body/div/div/ul/li/ul")).not_to be_nil 14 | end 15 | 16 | it 'displays the inside elements from a namespace', js: true do 17 | visit 'http://localhost:3000/translate' 18 | expect(page.first(:xpath, "/html/body/div/div[2]/form/div[3]/div/div/span").text).to eq 'activerecord.attributes.article.active' 19 | page.first(:xpath, "/html/body/div/div/ul/li/span").click 20 | expect(page.first(:xpath, "/html/body/div/div[2]/form/div[3]/div/div/span").text).to eq 'title' 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /spec/lib/yamlfile_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'spec_helper' 4 | 5 | describe RailsI18nterface::Yamlfile do 6 | 7 | include RailsI18nterface::Utils 8 | 9 | before :each do 10 | @translations = { en: { a: { aa: 'aa' }, b: 'b' } } 11 | end 12 | 13 | describe 'write' do 14 | before(:each) do 15 | @root_dir = File.expand_path(File.join('..', '..', '..', 'spec', 'internal'), __FILE__) 16 | @file_path = File.join(@root_dir, 'config', 'locales', 'en.yml') 17 | @file = RailsI18nterface::Yamlfile.new(@root_dir, :en) 18 | end 19 | 20 | after(:each) do 21 | FileUtils.rm(@file_path) if File.exists? @file_path 22 | end 23 | 24 | it 'writes all I18n messages for a locale to YAML file' do 25 | @file.write(@translations) 26 | expect(@file.read).to eq deep_stringify_keys(@translations) 27 | end 28 | 29 | end 30 | 31 | describe 'deep_stringify_keys' do 32 | it 'should convert all keys in a hash to strings' do 33 | expected = { 'en' => { 'a' => { 'aa' => 'aa' }, 'b' => 'b' } } 34 | expect(deep_stringify_keys @translations).to eq expected 35 | end 36 | end 37 | 38 | end 39 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2009 Peter Marklund, Joakim Westerlund, Claudius Coenen 2 | Copyright 2011 Larry Sprock, Artin Boghosain, Michal Hantl 3 | Copyright 2013 Mose 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /spec/lib/cache_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'spec_helper' 4 | 5 | describe RailsI18nterface::Cache do 6 | include RailsI18nterface::Cache 7 | 8 | let(:cachefile) { File.expand_path(File.join('..', 'files', 'cache_test'), __FILE__) } 9 | 10 | after { FileUtils.rm cachefile if File.exists? cachefile } 11 | 12 | describe '.save' do 13 | let(:a) { { a: 'a' } } 14 | before { cache_save a, cachefile } 15 | it 'stores cache of an object' do 16 | expect(File.exists? cachefile).to be_truthy 17 | end 18 | end 19 | 20 | describe '.load' do 21 | context 'reads cache from marshalled file' do 22 | let(:a) { { a: 'a' } } 23 | let(:b) { cache_load cachefile } 24 | before { cache_save a, cachefile } 25 | it { expect(b).to eq a } 26 | end 27 | 28 | context 'when the cache if not present' do 29 | before { 30 | @b = cache_load cachefile do 31 | 20 32 | end 33 | } 34 | it { expect(@b).to be 20 } 35 | it { expect(File.exists? cachefile).to be_truthy } 36 | end 37 | 38 | context 'when the cache if not present, using an argument' do 39 | before { 40 | @b = cache_load cachefile, 'something' do |options| 41 | options 42 | end 43 | } 44 | it { expect(@b).to eq 'something' } 45 | it { expect(File.exists? cachefile).to be_truthy } 46 | end 47 | end 48 | 49 | 50 | end 51 | -------------------------------------------------------------------------------- /spec/requests/search_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'spec_helper' 4 | 5 | describe 'searching' do 6 | 7 | describe 'keys' do 8 | 9 | context 'using contains' do 10 | it 'finds the correct keys' do 11 | visit '/translate' 12 | select 'Key contains', from: 'key_type' 13 | fill_in 'key_pattern', with: 'ey2' 14 | click_button 'Search' 15 | expect(page).to have_content 'key2' 16 | end 17 | end 18 | 19 | context 'using starts with' do 20 | it 'finds the correct keys' do 21 | visit '/translate' 22 | select 'Key starts with', from: 'key_type' 23 | fill_in 'key_pattern', with: 'article.k' 24 | click_button 'Search' 25 | expect(page).to have_content 'article.key2' 26 | end 27 | end 28 | 29 | end 30 | 31 | describe 'values' do 32 | 33 | context 'using contains' do 34 | it 'finds the correct values' do 35 | visit '/translate' 36 | select 'contains', from: 'text_type' 37 | fill_in 'text_pattern', with: '1 year' 38 | click_button 'Search' 39 | expect(page).to have_content 'over 1 year' 40 | end 41 | end 42 | 43 | context 'using equals' do 44 | it 'finds the correct values' do 45 | visit '/translate' 46 | select 'equals', from: 'text_type' 47 | fill_in 'text_pattern', with: 'over 1 year' 48 | click_button 'Search' 49 | expect(page).to have_content 'over 1 year' 50 | end 51 | end 52 | 53 | end 54 | 55 | end 56 | -------------------------------------------------------------------------------- /spec/selenium/sauce.rb: -------------------------------------------------------------------------------- 1 | if ENV['sauce'] 2 | 3 | module Job 4 | module_function 5 | 6 | def id 7 | @__jobid || 'undefined' 8 | end 9 | 10 | def id=(j) 11 | @__jobid ||= j 12 | end 13 | 14 | def failed? 15 | !!@__failed 16 | end 17 | 18 | def fails 19 | @__failed = true 20 | end 21 | 22 | def build 23 | Time.now.to_i.to_s 24 | end 25 | 26 | end 27 | 28 | require 'sauce/capybara' 29 | require 'rest_client' 30 | 31 | Capybara.javascript_driver = :sauce 32 | Sauce.config do |c| 33 | c[:browsers] = [ 34 | ["Windows 7", "iehta", "9"] 35 | ] 36 | end 37 | 38 | RSpec.configure do |config| 39 | config.after :each do 40 | Job.id = page.driver.browser.send(:bridge).session_id 41 | Job.fails unless example.exception.nil? 42 | end 43 | 44 | config.after :suite do 45 | http = "https://saucelabs.com/rest/v1/#{ENV["SAUCE_USERNAME"]}/jobs/#{Job.id}" 46 | body = { 47 | name: "RailsI18nterface", 48 | passed: !Job.failed?, 49 | public: 'public', 50 | tags: ['rails-i18nterface'], 51 | build: Job.build, 52 | "custom-data" => { version: RailsI18nterface::VERSION } 53 | }.to_json 54 | # puts 'http: ' + http 55 | # puts 'body: ' + body 56 | RestClient::Request.execute( 57 | :method => :put, 58 | :url => http, 59 | :user => ENV["SAUCE_USERNAME"], 60 | :password => ENV["SAUCE_ACCESS_KEY"], 61 | :headers => {:content_type => "application/json"}, 62 | :payload => body 63 | ) 64 | end 65 | end 66 | 67 | end 68 | 69 | -------------------------------------------------------------------------------- /rails-i18nterface.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | # Maintain your gem's version: 4 | require "rails-i18nterface/version" 5 | 6 | # Describe your gem and declare its dependencies: 7 | Gem::Specification.new do |s| 8 | s.name = "rails-i18nterface" 9 | s.version = RailsI18nterface::VERSION 10 | s.authors = ["Mose"] 11 | s.email = ["mose@mose.com"] 12 | s.homepage = "https://github.com/mose/rails-i18nterface" 13 | s.summary = "A rails engine for translating in a web page." 14 | s.description = "A rails engine adding an interface for translating and writing translation files. Works with rails 3 and 4." 15 | s.license = "MIT" 16 | 17 | s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.md"] 18 | s.test_files = Dir["spec/**/*"] 19 | 20 | s.add_dependency "railties", ">= 3.1.0" 21 | s.add_dependency "rake", ">= 3.1.0" 22 | 23 | s.add_development_dependency "tzinfo", ">= 0.3.37" 24 | s.add_development_dependency "combustion", '~> 0.5.3' 25 | s.add_development_dependency "rspec", '~> 3.5.0' 26 | s.add_development_dependency "rspec-rails", '~> 3.5.0' 27 | s.add_development_dependency "rspec-mocks" 28 | s.add_development_dependency "sprockets-rails" 29 | s.add_development_dependency "activemodel" 30 | s.add_development_dependency "test-unit" 31 | s.add_development_dependency "capybara" 32 | s.add_development_dependency "simplecov" 33 | s.add_development_dependency "metric_fu" 34 | s.add_development_dependency "rubocop" 35 | s.add_development_dependency "coveralls" 36 | s.add_development_dependency "sauce", '~> 3.5.11' 37 | s.add_development_dependency "rest-client" 38 | s.add_development_dependency "rails-controller-testing" 39 | 40 | end 41 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | ENV['RAILS_ENV'] ||= 'test' 4 | $LOAD_PATH << File.expand_path('../../lib', __FILE__) 5 | 6 | require 'rubygems' 7 | require 'bundler' 8 | require 'combustion' 9 | 10 | require 'rails-controller-testing' 11 | Rails::Controller::Testing.install 12 | 13 | if ENV['COV'] 14 | require 'simplecov' 15 | SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ 16 | SimpleCov::Formatter::HTMLFormatter, 17 | ] 18 | SimpleCov.start do 19 | add_filter '/spec/' 20 | add_filter '/config/' 21 | add_filter '/db/' 22 | add_filter '/vendor/' 23 | add_group 'Models', '/app/models/' 24 | add_group 'Controllers', '/app/controllers/' 25 | add_group 'Helpers', '/app/helpers/' 26 | add_group 'Lib', '/lib/' 27 | end 28 | else 29 | require 'coveralls' 30 | Coveralls.wear! 31 | end 32 | 33 | Bundler.require :default, :test 34 | 35 | require 'capybara/rspec' 36 | 37 | Combustion.initialize! :action_controller, :action_view, :sprockets 38 | 39 | require 'rspec/rails' 40 | 41 | require 'capybara/rails' 42 | require 'rails-i18nterface' 43 | 44 | Capybara.server_port = 9090 45 | 46 | RSpec.configure do |config| 47 | config.mock_with :rspec 48 | config.expect_with :rspec do |c| 49 | c.syntax = :expect 50 | end 51 | config.include RailsI18nterface::Engine.routes.url_helpers 52 | config.before(:each) do 53 | allow(RailsI18nterface::Keys).to receive(:i18n_keys).and_return(:en) 54 | allow(I18n).to receive(:default_locale).and_return(:en) 55 | allow(I18n).to receive(:available_locales).and_return([:sv, :no, :en, :root]) 56 | end 57 | end 58 | 59 | # improve the performance of the specs suite by not logging anything 60 | # see http://blog.plataformatec.com.br/2011/12/three-tips-to-improve-the-performance-of-your-test-suite/ 61 | Rails.logger.level = 4 62 | 63 | -------------------------------------------------------------------------------- /app/helpers/rails_i18nterface/translate_helper.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | module RailsI18nterface 4 | 5 | # various views helpers 6 | module TranslateHelper 7 | 8 | def simple_filter(labels, param_name = 'filter') 9 | filter = [] 10 | labels.each do |label| 11 | if label.to_s == params[param_name].to_s 12 | filter << "#{label}" 13 | else 14 | link_params = @filter_params.to_h.merge(param_name.to_s => label) 15 | link_params.merge!('page' => nil) if param_name.to_s != 'page' 16 | filter << link_to(label, link_params) 17 | end 18 | end 19 | filter.join(' | ') 20 | end 21 | 22 | def build_namespace(h) 23 | out = '' 41 | out << list_namespace('', dirs) 42 | end 43 | 44 | def list_namespace(k, h) 45 | out = '' 62 | end 63 | 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /app/assets/javascripts/rails_i18nterface/base.js: -------------------------------------------------------------------------------- 1 | $.domReady(function() { 2 | function getFocus() { 3 | url = window.location.href; 4 | m = url.indexOf("key_pattern"); 5 | if (m !== -1) { 6 | focus = url.slice(url.indexOf("=", m)+1, url.indexOf("&", m)); 7 | } else { 8 | focus = false; 9 | } 10 | return focus; 11 | } 12 | function openNav(focus) { 13 | if (focus) { 14 | if (focus === '.') { 15 | items = ['.']; 16 | } else if (!focus.indexOf('.')) { 17 | items = ['ROOT',focus]; 18 | } else { 19 | items = focus.split(/\./); 20 | } 21 | namespace = []; 22 | while (it = items.shift()) { 23 | namespace.push(it); 24 | join = namespace.join('.'); 25 | it = $("#namespaces span[data-id='"+join+"']"); 26 | if (it.length > 0) { 27 | $(it.selector).siblings("ul").toggleClass("view"); 28 | } 29 | } 30 | } 31 | return; 32 | } 33 | var focus = getFocus(); 34 | openNav(focus); 35 | function filterThat(s,start) { 36 | if (start) { 37 | $("#key_type").val("starts_with"); 38 | } else { 39 | $("#key_type").val("contains"); 40 | } 41 | $("#key_pattern_value").val(s); 42 | document.forms['filter_form'].submit(); 43 | } 44 | $("#namespaces ul li").on("click", function(e) { 45 | e.preventDefault(); 46 | e.stopPropagation(); 47 | $(this).children("ul").toggleClass("view"); 48 | }); 49 | $("#namespaces ul li .display").on("click", function(e) { 50 | e.preventDefault(); 51 | e.stopPropagation(); 52 | filter = $(this).data("id"); 53 | filterThat(filter,true); 54 | }); 55 | $("#namespaces ul li.item").on("click", function(e) { 56 | e.preventDefault(); 57 | e.stopPropagation(); 58 | filter = $(this).data("id"); 59 | filterThat(filter,false); 60 | }); 61 | $(".delete").on("click", function(e) { 62 | e.preventDefault(); 63 | e.stopPropagation(); 64 | key = $(this).previous().text(); 65 | if (confirm("Are you sure you want to delete the key "+key+" from database ?")) { 66 | var newF = document.createElement("form"); 67 | newF.action = 'delete/'+key; 68 | newF.method = 'POST'; 69 | document.getElementsByTagName('body')[0].appendChild(newF); 70 | newF.submit(); 71 | } 72 | }); 73 | $(".multiline").on('click', function(e) { 74 | e.preventDefault(); 75 | input = $(this).next(); 76 | area = $.create('