idioma 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +91 -0
- data/Rakefile +28 -0
- data/app/assets/javascripts/idioma/application.js +15 -0
- data/app/assets/javascripts/idioma/phrases.js.coffee +35 -0
- data/app/assets/stylesheets/idioma/application.css.scss +26 -0
- data/app/assets/stylesheets/idioma/forms.css.scss +19 -0
- data/app/assets/stylesheets/idioma/phrases.css +4 -0
- data/app/controllers/idioma/application_controller.rb +4 -0
- data/app/controllers/idioma/phrases_controller.rb +96 -0
- data/app/helpers/idioma/application_helper.rb +4 -0
- data/app/helpers/idioma/phrases_helper.rb +4 -0
- data/app/models/idioma/phrase.rb +115 -0
- data/app/models/idioma/phrase_exporter.rb +69 -0
- data/app/models/idioma/phrase_extractor.rb +49 -0
- data/app/models/idioma/phrase_importer.rb +50 -0
- data/app/models/idioma/redis_backend.rb +22 -0
- data/app/views/idioma/phrases/index.html.haml +45 -0
- data/app/views/layouts/idioma/application.html.haml +22 -0
- data/config/locales/idioma.en.yml +20 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20140709015052_create_idioma_phrases.rb +14 -0
- data/lib/concerns/models/date_flag.rb +96 -0
- data/lib/idioma/engine.rb +27 -0
- data/lib/idioma/version.rb +3 -0
- data/lib/idioma.rb +23 -0
- data/lib/tasks/idioma_tasks.rake +15 -0
- data/lib/templates/erb/scaffold/_form.html.erb +13 -0
- data/spec/controllers/phrases_controller_spec.rb +91 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +25 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +28 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +83 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/i18n.rb +4 -0
- data/spec/dummy/config/initializers/idioma.rb +9 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20141115171836_create_idioma_phrases.idioma.rb +15 -0
- data/spec/dummy/db/schema.rb +30 -0
- data/spec/dummy/log/development.log +25637 -0
- data/spec/dummy/log/test.log +4291 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/0a79a4ff6e73052b217cd977d4b50fdc54118d68/_bootstrap-sprockets.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/0a79a4ff6e73052b217cd977d4b50fdc54118d68/_bootstrap.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_alerts.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_background-variant.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_border-radius.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_buttons.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_center-block.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_clearfix.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_forms.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_gradients.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_grid-framework.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_grid.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_hide-text.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_image.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_labels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_list-group.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_nav-divider.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_nav-vertical-align.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_opacity.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_pagination.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_panels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_progress-bar.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_reset-filter.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_resize.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_responsive-visibility.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_size.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_tab-focus.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_table-row.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_text-emphasis.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_text-overflow.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/388135616c2e0e4a55abea5d6089cd23176cca81/_vendor-prefixes.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_alerts.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_background-variant.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_border-radius.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_buttons.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_center-block.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_clearfix.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_forms.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_gradients.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_grid-framework.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_grid.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_hide-text.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_image.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_labels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_list-group.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_nav-divider.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_nav-vertical-align.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_opacity.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_pagination.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_panels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_progress-bar.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_reset-filter.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_resize.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_responsive-visibility.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_size.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_tab-focus.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_table-row.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_text-emphasis.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_text-overflow.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/6d2c3dd352078ee620f88d0e68cd2a546af6caa9/_vendor-prefixes.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a3c1058d9af83b2a8b1bfae5d618b8a18753385f/_bootstrap-sprockets.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a3c1058d9af83b2a8b1bfae5d618b8a18753385f/_bootstrap.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_alerts.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_badges.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_breadcrumbs.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_button-groups.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_buttons.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_carousel.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_close.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_code.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_component-animations.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_dropdowns.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_forms.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_glyphicons.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_grid.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_input-groups.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_jumbotron.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_labels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_list-group.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_media.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_mixins.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_modals.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_navbar.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_navs.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_normalize.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_pager.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_pagination.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_panels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_popovers.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_print.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_progress-bars.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_responsive-embed.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_responsive-utilities.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_scaffolding.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_tables.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_thumbnails.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_tooltip.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_type.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_utilities.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_variables.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/a7efb1bfb1ea736b4b985c80527151a3e8b6dbc6/_wells.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/d940cd7e88bf0a9500208e10220e6b529d01020b/application.css.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/d940cd7e88bf0a9500208e10220e6b529d01020b/forms.css.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_alerts.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_badges.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_breadcrumbs.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_button-groups.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_buttons.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_carousel.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_close.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_code.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_component-animations.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_dropdowns.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_forms.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_glyphicons.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_grid.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_input-groups.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_jumbotron.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_labels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_list-group.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_media.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_mixins.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_modals.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_navbar.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_navs.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_normalize.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_pager.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_pagination.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_panels.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_popovers.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_print.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_progress-bars.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_responsive-embed.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_responsive-utilities.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_scaffolding.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_tables.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_thumbnails.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_tooltip.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_type.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_utilities.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_variables.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sass/ea7b58bf4bbb3d8d5abf667eec7914942f653de6/_wells.scssc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/02ecd6370f91c7b9aa00319b7b66ca57 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/034fda66e03e8dcfacf72397fb1616fb +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/0372d3378d1aec4dd7f546428d9d84df +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/071b598f6568db8d75333d67e6a54477 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/0faf8e82aa4c81c82c3d5efd58fcaae2 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1665127ceea38e019fda9859305342a7 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/16b4a10fdb8214557970232c41d57362 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1750899b365166d7cfff321fe7fa7acd +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/17e0784a695845bd1a32dd1346c280ea +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1ad97a1fb78577c298b407d3d2cc4226 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1c146cfb664a6770a3d20305f8baaee3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1d53471c5ad320073dda367e45390e1a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1f6b42e6726c8b498066fc910a16e643 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/25a65c717fc9c64ba1aba14d1c14ffee +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/291cfa25c65c3163a5815d67b5f62756 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2acbd5c6f7047cd0e95f86968fd19f46 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2e4f3bcd559a961bc58e2a0e84792662 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2f31bab0beabd5a3f5c34b4e907a34fc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/306a635124154ffdea9b8e8ce8b61410 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/30e642c26825645592d13dd299e19a65 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3312b404b988f9a8763bd1c06b9952ef +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3487ff606d58ba5df51a1117dba8c84b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/357d6ae318d42fc558676b425c1a9e78 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/361cc4bdb4a3f33a6ba7e9a7db1a5407 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3636dd32d14102a55225b245bd2a6489 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/36874c0716e0da5db2dde7cf47dec6ca +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/39ce7471b9ff1c273b4f1518b5aba8f0 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3b25a99aa1b8d0f87755ebd53f3d7fc6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3bf04cff80d6513190387eea44e4589f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3c284cbc7d309735cbebcaddf4467d71 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3d067ab624734ad0663d1425c5b201c1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3fb41299c66c3e363e841ca3d76b11b7 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4063ddd81171d5b6dc967ca64faeca75 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/40ca1415d6ca19cdf937bbc542925af9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/40e3a16192cb5bd3559b3abe6b31cefe +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/43f257974098a37cabc9a61314b816f5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/44657b24ddb307d1e7f85ad2ecca2e10 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/458ca3a8c2f4224a08e724716a2f17d4 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4a368dccbd67682ba64048d4b24fd8a6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4a85c925086e64caf1d1b700d916bdbd +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/4ce8718297a50cd3d658b5952cd8c220 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/510c6fd27db7dfbaf0a0b0875e1a472c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/52601bfc1fdc6967ffc898526bb67c48 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/52f63d83d0a7b86318e8de59538598ce +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5369fbbcf397cc9d96948fe373705d13 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/56435206e505c649b556d17094d68fda +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5814911eaed8f6e6be8c46d6b9cb880f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/58f4e4ba656d78cf623d22cca4e118d9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5d2ca5f96ec23ecb6926eb3732d45e40 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/650130979c39b20be8a1c9af85b76638 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6a9bec079f93d94c0dbf4b7faa1441ad +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6c75734197a9efc5a8a3a6ca1064eb41 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6f388bb30dc94599b503d0d9091f1d8a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6f88ef16a3db4dfcde35acff34596af9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6f894580ff1180ef27e44fb54bfec225 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6f9d821dc32360a03e328a188908175f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7002ce8d64dafbc1a536eeeb902218c0 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7005283a4d4bbbdee421e3479dc12cef +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7311218619b974306177cebe229dc84c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/744470be6e2c66f767dd3796ce78f559 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/75e87583a132b975027118095bf4818f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/764d58940328aaefb24a04bef44b3789 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/76736f185d75c28fcb1a476ae52cf30e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/772600c69b884a0036fb15de213d3232 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7a3ccc02bfad9d04783b020d3dcdb67f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7da54db8bdd56cd00dc338448b263424 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7f402d16975bdcfc442e9cef98821840 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7f992b68655a9d27c89d97eeeaae5cff +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/812a0d810b679dbb7f5d512beef887c8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/81cfdb55475e7b7a5a63ffe9c204673c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/81fce3ac36b10e033b9264e39a76d90a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/83dafa375dd3513360fd7b4553f44113 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/846430db48a99b44ec1b08022d0276ad +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8747b295bb7c63b1388aef97cfb67b3c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/87bf4781cd1e8b52a4b8fc2c0e379531 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8960bbc70a2914b7ed8e6f7b5b04359f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8abcaf5a11cddb7b0c2aa424bd1e3b80 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/90edf8db23ea1dbf263e6391e93a483d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/92871f270f3bebaf37c07d62016a3d7e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/933dfcd36b972a52fa603f5234bd1e7e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/960b52015983bd58ede5592a759c08fb +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/96eb906f063e4ce8718416772a28ddda +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/97c07e644cabf01abcec894d4e69d985 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/9d2af4036fcf352fd6695966ba8e0006 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a011ecbdccaea9b25d06cedffa60f15b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a200c1f26bc11623541b221d0b819a31 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a3900259c72f7f6917024284b8bdc4fb +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a45d05646c5fc237f0a7419ba456eaaa +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a4819b17d0802ac0d8d7e2a9d1832752 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a57c75e1396ec82ae78589a9ae6b3861 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a5d6adcfd6cbc7beef744d02302d0a8c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a6e5e94828ebb7680a0a1499dda39e2c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ada1d0f8bc5368b25d6fbaa8a95b4ef8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ada35950e2733da1d227585deb4a09fd +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/aefe71c7ac3edd29fbbb6a3e4bfe84a4 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b0376faf689d528b625a5a88ef0dcc7a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b7e39ee40edb822dde438cae9f5b0987 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b8c774f83a302c891103bdf82662bc8d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/bb86516784ddda57801c5b5ca185e838 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/be81012acaf20ecb9f67c32dbc2ee5ae +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/bfa847822a8d7778ab5f8b469491b114 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c7e523ec10215d71cb5d98fe9e069b35 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c82292a064ec438357e22805eee89191 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c843a7a53cf4a5dc94dfea6a59f04e4f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d05de76ba0f58b49a47dea63d2a5b4a6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d5022437eeb42f08dd710ee8f240de2a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d71a839bca3a6881f8b7b42b7f05bda6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d976a7c91926f70a3e80c2603de3bf69 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/dd677fcb17536b3f6c2bf936f571a02e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/df9a7d2c532e121a104d5b63b4441b2d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e29bdfdcad985cd8d26e1d31a09f00b1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e46bf23d379db0e7483b2ccc0fbff9f3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e5fa939c3fa26ae0df54d40f316bec75 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e6f47dfc8b9542ee9c6f54b1ecfde664 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e75d8f8a9ec139a10086a83dca74e9b3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/eb29baddef1d85815159f3d1089e3be4 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/efa76e374b3ab82bde4b35f9d76d9caf +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f1262794e42011b8c57f36f71b9815a0 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f5268ce26d4948c182f520c4df83b261 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f6f7145113c3cd4e160e3d39f7f1f56b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f757aee56e52254e2fb14b4f6424c937 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/fbf4527e3604500e4c3521c4fd2deaf6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ff4769a8564990f599f4e977ccd8e661 +0 -0
- data/spec/dummy/tmp/pids/server.pid +1 -0
- data/spec/dummy/tmp/restart.txt +0 -0
- data/spec/factories/phrase.rb +8 -0
- data/spec/models/phrase_exporter_spec.rb +38 -0
- data/spec/models/phrase_extractor_spec.rb +53 -0
- data/spec/models/phrase_importer_spec.rb +30 -0
- data/spec/models/phrase_spec.rb +80 -0
- data/spec/spec_helper.rb +23 -0
- metadata +851 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 4297d3391e67e66042c2a6572edf9e8928bdd39a
|
|
4
|
+
data.tar.gz: 3d9c1f1a8c2efb1b012a008a7ee12fb145543af5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 3c071cda64b47acf5fbb7653edb39c5bebe920a823dee0b28847120a5c1c584fc525ea2f1323d09349b888de58317d5b09bfa8a9a2a5547547b634b1942a3413
|
|
7
|
+
data.tar.gz: 449f8cd93ddc4c1fac4a435d0b189ed9afe3f496c73d18b93957326f47bcc6cf6dbab74ef37fecb3bfb4542c33269b311589b98601a7064bbd5e575f1a8fa175
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2014 YOURNAME
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Idioma
|
|
2
|
+
|
|
3
|
+
Idioma is a Ruby Engine to help manage the flow and editing of translations.
|
|
4
|
+
|
|
5
|
+
### Current Features
|
|
6
|
+
* Imports translations into database from the config yaml files.
|
|
7
|
+
* Interface for managing translations.
|
|
8
|
+
* Duplicate translations from one locale to other locales.
|
|
9
|
+
* DB changes will be persisted to Redis I18n backend store if supplied.
|
|
10
|
+
* Exports translations from DB into CSV and YAML formats.
|
|
11
|
+
|
|
12
|
+
### Pending Features
|
|
13
|
+
* Import translations from CSV into DB.
|
|
14
|
+
* Stats on each locale, giving percentage of translated/missing.
|
|
15
|
+
* Test persisting to Redis using https://github.com/guilleiguaran/fakeredis
|
|
16
|
+
* Improve interface by converting into SPA with Angular.
|
|
17
|
+
|
|
18
|
+
### Starting
|
|
19
|
+
Add it to your gemfile.
|
|
20
|
+
```ruby
|
|
21
|
+
gem 'idioma'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Mount it in your config/routes.rb.
|
|
25
|
+
```ruby
|
|
26
|
+
# config/routes.rb
|
|
27
|
+
MyApp::Application.routes.draw do
|
|
28
|
+
mount Idioma::Engine => "/idioma"
|
|
29
|
+
end
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Security
|
|
33
|
+
You can secure access to the Idioma interface by using [route constraints](http://guides.rubyonrails.org/routing.html#request-based-constraints).
|
|
34
|
+
|
|
35
|
+
Example 1 by IP address.
|
|
36
|
+
```ruby
|
|
37
|
+
# config/routes.rb
|
|
38
|
+
idioma_constraint = lambda { |request| request.remote_ip == '127.0.0.1' }
|
|
39
|
+
constraints idioma_constraint do
|
|
40
|
+
mount Idioma::Engine => "/idioma"
|
|
41
|
+
end
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Example 2 by using Devise or another warden based authentication system.
|
|
45
|
+
```ruby
|
|
46
|
+
# config/routes.rb
|
|
47
|
+
idioma_constraint = lambda do |request|
|
|
48
|
+
current_user = request.env['warden'].user
|
|
49
|
+
current_user.present? && current_user.respond_to?(:is_admin?) && current_user.is_admin?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
constraints idioma_constraint do
|
|
53
|
+
mount Idioma::Engine => "/idioma"
|
|
54
|
+
end
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Configuration
|
|
58
|
+
Setting | Default | Description
|
|
59
|
+
------- | ------- | -----------
|
|
60
|
+
default_locale | :en | Used for showing the default translation (for translators to translate from) for a given phrase
|
|
61
|
+
locales | [:en] | Idioma will only import translations of locales in this list... ignoring the rest
|
|
62
|
+
ignore_keys | ["ransack", "simple_form"] | Gems sometimes bring their own phrases that you don't actually need translated
|
|
63
|
+
redis_backend | nil | Should be an I18n backend of a Redis store.
|
|
64
|
+
|
|
65
|
+
### Setup
|
|
66
|
+
Import the migrations into your application
|
|
67
|
+
```
|
|
68
|
+
rake idioma:install:migrations
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
To populate the idioma_phrases table with translations from your locales/yaml files.
|
|
72
|
+
```
|
|
73
|
+
rake idioma:import_from_extraction
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
To duplicate all translations from a locale to a new locale (as untranslated).
|
|
77
|
+
```
|
|
78
|
+
rake idioma:duplicate_for_locales base_locale=en new_locale=es
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Example
|
|
82
|
+
```ruby
|
|
83
|
+
$redis = Redis.new(:host => 'localhost', :port => 6379)
|
|
84
|
+
I18n.backend = I18n::Backend::KeyValue.new($redis)
|
|
85
|
+
|
|
86
|
+
Idioma.configure do |configure|
|
|
87
|
+
configure.default_locale = :en
|
|
88
|
+
configure.locales = [:en, :es, :fr]
|
|
89
|
+
configure.redis_backend = I18n.backend
|
|
90
|
+
end
|
|
91
|
+
```
|
data/Rakefile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Idioma'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
|
18
|
+
load 'rails/tasks/engine.rake'
|
|
19
|
+
|
|
20
|
+
Bundler::GemHelper.install_tasks
|
|
21
|
+
|
|
22
|
+
require 'rspec/core'
|
|
23
|
+
require 'rspec/core/rake_task'
|
|
24
|
+
|
|
25
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
|
26
|
+
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
|
27
|
+
|
|
28
|
+
task :default => :spec
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
|
2
|
+
// listed below.
|
|
3
|
+
//
|
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
6
|
+
//
|
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
+
// compiled file.
|
|
9
|
+
//
|
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
|
11
|
+
// about supported directives.
|
|
12
|
+
//
|
|
13
|
+
//= require_tree .
|
|
14
|
+
//= require jquery
|
|
15
|
+
//= require bootstrap-sprockets
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
window.InlinePhraseUpdater = class InlinePhraseUpdater
|
|
2
|
+
constructor: () ->
|
|
3
|
+
# attributes
|
|
4
|
+
@phraseInputs = $(".i18n_value")
|
|
5
|
+
|
|
6
|
+
# events
|
|
7
|
+
@phraseInputs.on "focus", (e) => @setOriginalValue(e)
|
|
8
|
+
@phraseInputs.on "blur", (e) => @updateIfChanged(e)
|
|
9
|
+
|
|
10
|
+
# init
|
|
11
|
+
|
|
12
|
+
setOriginalValue: (e) =>
|
|
13
|
+
phraseInput = $(e.target)
|
|
14
|
+
phraseInput.data("original", phraseInput.val())
|
|
15
|
+
|
|
16
|
+
updateIfChanged: (e) =>
|
|
17
|
+
phraseInput = $(e.target)
|
|
18
|
+
if phraseInput.data("original") != phraseInput.val()
|
|
19
|
+
@updateStatus(phraseInput, "status-working")
|
|
20
|
+
$.ajax(
|
|
21
|
+
type: "PUT"
|
|
22
|
+
url: phraseInput.data("url")
|
|
23
|
+
dataType: "json"
|
|
24
|
+
data:
|
|
25
|
+
phrase:
|
|
26
|
+
i18n_value: phraseInput.val()
|
|
27
|
+
).done((data) =>
|
|
28
|
+
@updateStatus(phraseInput, "status-success")
|
|
29
|
+
).fail((data) =>
|
|
30
|
+
@updateStatus(phraseInput, "status-error")
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
updateStatus: (input, status) ->
|
|
34
|
+
input.removeClass("status-success").removeClass("status-error").removeClass("status-working")
|
|
35
|
+
input.addClass(status)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
+
* listed below.
|
|
4
|
+
*
|
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
|
7
|
+
*
|
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
|
11
|
+
* file per style scope.
|
|
12
|
+
*
|
|
13
|
+
*= require_tree .
|
|
14
|
+
*= require_self
|
|
15
|
+
*/
|
|
16
|
+
@import "bootstrap-sprockets";
|
|
17
|
+
@import "bootstrap";
|
|
18
|
+
|
|
19
|
+
body {
|
|
20
|
+
padding-top: 50px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.highlight {
|
|
24
|
+
padding: 10px;
|
|
25
|
+
background-color: #f8f8f8;
|
|
26
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.search {
|
|
2
|
+
.form-group {
|
|
3
|
+
padding-right: 10px;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
label {
|
|
7
|
+
margin-right: 10px;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.status-working {
|
|
12
|
+
border-color: yellow !important;
|
|
13
|
+
}
|
|
14
|
+
.status-success {
|
|
15
|
+
border-color: green !important;
|
|
16
|
+
}
|
|
17
|
+
.status-error {
|
|
18
|
+
border-color: red !important;
|
|
19
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#require_dependency "idioma/application_controller"
|
|
2
|
+
|
|
3
|
+
module Idioma
|
|
4
|
+
class PhrasesController < ApplicationController
|
|
5
|
+
before_action :set_phrase, only: [:edit, :update, :show]
|
|
6
|
+
|
|
7
|
+
# GET /phrases
|
|
8
|
+
def index
|
|
9
|
+
params[:locale] ||= I18n.default_locale
|
|
10
|
+
scope = Phrase.where(locale: params[:locale])
|
|
11
|
+
|
|
12
|
+
if params[:q].present?
|
|
13
|
+
scope = scope.where("i18n_key ilike ? OR i18n_value ilike ?", "%#{params[:q]}%", "%#{params[:q]}%")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
respond_to do |format|
|
|
17
|
+
format.html {
|
|
18
|
+
@phrases = scope.paginate(:page => params[:page])
|
|
19
|
+
}
|
|
20
|
+
format.csv {
|
|
21
|
+
render text: PhraseExporter.to_csv(scope)
|
|
22
|
+
}
|
|
23
|
+
format.yaml {
|
|
24
|
+
render text: PhraseExporter.to_yaml(scope)
|
|
25
|
+
}
|
|
26
|
+
format.json {
|
|
27
|
+
@phrases = scope.paginate(:page => params[:page])
|
|
28
|
+
render json: {
|
|
29
|
+
meta: {
|
|
30
|
+
pagination: {
|
|
31
|
+
current_page: @phrases.current_page,
|
|
32
|
+
per_page: @phrases.per_page,
|
|
33
|
+
total_entries: @phrases.total_entries
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
phrases: @phrases
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# GET /phrases/1
|
|
44
|
+
def show
|
|
45
|
+
respond_to do |format|
|
|
46
|
+
format.json {
|
|
47
|
+
render json: @phrase
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# PATCH/PUT /phrases/1
|
|
53
|
+
def update
|
|
54
|
+
result = @phrase.update_and_update_backend(phrase_params)
|
|
55
|
+
respond_to do |format|
|
|
56
|
+
format.html {
|
|
57
|
+
if result
|
|
58
|
+
redirect_to [:edit, @phrase], flash: {success: t('idioma.record_updated')}
|
|
59
|
+
else
|
|
60
|
+
render :edit
|
|
61
|
+
end
|
|
62
|
+
}
|
|
63
|
+
format.json {
|
|
64
|
+
if result
|
|
65
|
+
render json: @phrase
|
|
66
|
+
else
|
|
67
|
+
render json: {
|
|
68
|
+
errors: @phrase.errors.messages
|
|
69
|
+
}.merge(@phrase.attributes),
|
|
70
|
+
status: :bad_request
|
|
71
|
+
end
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
# Use callbacks to share common setup or constraints between actions.
|
|
79
|
+
def set_phrase
|
|
80
|
+
@phrase = Phrase.find(params[:id])
|
|
81
|
+
rescue ActiveRecord::RecordNotFound
|
|
82
|
+
respond_to do |format|
|
|
83
|
+
format.json { render json: {}.to_json, status: :not_found }
|
|
84
|
+
format.html {
|
|
85
|
+
flash[:error] = t('idioma.record_not_found')
|
|
86
|
+
redirect_to phrases_path
|
|
87
|
+
}
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Only allow a trusted parameter "white list" through.
|
|
92
|
+
def phrase_params
|
|
93
|
+
params.require(:phrase).permit(:locale, :i18n_key, :i18n_value, :flagged_at, :notes)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
module Idioma
|
|
2
|
+
class Phrase < ActiveRecord::Base
|
|
3
|
+
|
|
4
|
+
# == Constants ============================================================
|
|
5
|
+
|
|
6
|
+
# == Attributes ===========================================================
|
|
7
|
+
|
|
8
|
+
# == Extensions ===========================================================
|
|
9
|
+
|
|
10
|
+
# == Relationships ========================================================
|
|
11
|
+
|
|
12
|
+
# == Validations ==========================================================
|
|
13
|
+
|
|
14
|
+
validates :locale, :i18n_key, presence: true
|
|
15
|
+
validates :i18n_key, uniqueness: { scope: :locale }
|
|
16
|
+
|
|
17
|
+
# == Scopes ===============================================================
|
|
18
|
+
|
|
19
|
+
scope :translated, lambda { where("translated_at is not null") }
|
|
20
|
+
scope :untranslated, lambda { where("translated_at is null") }
|
|
21
|
+
scope :missing, lambda { where("i18n_value is null") }
|
|
22
|
+
|
|
23
|
+
# == Callbacks ============================================================
|
|
24
|
+
|
|
25
|
+
before_validation :strip_values
|
|
26
|
+
|
|
27
|
+
# == Class Methods ========================================================
|
|
28
|
+
|
|
29
|
+
# Given a base locale, duplicate all phrases to a set of other locales
|
|
30
|
+
#
|
|
31
|
+
# @param [Symbol] The base locale
|
|
32
|
+
# @param [Array] An array of other locales
|
|
33
|
+
def self.duplicate_for_locales(base_locale, locales)
|
|
34
|
+
locales = [locales] unless locales.class == Array
|
|
35
|
+
where(locale: base_locale).find_each do |base_phrase|
|
|
36
|
+
locales.each do |locale|
|
|
37
|
+
unless where(locale: locale, i18n_key: base_phrase.i18n_key).exists?
|
|
38
|
+
phrase = Phrase.create!({
|
|
39
|
+
locale: locale,
|
|
40
|
+
i18n_key: base_phrase.i18n_key
|
|
41
|
+
})
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Take what's in the database and prime the i18n backend store (Redis)
|
|
48
|
+
def self.prime_backend
|
|
49
|
+
find_each do |phrase|
|
|
50
|
+
phrase.update_backend
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# == Instance Methods =====================================================
|
|
55
|
+
|
|
56
|
+
# Update the record and then push those changes to the i18n backend
|
|
57
|
+
#
|
|
58
|
+
# @param [Hash] The Phrase attributes to update
|
|
59
|
+
# @return [Boolean] Whether the update was successful
|
|
60
|
+
def update_and_update_backend(params = {})
|
|
61
|
+
self.translated_at = Time.zone.now if self.untranslated?
|
|
62
|
+
|
|
63
|
+
result = self.update(params)
|
|
64
|
+
if result
|
|
65
|
+
self.update_backend
|
|
66
|
+
end
|
|
67
|
+
result
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Save and push the changes to the i18n backend
|
|
71
|
+
#
|
|
72
|
+
# @param [Hash] The Phrase attributes to save
|
|
73
|
+
# @return [Boolean] Whether the save was successful
|
|
74
|
+
def save_and_update_backend(params = {})
|
|
75
|
+
result = self.save(params)
|
|
76
|
+
if result
|
|
77
|
+
self.update_backend
|
|
78
|
+
end
|
|
79
|
+
result
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Will update the i18n backend if it has been configured
|
|
83
|
+
def update_backend
|
|
84
|
+
if Idioma.configuration.redis_backend
|
|
85
|
+
if i18n_value.present?
|
|
86
|
+
Idioma::RedisBackend.update_phrase(self)
|
|
87
|
+
else
|
|
88
|
+
Idioma::RedisBackend.delete_phrase(self)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Is this phrase translated?
|
|
94
|
+
# @return [Boolean]
|
|
95
|
+
def translated?
|
|
96
|
+
translated_at.present?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Is this phrase untranslated?
|
|
100
|
+
# @return [Boolean]
|
|
101
|
+
def untranslated?
|
|
102
|
+
!translated?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
# Strip the values before validating the model
|
|
108
|
+
def strip_values
|
|
109
|
+
[:i18n_value].each do |field|
|
|
110
|
+
self.send("#{field}=", self.send(field).to_s.strip)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
module Idioma
|
|
2
|
+
class PhraseExporter
|
|
3
|
+
|
|
4
|
+
# Produce a CSV string of Phrases based on a scope
|
|
5
|
+
# @param [ActiveRecord::Relation] From the Phrase model
|
|
6
|
+
# @return [String] in CSV format
|
|
7
|
+
def self.to_csv(scope)
|
|
8
|
+
require 'csv'
|
|
9
|
+
CSV.generate do |csv_object|
|
|
10
|
+
csv_object << [
|
|
11
|
+
I18n.t("idioma.locale"),
|
|
12
|
+
I18n.t("idioma.key"),
|
|
13
|
+
I18n.t("idioma.value"),
|
|
14
|
+
I18n.t("idioma.translated")
|
|
15
|
+
]
|
|
16
|
+
scope.find_each do |phrase|
|
|
17
|
+
csv_object << [
|
|
18
|
+
phrase.locale,
|
|
19
|
+
phrase.i18n_key,
|
|
20
|
+
phrase.i18n_value,
|
|
21
|
+
phrase.translated_at.present? ? I18n.t('idioma.ans_yes') : I18n.t('idioma.ans_no')
|
|
22
|
+
]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Produce a YAML string of Phrases based on a scope
|
|
28
|
+
# @param [ActiveRecord::Relation] From the Phrase model
|
|
29
|
+
# @return [String] in YAML format
|
|
30
|
+
def self.to_yaml(scope)
|
|
31
|
+
phrases = scope.order(:locale, :i18n_key).pluck(:locale, :i18n_key, :i18n_value)
|
|
32
|
+
|
|
33
|
+
phrase_hash = phrases.each_with_object({}) do |phrase, hsh|
|
|
34
|
+
hsh["#{phrase[0]}.#{phrase[1]}"] = phrase[2]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
to_nested_hash(phrase_hash).to_yaml
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# Will take a flat hash with dot notation (en.errors.invalid) keys and
|
|
43
|
+
# convert it to a nested hash.
|
|
44
|
+
#
|
|
45
|
+
# Example: {"en.hello" => "Hi"} becomes {"en" => {"hello" => "Hi"}}
|
|
46
|
+
#
|
|
47
|
+
# @param [Hash] Flat hash with dot notation keys
|
|
48
|
+
# @return [Hash] Nested hash
|
|
49
|
+
def self.to_nested_hash(input_hash)
|
|
50
|
+
input_hash.each_with_object({}) do |(key, value), hsh|
|
|
51
|
+
hsh.deep_merge!(dot_keys_to_hash(key.split("."), value))
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Will take an array of keys and a value, and convert this into a nested
|
|
56
|
+
# hash.
|
|
57
|
+
# @param [Array] Of keys
|
|
58
|
+
# @param [Object] Any value
|
|
59
|
+
# @return [Hash] Nested hash using the keys and value
|
|
60
|
+
def self.dot_keys_to_hash(keys, value)
|
|
61
|
+
if keys.length == 1
|
|
62
|
+
{keys.first => value}
|
|
63
|
+
else
|
|
64
|
+
{keys.shift => dot_keys_to_hash(keys, value)}
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Idioma
|
|
2
|
+
class PhraseExtractor
|
|
3
|
+
|
|
4
|
+
# Find all of the translations that are in the locale yaml files
|
|
5
|
+
# and convert them into a hash of dotted hash notation key/values
|
|
6
|
+
# for each locale that is found
|
|
7
|
+
# @return [Hash] Dotted hash notation key/value pairs
|
|
8
|
+
def self.extract
|
|
9
|
+
phrase_hashes = self.get_translations
|
|
10
|
+
|
|
11
|
+
phrase_dotted_hashes = {}
|
|
12
|
+
# convert each locales translations to dotted hash
|
|
13
|
+
phrase_hashes.each do |locale, phrase_hash|
|
|
14
|
+
phrase_dotted_hashes[locale] = self.to_dotted_hash(phrase_hash)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
phrase_dotted_hashes
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Get translations from the i18n backend
|
|
21
|
+
# @param [I18n::Backend, nil] A custom I18n backend
|
|
22
|
+
# @return [Hash] of translations separated by locale
|
|
23
|
+
def self.get_translations(backend = nil)
|
|
24
|
+
backend = I18n::Backend::Simple.new if backend.nil?
|
|
25
|
+
backend.send(:init_translations)
|
|
26
|
+
backend.send(:translations)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Convert a nested Hash ({date: {format: {long: "YYYY-MM-DD"}}})
|
|
30
|
+
# to a dotted hash {"date.format.long" => "YYYY-MM-DD"}
|
|
31
|
+
# @param [Hash] Nested hash input
|
|
32
|
+
# @param [Hash, {}] An accumulator to store the result
|
|
33
|
+
# @param [String, nil] An accumulator for the key that gets built up
|
|
34
|
+
# @return [Hash] The end result after the conversion
|
|
35
|
+
def self.to_dotted_hash(source, accumulator = {}, namespace = nil)
|
|
36
|
+
prefix = "#{namespace}." if namespace
|
|
37
|
+
case source
|
|
38
|
+
when Hash
|
|
39
|
+
source.each do |key, value|
|
|
40
|
+
to_dotted_hash(value, accumulator, "#{prefix}#{key}")
|
|
41
|
+
end
|
|
42
|
+
else
|
|
43
|
+
accumulator[namespace] = source
|
|
44
|
+
end
|
|
45
|
+
accumulator
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Idioma
|
|
2
|
+
class PhraseImporter
|
|
3
|
+
|
|
4
|
+
# Import all of the locales and phrases from the extraction
|
|
5
|
+
# The extraction comes from Idioma::PhraseExtractor.extract
|
|
6
|
+
def self.import_from_extraction
|
|
7
|
+
phrases = Idioma::PhraseExtractor.extract
|
|
8
|
+
phrases.each do |locale, locale_phrases|
|
|
9
|
+
next unless Idioma.configuration.locales.include?(locale.to_sym)
|
|
10
|
+
self.import(locale, locale_phrases)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# For a given locale, impot its phrases
|
|
15
|
+
#
|
|
16
|
+
# @param [Symbol] the locale, eg. :en
|
|
17
|
+
# @param [Hash] a hash of phrases which are already in dot-notation
|
|
18
|
+
def self.import(locale, locale_phrases)
|
|
19
|
+
locale_phrases.each do |key, value|
|
|
20
|
+
next if self.ignore_key?(key)
|
|
21
|
+
|
|
22
|
+
phrase = Idioma::Phrase.find_by(locale: locale, i18n_key: key)
|
|
23
|
+
if !phrase
|
|
24
|
+
phrase = Idioma::Phrase.new({
|
|
25
|
+
locale: locale,
|
|
26
|
+
i18n_key: key,
|
|
27
|
+
i18n_value: value,
|
|
28
|
+
translated_at: Time.zone.now
|
|
29
|
+
})
|
|
30
|
+
elsif phrase.untranslated?
|
|
31
|
+
phrase.i18n_value = value
|
|
32
|
+
phrase.translated_at = Time.zone.now if value.present?
|
|
33
|
+
end
|
|
34
|
+
phrase.save_and_update_backend
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Checks to see if a given key should be ignored based on the ignore_keys array
|
|
39
|
+
#
|
|
40
|
+
# @param [String] The key to check against
|
|
41
|
+
# @return [Boolean] Whether to ignore this key or not
|
|
42
|
+
def self.ignore_key?(key)
|
|
43
|
+
Idioma.configuration.ignore_keys.each do |ignore_key|
|
|
44
|
+
return true if key.to_s.include?(ignore_key)
|
|
45
|
+
end
|
|
46
|
+
false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Idioma
|
|
2
|
+
|
|
3
|
+
# Class for dealing with deleting and updating phrases in the i18n backend.
|
|
4
|
+
# This is specifically when the backend is Redis
|
|
5
|
+
class RedisBackend
|
|
6
|
+
|
|
7
|
+
# Delete a given Phrase from Redis
|
|
8
|
+
# @param [Phrase] The Phrase to delete
|
|
9
|
+
# @return [Boolean] Result of the del command in Redis
|
|
10
|
+
def self.delete_phrase(phrase)
|
|
11
|
+
Idioma.configuration.redis_backend.store.del("#{phrase.locale}.#{phrase.i18n_key}")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Update (or create) a Phrase in Redis
|
|
15
|
+
# @param [Phrase] The Phrase to update or create
|
|
16
|
+
# @return [Boolean] Result of the store_translations command from the Redis backend (I18n::Backend)
|
|
17
|
+
def self.update_phrase(phrase)
|
|
18
|
+
Idioma.configuration.redis_backend.
|
|
19
|
+
store_translations(phrase.locale, {phrase.i18n_key => phrase.i18n_value}, :escape => false)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|