pax_global_header00006660000000000000000000000064151025155300014507gustar00rootroot0000000000000052 comment=a95f0f4a5f05b0a9b19a28911ad1694dbc0458c0 grosser-gettext_i18n_rails-885ef82/000077500000000000000000000000001510251553000172615ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/.github/000077500000000000000000000000001510251553000206215ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/.github/workflows/000077500000000000000000000000001510251553000226565ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/.github/workflows/test.yml000066400000000000000000000012721510251553000243620ustar00rootroot00000000000000name: Test on: - push - pull_request jobs: run: strategy: fail-fast: false matrix: gemfile: - gemfiles/rails70.gemfile - gemfiles/rails71.gemfile ruby-version: - "3.0" - "3.1" - "3.2" runs-on: - ubuntu-latest name: ${{ matrix.ruby-version}} on ${{ matrix.runs-on }} with ${{ matrix.gemfile }} runs-on: ${{ matrix.runs-on }} env: BUNDLE_GEMFILE: ${{ matrix.gemfile }} steps: - uses: actions/checkout@master - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true - run: bundle exec rake grosser-gettext_i18n_rails-885ef82/.gitignore000066400000000000000000000000201510251553000212410ustar00rootroot00000000000000.idea pkg/*.gem grosser-gettext_i18n_rails-885ef82/CHANGELOG.md000066400000000000000000000005701510251553000210740ustar00rootroot00000000000000# Changelog ## Unreleased ## 2.1.0 - Add automatic reloading of .po and .mo files in development mode ## 2.0.0 - change how model attributes are looked up (class first, then sti root) - drop support for old rubies ## v1.13.0 - Use subclasses instead of direct_descendants on rails 7 and above ## v1.12.0 - drop support for gettext < 3 - improve haml and slim parsing grosser-gettext_i18n_rails-885ef82/Gemfile000066400000000000000000000000461510251553000205540ustar00rootroot00000000000000source 'https://rubygems.org' gemspec grosser-gettext_i18n_rails-885ef82/Gemfile.lock000066400000000000000000000115321510251553000215050ustar00rootroot00000000000000PATH remote: . specs: gettext_i18n_rails (2.1.0) fast_gettext (>= 0.9.0) GEM remote: https://rubygems.org/ specs: actioncable (7.0.5) actionpack (= 7.0.5) activesupport (= 7.0.5) nio4r (~> 2.0) websocket-driver (>= 0.6.1) actionmailbox (7.0.5) actionpack (= 7.0.5) activejob (= 7.0.5) activerecord (= 7.0.5) activestorage (= 7.0.5) activesupport (= 7.0.5) mail (>= 2.7.1) net-imap net-pop net-smtp actionmailer (7.0.5) actionpack (= 7.0.5) actionview (= 7.0.5) activejob (= 7.0.5) activesupport (= 7.0.5) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.0) actionpack (7.0.5) actionview (= 7.0.5) activesupport (= 7.0.5) rack (~> 2.0, >= 2.2.4) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) actiontext (7.0.5) actionpack (= 7.0.5) activerecord (= 7.0.5) activestorage (= 7.0.5) activesupport (= 7.0.5) globalid (>= 0.6.0) nokogiri (>= 1.8.5) actionview (7.0.5) activesupport (= 7.0.5) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) activejob (7.0.5) activesupport (= 7.0.5) globalid (>= 0.3.6) activemodel (7.0.5) activesupport (= 7.0.5) activerecord (7.0.5) activemodel (= 7.0.5) activesupport (= 7.0.5) activestorage (7.0.5) actionpack (= 7.0.5) activejob (= 7.0.5) activerecord (= 7.0.5) activesupport (= 7.0.5) marcel (~> 1.0) mini_mime (>= 1.1.0) activesupport (7.0.5) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) builder (3.2.4) bump (0.10.0) concurrent-ruby (1.2.2) crass (1.0.6) date (3.3.3) diff-lcs (1.5.0) erubi (1.12.0) fast_gettext (2.2.0) forwardable (1.3.2) gettext (3.4.3) erubi locale (>= 2.0.5) prime text (>= 1.3.0) globalid (1.1.0) activesupport (>= 5.0) haml (5.2.2) temple (>= 0.8.0) tilt hamlit (3.0.1) temple (>= 0.8.2) thor tilt i18n (1.13.0) concurrent-ruby (~> 1.0) locale (2.1.3) loofah (2.21.3) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) mini_mime (>= 0.1.1) net-imap net-pop net-smtp marcel (1.0.2) method_source (1.0.0) mini_mime (1.1.2) minitest (5.18.0) net-imap (0.3.4) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.1) timeout net-smtp (0.3.3) net-protocol nio4r (2.5.9) nokogiri (1.15.2-arm64-darwin) racc (~> 1.4) nokogiri (1.15.2-x86_64-darwin) racc (~> 1.4) nokogiri (1.15.2-x86_64-linux) racc (~> 1.4) prime (0.1.2) forwardable singleton racc (1.6.2) rack (2.2.7) rack-test (2.1.0) rack (>= 1.3) rails (7.0.5) actioncable (= 7.0.5) actionmailbox (= 7.0.5) actionmailer (= 7.0.5) actionpack (= 7.0.5) actiontext (= 7.0.5) actionview (= 7.0.5) activejob (= 7.0.5) activemodel (= 7.0.5) activerecord (= 7.0.5) activestorage (= 7.0.5) activesupport (= 7.0.5) bundler (>= 1.15.0) railties (= 7.0.5) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) railties (7.0.5) actionpack (= 7.0.5) activesupport (= 7.0.5) method_source rake (>= 12.2) thor (~> 1.0) zeitwerk (~> 2.5) rake (13.0.6) rspec (3.12.0) rspec-core (~> 3.12.0) rspec-expectations (~> 3.12.0) rspec-mocks (~> 3.12.0) rspec-core (3.12.2) rspec-support (~> 3.12.0) rspec-expectations (3.12.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-mocks (3.12.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-support (3.12.0) singleton (0.1.1) slim (4.1.0) temple (>= 0.7.6, < 0.9) tilt (>= 2.0.6, < 2.1) sqlite3 (1.7.3-arm64-darwin) sqlite3 (1.7.3-x86_64-darwin) sqlite3 (1.7.3-x86_64-linux) temple (0.8.2) text (1.3.1) thor (1.2.2) tilt (2.0.11) timeout (0.3.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) zeitwerk (2.6.8) PLATFORMS arm64-darwin-21 arm64-darwin-23 arm64-darwin-24 arm64-darwin-25 x86_64-darwin-22 x86_64-linux DEPENDENCIES bump gettext (>= 3.0.2) gettext_i18n_rails! haml hamlit rails rake rspec slim sqlite3 (~> 1.7) BUNDLED WITH 2.4.13 grosser-gettext_i18n_rails-885ef82/MIT-LICENSE.txt000066400000000000000000000020701510251553000215320ustar00rootroot00000000000000Copyright (C) 2013 Michael Grosser 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. grosser-gettext_i18n_rails-885ef82/Rakefile000066400000000000000000000007331510251553000207310ustar00rootroot00000000000000require 'bundler/setup' require 'bundler/gem_tasks' require 'bump/tasks' Bump.replace_in_default = Dir["gemfiles/*.gemfile.lock"] task :spec do sh "rspec spec" end task :default => "spec" desc "bundle all gemfiles [EXTRA=]" task :bundle_all do extra = ENV["EXTRA"] || "install" gemfiles = (["Gemfile"] + Dir["gemfiles/*.gemfile"]) gemfiles.each do |gemfile| Bundler.with_unbundled_env do sh "BUNDLE_GEMFILE=#{gemfile} bundle #{extra}" end end end grosser-gettext_i18n_rails-885ef82/Readme.md000066400000000000000000000276401510251553000210110ustar00rootroot00000000000000[FastGettext](http://github.com/grosser/fast_gettext) / Rails integration. Translate via FastGettext, use any other I18n backend as extension/fallback. Rails does: `I18n.t('syntax.with.lots.of.dots')` with nested yml files We do: `_('Just translate my damn text!')` with simple, flat mo/po/yml files or directly from db To use I18n calls add a `syntax.with.lots.of.dots` translation. [See it working in the example application.](https://github.com/grosser/gettext_i18n_rails_example) Setup ===== ### Installation ```Ruby # Gemfile gem 'gettext_i18n_rails' ``` ##### Optional: Add `gettext` if you want to find translations or build .mo files
```Ruby # Gemfile gem 'gettext', '>=3.0.2', :require => false ``` ###### Add first language: Add the first language using: ```Bash rake gettext:add_language[xx] ``` or ```Bash LANGUAGE=xx rake gettext:add_language ``` where `xx` is the lowercased [ISO 639-1](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) 2-letter code for the language you want to create. for example: ```Bash rake gettext:add_language[es] ``` This will also create the `locales` directory (where the translations are being stored) and run `gettext:find` to find any strings marked for translation. You can, of course, add more languages using the same command. ### Locales & initialisation Copy default locales with dates/sentence-connectors/AR-errors you want from e.g. [rails i18n](https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale/) into 'config/locales' To initialize: ```Ruby # config/initializers/fast_gettext.rb FastGettext.add_text_domain 'app', :path => 'locale', :type => :po FastGettext.default_available_locales = ['en','de'] #all you want to allow FastGettext.default_text_domain = 'app' ``` And in your application: ```Ruby # app/controllers/application_controller.rb class ApplicationController < ... before_action :set_gettext_locale ``` Translating =========== Performance is almost the same for all backends since translations are cached after first use. ### Option A: .po files ```Ruby FastGettext.add_text_domain 'app', :path => 'locale', :type => :po ``` - use some `_('translations')` - run `rake gettext:find`, to let GetText find all translations used - (optional) run `rake gettext:store_model_attributes`, to parse the database for columns that can be translated - if this is your first translation: `cp locale/app.pot locale/de/app.po` for every locale you want to use - translate messages in 'locale/de/app.po' (leave msgstr blank and msgstr == msgid) New translations will be marked "fuzzy", search for this and remove it, so that they will be used. Obsolete translations are marked with ~#, they usually can be removed since they are no longer needed #### Unfound translations with rake gettext:find Dynamic translations like `_("x"+"u")` cannot be found. You have 4 options: - add `N_('xu')` somewhere else in the code, so the parser sees it - add `N_('xu')` in a totally separate file like `locale/unfound_translations.rb`, so the parser sees it - use the [gettext_test_log rails plugin ](http://github.com/grosser/gettext_test_log) to find all translations that where used while testing - add a Logger to a translation Chain, so every unfound translations is logged ([example](http://github.com/grosser/fast_gettext)) ### Option B: Traditional .po/.mo files FastGettext.add_text_domain 'app', :path => 'locale' - follow Option A - run `rake gettext:pack` to write binary GetText .mo files ### Option C: Database Most scalable method, all translators can work simultaneously and online. Easiest to use with the [translation database Rails engine](http://github.com/grosser/translation_db_engine). Translations can be edited under `/translation_keys` ```Ruby FastGettext::TranslationRepository::Db.require_models FastGettext.add_text_domain 'app', :type => :db, :model => TranslationKey ``` I18n ==== ```Ruby I18n.locale <==> FastGettext.locale.to_sym I18n.locale = :de <==> FastGettext.locale = 'de' ``` Any call to I18n that matches a gettext key will be translated through FastGettext. Namespaces ========== Car|Model means Model in namespace Car. You do not have to translate this into english "Model", if you use the namespace-aware translation ```Ruby s_('Car|Model') == 'Model' #when no translation was found ``` XSS / html_safe =============== If you trust your translators and all your usages of % on translations:
```Ruby # config/environment.rb GettextI18nRails.translations_are_html_safe = true ``` String % vs html_safe is buggy
My recommended fix is: `require 'gettext_i18n_rails/string_interpolate_fix'` - safe stays safe (escape added strings) - unsafe stays unsafe (do not escape added strings) ActiveRecord - error messages ============================= ActiveRecord error messages are translated through Rails::I18n, but model names and model attributes are translated through FastGettext. Therefore a validation error on a BigCar's wheels_size needs `_('big car')` and `_('BigCar|Wheels size')` to display localized. The model/attribute translations can be found through `rake gettext:store_model_attributes`, (which ignores some commonly untranslated columns like id,type,xxx_count,...). Error messages can be translated through FastGettext, if the ':message' is a translation-id or the matching Rails I18n key is translated. #### Option A: Define a translation for "I need my rating!" and use it as message. ```Ruby validates_inclusion_of :rating, :in=>1..5, :message=>N_('I need my rating!') ``` #### Option B: ```Ruby validates_inclusion_of :rating, :in=>1..5 ``` Make a translation for the I18n key: `activerecord.errors.models.rating.attributes.rating.inclusion` #### Option C: Add a translation to each config/locales/*.yml files ```Yaml en: activerecord: errors: models: rating: attributes: rating: inclusion: " -- please choose!" ``` The [rails I18n guide](http://guides.rubyonrails.org/i18n.html) can help with Option B and C. Plurals ======= FastGettext supports pluralization ```Ruby n_('Apple','Apples',3) == 'Apples' ``` Languages with complex plural forms (such as Polish with its 4 different forms) can also be addressed, see [FastGettext Readme](http://github.com/grosser/fast_gettext) Customizing list of translatable files ====================================== When you run ```Bash rake gettext:find ``` by default the following files are going to be scanned for translations: {app,lib,config,locale}/**/*.{rb,erb,haml,slim}. If you want to specify a different list, you can redefine files_to_translate in the gettext namespace in a file like lib/tasks/gettext.rake: ```Ruby namespace :gettext do def files_to_translate Dir.glob("{app,lib,config,locale}/**/*.{rb,erb,haml,slim,rhtml}") end end ``` Customizing text domains setup task =================================== By default a single application text domain is created (named `app` or if you load the environment the value of `FastGettext.text_domain` is being used). If you want to have multiple text domains or change the definition of the text domains in any way, you can do so by overriding the `:setup` task in a file like lib/tasks/gettext.rake: ```Ruby # Remove the provided gettext setup task Rake::Task["gettext:setup"].clear namespace :gettext do task :setup => [:environment] do domains = Application.config.gettext["domains"] domains.each do |domain, options| files = Dir.glob(options["paths"]) GetText::Tools::Task.define do |task| task.package_name = options["name"] task.package_version = "1.0.0" task.domain = options["name"] task.po_base_directory = locale_path task.mo_base_directory = locale_path task.files = files task.enable_description = false task.msgmerge_options = gettext_msgmerge_options task.msgcat_options = gettext_msgcat_options task.xgettext_options = gettext_xgettext_options end end end end ``` Changing msgmerge, msgcat, and xgettext options =============================================== The default options for parsing and create `.po` files are: ```Bash --sort-by-msgid --no-location --no-wrap ``` These options sort the translations by the msgid (original / source string), don't add location information in the po file and don't wrap long message lines into several lines. If you want to override them you can put the following into an initializer like config/initializers/gettext.rb: ```Ruby Rails.application.config.gettext_i18n_rails.msgmerge = %w[--no-location] Rails.application.config.gettext_i18n_rails.msgcat = %w[--no-location] Rails.application.config.gettext_i18n_rails.xgettext = %w[--no-location] ``` or ```Ruby Rails.application.config.gettext_i18n_rails.default_options = %w[--no-location] ``` to override both. You can see the available options by running `rgettext -h`, `rmsgcat -f` and `rxgettext -h`. Use I18n instead Gettext to ActiveRecord/ActiveModel translations ================================================================= If you want to disable translations to model name and attributes you can put the following into an initializer like config/initializers/gettext.rb: ```Ruby Rails.application.config.gettext_i18n_rails.use_for_active_record_attributes = false ``` And now you can use your I18n yaml files instead. Auto-reload translations in development ======================================== By default, .po and .mo files are automatically reloaded in development mode when they change, so you don't need to restart the Rails server after editing translations. This feature is enabled by default in development. You can configure it in any environment file: ```Ruby # To disable in development config.gettext_i18n_rails.auto_reload = false # To enable in production (not recommended) config.gettext_i18n_rails.auto_reload = true ``` The auto-reload feature uses `ActiveSupport::FileUpdateChecker` to monitor changes to translation files in your `locale/` directory and reloads them only when they've been modified, ensuring minimal performance impact. Using your translations from javascript ======================================= If want to use your .PO files on client side javascript you should have a look at the [GettextI18nRailsJs](https://github.com/nubis/gettext_i18n_rails_js) extension. [Contributors](http://github.com/grosser/gettext_i18n_rails/contributors) ====== - [ruby gettext extractor](http://github.com/retoo/ruby_gettext_extractor/tree/master) from [retoo](http://github.com/retoo) - [Paul McMahon](http://github.com/pwim) - [Duncan Mac-Vicar P](http://duncan.mac-vicar.com/blog) - [Ramihajamalala Hery](http://my.rails-royce.org) - [J. Pablo Fernández](http://pupeno.com) - [Anh Hai Trinh](http://blog.onideas.ws) - [ed0h](http://github.com/ed0h) - [Nikos Dimitrakopoulos](http://blog.nikosd.com) - [Ben Tucker](http://btucker.net/) - [Kamil Śliwak](https://github.com/cameel) - [Rainux Luo](https://github.com/rainux) - [Lucas Hills](https://github.com/2potatocakes) - [Ladislav Slezák](https://github.com/lslezak) - [Greg Weber](https://github.com/gregwebs) - [Sean Kirby](https://github.com/sskirby) - [Julien Letessier](https://github.com/mezis) - [Seb Bacon](https://github.com/sebbacon) - [Ramón Cahenzli](https://github.com/psy-q) - [rustygeldmacher](https://github.com/rustygeldmacher) - [Jeroen Knoops](https://github.com/JeroenKnoops) - [Ivan Necas](https://github.com/iNecas) - [Andrey Chernih](https://github.com/AndreyChernyh) - [Imre Farkas](https://github.com/ifarkas) - [Trong Tran](https://github.com/trongrg) - [Dmitri Dolguikh](https://github.com/witlessbird) - [Joe Ferris](https://github.com/jferris) - [exAspArk](https://github.com/exAspArk) - [martinpovolny](https://github.com/martinpovolny) - [akimd](https://github.com/akimd) - [adam-h](https://github.com/adam-h) [Michael Grosser](http://grosser.it)
michael@grosser.it
License: MIT
[![Build Status](https://travis-ci.org/grosser/gettext_i18n_rails.png)](https://travis-ci.org/grosser/gettext_i18n_rails) grosser-gettext_i18n_rails-885ef82/gemfiles/000077500000000000000000000000001510251553000210545ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/gemfiles/rails70.gemfile000066400000000000000000000001171510251553000236660ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "rails", "~> 7.0.0" grosser-gettext_i18n_rails-885ef82/gemfiles/rails70.gemfile.lock000066400000000000000000000115001510251553000246130ustar00rootroot00000000000000PATH remote: .. specs: gettext_i18n_rails (2.1.0) fast_gettext (>= 0.9.0) GEM remote: https://rubygems.org/ specs: actioncable (7.0.5) actionpack (= 7.0.5) activesupport (= 7.0.5) nio4r (~> 2.0) websocket-driver (>= 0.6.1) actionmailbox (7.0.5) actionpack (= 7.0.5) activejob (= 7.0.5) activerecord (= 7.0.5) activestorage (= 7.0.5) activesupport (= 7.0.5) mail (>= 2.7.1) net-imap net-pop net-smtp actionmailer (7.0.5) actionpack (= 7.0.5) actionview (= 7.0.5) activejob (= 7.0.5) activesupport (= 7.0.5) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.0) actionpack (7.0.5) actionview (= 7.0.5) activesupport (= 7.0.5) rack (~> 2.0, >= 2.2.4) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) actiontext (7.0.5) actionpack (= 7.0.5) activerecord (= 7.0.5) activestorage (= 7.0.5) activesupport (= 7.0.5) globalid (>= 0.6.0) nokogiri (>= 1.8.5) actionview (7.0.5) activesupport (= 7.0.5) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) activejob (7.0.5) activesupport (= 7.0.5) globalid (>= 0.3.6) activemodel (7.0.5) activesupport (= 7.0.5) activerecord (7.0.5) activemodel (= 7.0.5) activesupport (= 7.0.5) activestorage (7.0.5) actionpack (= 7.0.5) activejob (= 7.0.5) activerecord (= 7.0.5) activesupport (= 7.0.5) marcel (~> 1.0) mini_mime (>= 1.1.0) activesupport (7.0.5) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) builder (3.2.4) bump (0.10.0) concurrent-ruby (1.2.2) crass (1.0.6) date (3.3.3) diff-lcs (1.5.0) erubi (1.12.0) fast_gettext (2.3.0) forwardable (1.3.3) gettext (3.4.3) erubi locale (>= 2.0.5) prime text (>= 1.3.0) globalid (1.1.0) activesupport (>= 5.0) haml (6.1.1) temple (>= 0.8.2) thor tilt hamlit (3.0.3) temple (>= 0.8.2) thor tilt i18n (1.13.0) concurrent-ruby (~> 1.0) locale (2.1.3) loofah (2.21.3) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) mini_mime (>= 0.1.1) net-imap net-pop net-smtp marcel (1.0.2) method_source (1.0.0) mini_mime (1.1.2) minitest (5.18.0) net-imap (0.3.4) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.1) timeout net-smtp (0.3.3) net-protocol nio4r (2.7.3) nokogiri (1.15.2-arm64-darwin) racc (~> 1.4) nokogiri (1.15.2-x86_64-darwin) racc (~> 1.4) nokogiri (1.15.2-x86_64-linux) racc (~> 1.4) prime (0.1.2) forwardable singleton racc (1.6.2) rack (2.2.7) rack-test (2.1.0) rack (>= 1.3) rails (7.0.5) actioncable (= 7.0.5) actionmailbox (= 7.0.5) actionmailer (= 7.0.5) actionpack (= 7.0.5) actiontext (= 7.0.5) actionview (= 7.0.5) activejob (= 7.0.5) activemodel (= 7.0.5) activerecord (= 7.0.5) activestorage (= 7.0.5) activesupport (= 7.0.5) bundler (>= 1.15.0) railties (= 7.0.5) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) railties (7.0.5) actionpack (= 7.0.5) activesupport (= 7.0.5) method_source rake (>= 12.2) thor (~> 1.0) zeitwerk (~> 2.5) rake (13.0.6) rspec (3.12.0) rspec-core (~> 3.12.0) rspec-expectations (~> 3.12.0) rspec-mocks (~> 3.12.0) rspec-core (3.12.2) rspec-support (~> 3.12.0) rspec-expectations (3.12.3) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-mocks (3.12.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-support (3.12.0) singleton (0.1.1) slim (5.1.1) temple (~> 0.10.0) tilt (>= 2.1.0) sqlite3 (1.7.3-arm64-darwin) sqlite3 (1.7.3-x86_64-darwin) sqlite3 (1.7.3-x86_64-linux) temple (0.10.2) text (1.3.1) thor (1.2.2) tilt (2.1.0) timeout (0.3.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) zeitwerk (2.6.8) PLATFORMS arm64-darwin-21 arm64-darwin-23 x86_64-darwin-22 x86_64-linux DEPENDENCIES bump gettext (>= 3.0.2) gettext_i18n_rails! haml hamlit rails (~> 7.0.0) rake rspec slim sqlite3 (~> 1.7) BUNDLED WITH 2.4.13 grosser-gettext_i18n_rails-885ef82/gemfiles/rails71.gemfile000066400000000000000000000001511510251553000236650ustar00rootroot00000000000000source "https://rubygems.org" gemspec :path => "../" gem "rails", "~> 7.1.0" gem "sqlite3", "~> 1.6.3" grosser-gettext_i18n_rails-885ef82/gemfiles/rails71.gemfile.lock000066400000000000000000000126621510251553000246260ustar00rootroot00000000000000PATH remote: .. specs: gettext_i18n_rails (2.1.0) fast_gettext (>= 0.9.0) GEM remote: https://rubygems.org/ specs: actioncable (7.1.3.4) actionpack (= 7.1.3.4) activesupport (= 7.1.3.4) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) actionmailbox (7.1.3.4) actionpack (= 7.1.3.4) activejob (= 7.1.3.4) activerecord (= 7.1.3.4) activestorage (= 7.1.3.4) activesupport (= 7.1.3.4) mail (>= 2.7.1) net-imap net-pop net-smtp actionmailer (7.1.3.4) actionpack (= 7.1.3.4) actionview (= 7.1.3.4) activejob (= 7.1.3.4) activesupport (= 7.1.3.4) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.2) actionpack (7.1.3.4) actionview (= 7.1.3.4) activesupport (= 7.1.3.4) nokogiri (>= 1.8.5) racc rack (>= 2.2.4) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) actiontext (7.1.3.4) actionpack (= 7.1.3.4) activerecord (= 7.1.3.4) activestorage (= 7.1.3.4) activesupport (= 7.1.3.4) globalid (>= 0.6.0) nokogiri (>= 1.8.5) actionview (7.1.3.4) activesupport (= 7.1.3.4) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) activejob (7.1.3.4) activesupport (= 7.1.3.4) globalid (>= 0.3.6) activemodel (7.1.3.4) activesupport (= 7.1.3.4) activerecord (7.1.3.4) activemodel (= 7.1.3.4) activesupport (= 7.1.3.4) timeout (>= 0.4.0) activestorage (7.1.3.4) actionpack (= 7.1.3.4) activejob (= 7.1.3.4) activerecord (= 7.1.3.4) activesupport (= 7.1.3.4) marcel (~> 1.0) activesupport (7.1.3.4) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) minitest (>= 5.1) mutex_m tzinfo (~> 2.0) base64 (0.2.0) bigdecimal (3.1.8) builder (3.3.0) bump (0.10.0) concurrent-ruby (1.3.3) connection_pool (2.4.1) crass (1.0.6) date (3.3.4) diff-lcs (1.5.1) drb (2.2.1) erubi (1.13.0) fast_gettext (2.4.0) prime forwardable (1.3.3) gettext (3.4.9) erubi locale (>= 2.0.5) prime racc text (>= 1.3.0) globalid (1.2.1) activesupport (>= 6.1) haml (6.3.0) temple (>= 0.8.2) thor tilt hamlit (3.0.3) temple (>= 0.8.2) thor tilt i18n (1.14.5) concurrent-ruby (~> 1.0) io-console (0.7.2) irb (1.14.0) rdoc (>= 4.0.0) reline (>= 0.4.2) locale (2.1.4) loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) mini_mime (>= 0.1.1) net-imap net-pop net-smtp marcel (1.0.4) mini_mime (1.1.5) minitest (5.24.1) mutex_m (0.2.0) net-imap (0.4.14) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.2) timeout net-smtp (0.5.0) net-protocol nio4r (2.7.3) nokogiri (1.15.6-arm64-darwin) racc (~> 1.4) nokogiri (1.15.6-x86_64-linux) racc (~> 1.4) prime (0.1.2) forwardable singleton psych (5.1.2) stringio racc (1.8.1) rack (3.1.7) rack-session (2.0.0) rack (>= 3.0.0) rack-test (2.1.0) rack (>= 1.3) rackup (2.1.0) rack (>= 3) webrick (~> 1.8) rails (7.1.3.4) actioncable (= 7.1.3.4) actionmailbox (= 7.1.3.4) actionmailer (= 7.1.3.4) actionpack (= 7.1.3.4) actiontext (= 7.1.3.4) actionview (= 7.1.3.4) activejob (= 7.1.3.4) activemodel (= 7.1.3.4) activerecord (= 7.1.3.4) activestorage (= 7.1.3.4) activesupport (= 7.1.3.4) bundler (>= 1.15.0) railties (= 7.1.3.4) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) railties (7.1.3.4) actionpack (= 7.1.3.4) activesupport (= 7.1.3.4) irb rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) rake (13.2.1) rdoc (6.7.0) psych (>= 4.0.0) reline (0.5.9) io-console (~> 0.5) rspec (3.13.0) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) rspec-core (3.13.0) rspec-support (~> 3.13.0) rspec-expectations (3.13.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-mocks (3.13.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-support (3.13.1) singleton (0.2.0) slim (5.2.1) temple (~> 0.10.0) tilt (>= 2.1.0) sqlite3 (1.6.9-arm64-darwin) sqlite3 (1.6.9-x86_64-linux) stringio (3.1.1) temple (0.10.3) text (1.3.1) thor (1.3.1) tilt (2.4.0) timeout (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) webrick (1.8.1) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) zeitwerk (2.6.17) PLATFORMS arm64-darwin-23 x86_64-linux DEPENDENCIES bump gettext (>= 3.0.2) gettext_i18n_rails! haml hamlit rails (~> 7.1.0) rake rspec slim sqlite3 (~> 1.6.3) BUNDLED WITH 2.4.13 grosser-gettext_i18n_rails-885ef82/gettext_i18n_rails.gemspec000066400000000000000000000015161510251553000243460ustar00rootroot00000000000000name = "gettext_i18n_rails" require "./lib/#{name}/version" Gem::Specification.new name, GettextI18nRails::VERSION do |s| s.summary = "Simple FastGettext Rails integration." s.authors = ["Michael Grosser"] s.email = "michael@grosser.it" s.homepage = "http://github.com/grosser/#{name}" s.files = `git ls-files lib MIT-LICENSE.txt`.split("\n") s.license = "MIT" s.required_ruby_version = '>= 3.0.0' s.add_runtime_dependency "fast_gettext", ">= 0.9.0" s.add_development_dependency "bump" s.add_development_dependency "gettext", ">= 3.0.2" s.add_development_dependency "haml" s.add_development_dependency "hamlit" s.add_development_dependency "rake" s.add_development_dependency "rails" s.add_development_dependency "rspec" s.add_development_dependency "slim" s.add_development_dependency "sqlite3", "~> 1.7" end grosser-gettext_i18n_rails-885ef82/lib/000077500000000000000000000000001510251553000200275ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails.rb000066400000000000000000000022041510251553000240670ustar00rootroot00000000000000require 'gettext_i18n_rails/version' require 'gettext_i18n_rails/gettext_hooks' module GettextI18nRails IGNORE_TABLES = [/^sitemap_/, /_versions$/, 'schema_migrations', 'sessions', 'delayed_jobs'] end # translate from everywhere require 'fast_gettext' Object.send(:include, FastGettext::Translation) # make translations html_safe if possible and wanted if "".respond_to?(:html_safe?) require 'gettext_i18n_rails/html_safe_translations' Object.send(:include, GettextI18nRails::HtmlSafeTranslations) end # set up the backend require 'gettext_i18n_rails/backend' I18n.backend = GettextI18nRails::Backend.new # make I18n play nice with FastGettext require 'gettext_i18n_rails/i18n_hacks' # translate activerecord errors if defined? Rails::Railtie # Rails 3+ # load active_model extensions at the correct point in time require 'gettext_i18n_rails/railtie' else if defined? ActiveRecord require 'gettext_i18n_rails/active_record' elsif defined?(ActiveModel) require 'gettext_i18n_rails/active_model' end end # make bundle console work in a rails project require 'gettext_i18n_rails/action_controller' if defined?(ActionController) grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/000077500000000000000000000000001510251553000235445ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/action_controller.rb000066400000000000000000000014141510251553000276110ustar00rootroot00000000000000# Autoloading in initializers is deprecated on rails 6.0. This delays initialization using the on_load # hooks, but does not change behaviour for existing rails versions. path_controller = ->() { class ::ActionController::Base def set_gettext_locale requested_locale = params[:locale] || session[:locale] || cookies[:locale] || request.env['HTTP_ACCEPT_LANGUAGE'] || I18n.default_locale locale = FastGettext.set_locale(requested_locale) session[:locale] = locale I18n.locale = locale # some weird overwriting in action-controller makes this necessary ... see I18nProxy end end } if defined?(Rails) && Rails::VERSION::MAJOR >= 6 ActiveSupport.on_load(:action_controller_base) do path_controller.call end else path_controller.call endgrosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/active_model.rb000066400000000000000000000001451510251553000265240ustar00rootroot00000000000000require 'gettext_i18n_rails/active_model/name' require 'gettext_i18n_rails/active_model/translation' grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/active_model/000077500000000000000000000000001510251553000261775ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/active_model/name.rb000066400000000000000000000004031510251553000274410ustar00rootroot00000000000000module ActiveModel Name.class_eval do def human(options={}) human_name = @klass.humanize_class_name if count = options[:count] n_(human_name, human_name.pluralize, count) else _(human_name) end end end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/active_model/translation.rb000066400000000000000000000025251510251553000310660ustar00rootroot00000000000000module ActiveModel module Translation # CarDealer.sales_count -> s_('CarDealer|Sales count') -> 'Sales count' if no translation was found def human_attribute_name(attribute, *args) s_(gettext_translation_for_attribute_name(attribute)) end def gettext_translation_for_attribute_name(attribute) attribute = attribute.to_s if attribute.end_with?('_id') humanize_class_name(attribute) else attribute_key = attribute.split('.').map! {|a| a.humanize }.join('|') root = inheritance_tree_root(self).to_s # in case of STI or no inheritance, first attempt retrieving the key for the current class sti_key = "#{to_s}|#{attribute_key}" return sti_key if to_s == root || FastGettext.cached_find(sti_key) # fallback to lookup for the root class return "#{root}|#{attribute_key}" end end def inheritance_tree_root(aclass) return aclass unless aclass.respond_to?(:base_class) base = aclass.base_class if base.superclass.abstract_class? if defined?(::ApplicationRecord) && base.superclass == ApplicationRecord base else base.superclass end else base end end def humanize_class_name(name=nil) name ||= self.to_s name.underscore.humanize end end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/active_record.rb000066400000000000000000000004341510251553000267030ustar00rootroot00000000000000require 'gettext_i18n_rails/active_model/translation' class ActiveRecord::Base extend ActiveModel::Translation def self.human_attribute_name(*args) super(*args) end # method deprecated in Rails 3.1 def self.human_name(*args) _(self.humanize_class_name) end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/backend.rb000066400000000000000000000046651510251553000254730ustar00rootroot00000000000000module GettextI18nRails #translates i18n calls to gettext calls class Backend @@translate_defaults = true cattr_accessor :translate_defaults attr_accessor :backend def initialize(*args) self.backend = I18n::Backend::Simple.new(*args) end def available_locales FastGettext.available_locales || [] end def translate(locale, key, options) I18n.with_locale(locale) do if gettext_key = gettext_key(key, options) translation = plural_translate(gettext_key, options) || FastGettext._(gettext_key) interpolate(translation, options) else result = backend.translate(locale, key, options) if result.is_a?(String) result = result.dup if result.frozen? result.force_encoding("UTF-8") else result end end end end def method_missing(method, *args) backend.send(method, *args) end protected def gettext_key(key, options) flat_key = flatten_key key, options if FastGettext.key_exist?(flat_key) flat_key elsif self.class.translate_defaults [*options[:default]].each do |default| #try the scoped(more specific) key first e.g. 'activerecord.errors.my custom message' flat_key = flatten_key default, options return flat_key if FastGettext.key_exist?(flat_key) #try the short key thereafter e.g. 'my custom message' return default if FastGettext.key_exist?(default) end return nil end end def plural_translate(gettext_key, options) if options[:count] translation = FastGettext.n_(gettext_key, options[:count]) discard_pass_through_key gettext_key, translation end end def discard_pass_through_key(key, translation) if translation == key nil else translation end end def interpolate(string, values) if string.respond_to?(:%) reserved_keys = if defined?(I18n::RESERVED_KEYS) # rails 3+ I18n::RESERVED_KEYS else I18n::Backend::Base::RESERVED_KEYS end options = values.except(*reserved_keys) options.any? ? (string % options) : string else string end end def flatten_key key, options scope = [*(options[:scope] || [])] scope.empty? ? key.to_s : "#{scope*'.'}.#{key}" end end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/base_parser.rb000066400000000000000000000016261510251553000263640ustar00rootroot00000000000000require 'gettext_i18n_rails/gettext_hooks' module GettextI18nRails class BaseParser def self.target?(file) File.extname(file) == ".#{extension}" end def self.parse(file, options = {}, _msgids = []) return _msgids unless load_library code = convert_to_code(File.read(file)) GetText::RubyParser.new(file, options).parse_source(code) end def self.libraries [extension] end def self.load_library return true if @library_loaded loaded = libraries.detect do |library| if Gem::Specification.find_all_by_name(library).any? require library true else false end end unless loaded puts "No #{extension} library could be found: #{libraries.join(" or ")}" return false end require 'gettext/tools/parser/ruby' @library_loaded = loaded end end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/gettext_hooks.rb000066400000000000000000000005121510251553000267560ustar00rootroot00000000000000module GettextI18nRails module GettextHooks # shorter call / maybe the interface changes again ... def self.add_parser(parser) xgettext.add_parser(parser) end def self.xgettext @xgettext ||= begin require 'gettext/tools/xgettext' GetText::Tools::XGetText end end end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/haml_parser.rb000066400000000000000000000011301510251553000263610ustar00rootroot00000000000000require 'gettext_i18n_rails/base_parser' module GettextI18nRails class HamlParser < BaseParser def self.extension "haml" end def self.convert_to_code(text) case @library_loaded when "haml" if Haml::VERSION.split('.').first.to_i <= 5 Haml::Engine.new(text).precompiled() else Haml::Engine.new.call(text) end when "hamlit" Hamlit::Engine.new.call(text) end end def self.libraries ["haml", "hamlit"] end end end GettextI18nRails::GettextHooks.add_parser GettextI18nRails::HamlParser grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/html_safe_translations.rb000066400000000000000000000010331510251553000306310ustar00rootroot00000000000000module GettextI18nRails mattr_accessor :translations_are_html_safe module HtmlSafeTranslations # also make available on class methods def self.included(base) base.extend self end def _(*args) html_safe_if_wanted super end def n_(*args) html_safe_if_wanted super end def s_(*args) html_safe_if_wanted super end private def html_safe_if_wanted(text) return text unless GettextI18nRails.translations_are_html_safe text.to_s.html_safe end end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/i18n_hacks.rb000066400000000000000000000010401510251553000260140ustar00rootroot00000000000000I18n::Config # autoload module I18n class Config def locale FastGettext.locale.gsub("_","-").to_sym end def locale=(new_locale) FastGettext.locale=(new_locale) end end # backport I18n.with_locale if it does not exist # Executes block with given I18n.locale set. def self.with_locale(tmp_locale = nil) if tmp_locale current_locale = self.locale self.locale = tmp_locale end yield ensure self.locale = current_locale if tmp_locale end unless defined? I18n.with_locale end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/model_attributes_finder.rb000066400000000000000000000140561510251553000307740ustar00rootroot00000000000000require 'rails/version' require 'rails' if Rails::VERSION::MAJOR > 2 module GettextI18nRails #write all found models/columns to a file where GetTexts ruby parser can find them def store_model_attributes(options) file = options[:to] || 'locale/model_attributes.rb' begin File.open(file,'w') do |f| f.puts "#DO NOT MODIFY! AUTOMATICALLY GENERATED FILE!" ModelAttributesFinder.new.find(options).each do |model,column_names| f.puts("_('#{model.humanize_class_name}')") #all columns namespaced under the model column_names.each do |attribute| translation = model.gettext_translation_for_attribute_name(attribute) f.puts("_('#{translation}')") end end f.puts "#DO NOT MODIFY! AUTOMATICALLY GENERATED FILE!" f.puts "{}" end rescue puts "[Error] Attribute extraction failed. Removing incomplete file (#{file})" File.delete(file) raise end end module_function :store_model_attributes class ModelAttributesFinder # options: # :ignore_tables => ['cars',/_settings$/,...] # :ignore_columns => ['id',/_id$/,...] # current connection ---> {'cars'=>['model_name','type'],...} def find(options) found = ActiveSupport::OrderedHash.new([]) models.each do |model| attributes = model_attributes(model, options[:ignore_tables], options[:ignore_columns]) found[model] = attributes.sort if attributes.any? end found end def initialize connection = ::ActiveRecord::Base.connection @existing_tables = (Rails::VERSION::MAJOR >= 5 ? connection.data_sources : connection.tables) end # Rails 7.0 has deprecated direct_descendants in favor of subclasses. # It was removed completely in Rails 7.1. # This will maintain backwards compatibility with Rails 3.0 - 6.1 def subclass_method if Rails::VERSION::MAJOR < 7 :direct_descendants else :subclasses end end # Rails < 3.0 doesn't have DescendantsTracker. # Instead of iterating over ObjectSpace (slow) the decision was made NOT to support # class hierarchies with abstract base classes in Rails 2.x def model_attributes(model, ignored_tables, ignored_cols) return [] if model.abstract_class? && Rails::VERSION::MAJOR < 3 if model.abstract_class? model.send(subclass_method).reject {|m| ignored?(m.table_name, ignored_tables)}.inject([]) do |attrs, m| attrs.push(model_attributes(m, ignored_tables, ignored_cols)).flatten.uniq end elsif !ignored?(model.table_name, ignored_tables) && @existing_tables.include?(model.table_name) model.columns.reject { |c| ignored?(c.name, ignored_cols) }.collect { |c| c.name } else [] end end def models if Rails::VERSION::MAJOR >= 3 # Ensure autoloaders are set up before we attempt to eager load! Rails.application.autoloaders.each(&:setup) if Rails.application.respond_to?(:autoloaders) Rails.application.eager_load! # make sure that all models are loaded so that direct_descendants works descendants = ::ActiveRecord::Base.send(subclass_method) # In rails 5+ user models are supposed to inherit from ApplicationRecord if defined?(::ApplicationRecord) descendants += ApplicationRecord.send(subclass_method) descendants.delete ApplicationRecord end descendants else ::ActiveRecord::Base.connection.tables \ .map { |t| table_name_to_namespaced_model(t) } \ .compact \ .collect { |c| c.superclass.abstract_class? ? c.superclass : c } end.uniq.sort_by(&:name) end def ignored?(name,patterns) return false unless patterns patterns.detect{|p|p.to_s==name.to_s or (p.is_a?(Regexp) and name=~p)} end private # Tries to find the model class corresponding to specified table name. # Takes into account that the model can be defined in a namespace. # Searches only up to one level deep - won't find models nested in two # or more modules. # # Note that if we allow namespaces, the conversion can be ambiguous, i.e. # if the table is named "aa_bb_cc" and AaBbCc, Aa::BbCc and AaBb::Cc are # all defined there's no absolute rule that tells us which one to use. # This method prefers the less nested one and, if there are two at # the same level, the one with shorter module name. def table_name_to_namespaced_model(table_name) # First assume that there are no namespaces model = to_class(table_name.singularize.camelcase) return model if model != nil # If you were wrong, assume that the model is in a namespace. # Iterate over the underscores and try to substitute each of them # for a slash that camelcase() replaces with the scope operator (::). underscore_position = table_name.index('_') while underscore_position != nil namespaced_table_name = table_name.dup namespaced_table_name[underscore_position] = '/' model = to_class(namespaced_table_name.singularize.camelcase) return model if model != nil underscore_position = table_name.index('_', underscore_position + 1) end # The model either is not defined or is buried more than one level # deep in a module hierarchy return nil end # Checks if there is a class of specified name and if so, returns # the class object. Otherwise returns nil. def to_class(name) # I wanted to use Module.const_defined?() here to avoid relying # on exceptions for normal program flow but it's of no use. # If class autoloading is enabled, the constant may be undefined # but turn out to be present when we actually try to use it. begin constant = name.constantize rescue NameError return nil rescue LoadError => e $stderr.puts "failed to load '#{name}', ignoring (#{e.class}: #{e.message})" return nil end return constant.is_a?(Class) ? constant : nil end end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/railtie.rb000066400000000000000000000023661510251553000255310ustar00rootroot00000000000000module GettextI18nRails class Railtie < ::Rails::Railtie config.gettext_i18n_rails = ActiveSupport::OrderedOptions.new config.gettext_i18n_rails.msgmerge = nil config.gettext_i18n_rails.msgcat = nil config.gettext_i18n_rails.xgettext = nil config.gettext_i18n_rails.use_for_active_record_attributes = true config.gettext_i18n_rails.auto_reload = Rails.env.development? rake_tasks do if Gem::Specification.find_all_by_name("gettext", ">= 3.0.2").any? require 'gettext_i18n_rails/tasks' end end config.after_initialize do |app| if app.config.gettext_i18n_rails.use_for_active_record_attributes ActiveSupport.on_load :active_record do require 'gettext_i18n_rails/active_model' end end # Auto-reload .po and .mo files when they change if app.config.gettext_i18n_rails.auto_reload po_files = Dir[Rails.root.join("locale/**/*.{po,mo}")] reloader = ActiveSupport::FileUpdateChecker.new(po_files) do FastGettext.translation_repositories.each_value(&:reload) Rails.logger.info "Reloaded gettext translations" end app.executor.to_run do reloader.execute_if_updated end end end end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/slim_parser.rb000066400000000000000000000004561510251553000264160ustar00rootroot00000000000000require 'gettext_i18n_rails/base_parser' module GettextI18nRails class SlimParser < BaseParser def self.extension "slim" end def self.convert_to_code(text) Slim::Engine.new.call(text) end end end GettextI18nRails::GettextHooks.add_parser GettextI18nRails::SlimParser grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/string_interpolate_fix.rb000066400000000000000000000010311510251553000306460ustar00rootroot00000000000000needed = "".respond_to?(:html_safe) and ( "".html_safe % {:x => '
'} == '
' or not ("".html_safe % {:x=>'a'}).html_safe? ) if needed class String alias :interpolate_without_html_safe :% def %(*args) if args.first.is_a?(Hash) and html_safe? safe_replacement = Hash[args.first.map{|k,v| [k,ERB::Util.h(v)] }] interpolate_without_html_safe(safe_replacement).html_safe else interpolate_without_html_safe(*args).dup # make sure its not html_safe end end end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/tasks.rb000066400000000000000000000074511510251553000252250ustar00rootroot00000000000000require "gettext/tools/task" gem "gettext", ">= 3.0.2" namespace :gettext do def locale_path path = FastGettext.translation_repositories[text_domain].instance_variable_get(:@options)[:path] rescue nil path || File.join(Rails.root, "locale") end def text_domain # if your textdomain is not 'app': require the environment before calling e.g. gettext:find OR add TEXTDOMAIN=my_domain (FastGettext.text_domain rescue nil) || ENV['TEXTDOMAIN'] || "app" end # do not rename, gettext_i18n_rails_js overwrites this to inject coffee + js def files_to_translate Dir.glob("{app,lib,config,#{locale_path}}/**/*.{rb,erb,haml,slim}") end def gettext_default_options config = (Rails.application.config.gettext_i18n_rails.default_options if defined?(Rails.application)) config || %w[--sort-by-msgid --no-location --no-wrap] end def gettext_msgmerge_options config = (Rails.application.config.gettext_i18n_rails.msgmerge if defined?(Rails.application)) config || gettext_default_options end def gettext_msgcat_options config = (Rails.application.config.gettext_i18n_rails.msgcat if defined?(Rails.application)) config || gettext_default_options - %w[--location] end def gettext_xgettext_options config = (Rails.application.config.gettext_i18n_rails.xgettext if defined?(Rails.application)) config || gettext_default_options end require "gettext_i18n_rails/haml_parser" require "gettext_i18n_rails/slim_parser" task :setup => [:environment] do GetText::Tools::Task.define do |task| task.package_name = text_domain task.package_version = "1.0.0" task.domain = text_domain task.po_base_directory = locale_path task.mo_base_directory = locale_path task.files = files_to_translate task.enable_description = false task.msgmerge_options = gettext_msgmerge_options task.msgcat_options = gettext_msgcat_options task.xgettext_options = gettext_xgettext_options end end desc "Create mo-files" task :pack => [:setup] do Rake::Task["gettext:mo:update"].invoke end desc "Update pot/po files" task :find => [:setup] do Rake::Task["gettext:po:update"].invoke end # This is more of an example, ignoring # the columns/tables that mostly do not need translation. # This can also be done with GetText::ActiveRecord # but this crashed too often for me, and # IMO which column should/should-not be translated does not # belong into the model # # You can get your translations from GetText::ActiveRecord # by adding this to you gettext:find task # # require 'active_record' # gem "gettext_activerecord", '>=0.1.0' #download and install from github # require 'gettext_activerecord/parser' desc "write the model attributes to /model_attributes.rb" task :store_model_attributes => :environment do FastGettext.silence_errors require 'gettext_i18n_rails/model_attributes_finder' require 'gettext_i18n_rails/active_record' storage_file = "#{locale_path}/model_attributes.rb" puts "writing model translations to: #{storage_file}" GettextI18nRails.store_model_attributes( :to => storage_file, :ignore_columns => [/_id$/, 'id', 'type', 'created_at', 'updated_at'], :ignore_tables => GettextI18nRails::IGNORE_TABLES ) end desc "add a new language" task :add_language, [:language] => :environment do |_, args| language = args.language || ENV["LANGUAGE"] # Let's do some pre-verification of the environment. if language.nil? puts "You need to specify the language to add. Either 'LANGUAGE=eo rake gettext:add_language' or 'rake gettext:add_language[eo]'" next end language_path = File.join(locale_path, language) mkdir_p(language_path) Rake.application.lookup('gettext:find', _.scope).invoke end end grosser-gettext_i18n_rails-885ef82/lib/gettext_i18n_rails/version.rb000066400000000000000000000000721510251553000255550ustar00rootroot00000000000000module GettextI18nRails Version = VERSION = '2.1.0' end grosser-gettext_i18n_rails-885ef82/lib/tasks/000077500000000000000000000000001510251553000211545ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/lib/tasks/gettext_rails_i18n.rake000066400000000000000000000001121510251553000255270ustar00rootroot00000000000000require File.join(File.dirname(__FILE__), "/../gettext_i18n_rails/tasks") grosser-gettext_i18n_rails-885ef82/spec/000077500000000000000000000000001510251553000202135ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/000077500000000000000000000000001510251553000237305ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/action_controller_spec.rb000066400000000000000000000024531510251553000310130ustar00rootroot00000000000000require "spec_helper" FastGettext.silence_errors describe ActionController::Base do def reset! fake_session = {} @c.stub(:session).and_return fake_session fake_cookies = {} @c.stub(:cookies).and_return fake_cookies @c.params = {} @c.request = double(:env => {}) end before do #controller @c = ActionController::Base.new reset! #locale FastGettext.available_locales = nil FastGettext.locale = I18n.default_locale = 'fr' FastGettext.available_locales = ['fr','en'] end it "changes the locale" do @c.params = {:locale=>'en'} @c.set_gettext_locale @c.session[:locale].should == 'en' FastGettext.locale.should == 'en' end it "stays with default locale when none was found" do @c.set_gettext_locale @c.session[:locale].should == 'fr' FastGettext.locale.should == 'fr' end it "locale isn't cached over request" do @c.params = {:locale=>'en'} @c.set_gettext_locale @c.session[:locale].should == 'en' reset! @c.set_gettext_locale @c.session[:locale].should == 'fr' end it "reads the locale from the HTTP_ACCEPT_LANGUAGE" do @c.request.stub(:env).and_return 'HTTP_ACCEPT_LANGUAGE'=>'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3' @c.set_gettext_locale FastGettext.locale.should == 'en' end end grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/active_model/000077500000000000000000000000001510251553000263635ustar00rootroot00000000000000grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/active_model/name_spec.rb000066400000000000000000000013431510251553000306430ustar00rootroot00000000000000# encoding: utf-8 require "spec_helper" if ActiveRecord::VERSION::MAJOR >= 3 require "gettext_i18n_rails/active_model/name" describe ActiveModel::Name do before do FastGettext.reload! end describe '#human' do it "is translated through FastGettext" do name = ActiveModel::Name.new(CarSeat) name.should_receive(:_).with('Car seat').and_return('Autositz') name.human.should == 'Autositz' end it "is translated through FastGettext in plural form" do name = ActiveModel::Name.new(CarSeat) name.should_receive(:n_).with('Car seat', 'Car seats', 2).and_return('Сиденья') name.human(count: 2).should == 'Сиденья' end end end end grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/active_record_spec.rb000066400000000000000000000051541510251553000301050ustar00rootroot00000000000000# coding: utf-8 require "spec_helper" describe ActiveRecord::Base do before do FastGettext.reload! end describe :human_name do it "is translated through FastGettext" do CarSeat.should_receive(:_).with('Car seat').and_return('Autositz') CarSeat.human_name.should == 'Autositz' end end describe :human_attribute_name do it "translates attributes through FastGettext" do CarSeat.should_receive(:s_).with('CarSeat|Seat color').and_return('Sitz farbe') CarSeat.human_attribute_name(:seat_color).should == 'Sitz farbe' end it "translates nested attributes through FastGettext" do CarSeat.should_receive(:s_).with('CarSeat|Parts|Name').and_return('Handle') CarSeat.human_attribute_name(:"parts.name").should == 'Handle' end it "translates attributes of STI classes through FastGettext" do StiChild.should_receive(:s_).with('StiParent|Child attribute').and_return('Kinderattribut') StiChild.human_attribute_name(:child_attribute).should == 'Kinderattribut' end it "translates attributes of concrete children of abstract parent classes" do ConcreteChildClass.should_receive(:s_).with('AbstractParentClass|Child attribute').and_return('Kinderattribut') ConcreteChildClass.human_attribute_name(:child_attribute).should == 'Kinderattribut' end end describe :gettext_translation_for_attribute_name do it "translates foreign keys to model name keys" do Part.gettext_translation_for_attribute_name(:car_seat_id).should == 'Car seat' end end describe 'error messages' do let(:model){ c = CarSeat.new c.valid? c } it "translates error messages" do FastGettext.stub(:current_repository).and_return('translate me'=>"Übersetz mich!") FastGettext._('translate me').should == "Übersetz mich!" model.errors.full_messages.should == ["Seat color Übersetz mich!"] end it "translates scoped error messages" do pending 'scope is no longer added in 3.x' if ActiveRecord::VERSION::MAJOR >= 3 FastGettext.stub(:current_repository).and_return('activerecord.errors.translate me'=>"Übersetz mich!") FastGettext._('activerecord.errors.translate me').should == "Übersetz mich!" model.errors.full_messages.should == ["Seat color Übersetz mich!"] end it "translates error messages with %{fn}" do pending FastGettext.stub(:current_repository).and_return('translate me'=>"Übersetz %{fn} mich!") FastGettext._('translate me').should == "Übersetz %{fn} mich!" model.errors[:seat_color].should == ["Übersetz car_seat mich!"] end end end grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/backend_spec.rb000066400000000000000000000124731510251553000266650ustar00rootroot00000000000000# encoding: UTF-8 require "spec_helper" FastGettext.silence_errors describe GettextI18nRails::Backend do subject { GettextI18nRails::Backend.new } before do FastGettext.reload! end it "redirects calls to another I18n backend" do subject.backend.should_receive(:xxx).with(1,2) subject.xxx(1,2) end describe :available_locales do it "maps them to FastGettext" do FastGettext.should_receive(:available_locales).and_return [:xxx] subject.available_locales.should == [:xxx] end it "and returns an empty array when FastGettext.available_locales is nil" do FastGettext.should_receive(:available_locales).and_return nil subject.available_locales.should == [] end end describe :translate do it "uses gettext when the key is translatable" do FastGettext.should_receive(:current_repository).and_return 'xy.z.u'=>'a' subject.translate('xx','u',:scope=>['xy','z']).should == 'a' end it "interpolates options" do FastGettext.should_receive(:current_repository).and_return 'ab.c'=>'a%{a}b' subject.translate('xx','c',:scope=>['ab'], :a => 'X').should == 'aXb' end it "will not try and interpolate when there are no options given" do FastGettext.should_receive(:current_repository).and_return 'ab.d' => 'a%{a}b' subject.translate('xx', 'd', :scope=>['ab']).should == 'a%{a}b' end it "uses plural translation if count is given" do repo = {'ab.e' => 'existing'} repo.should_receive(:plural).and_return %w(single plural) repo.stub(:pluralisation_rule).and_return nil FastGettext.stub(:current_repository).and_return repo subject.translate('xx', 'ab.e', :count => 1).should == 'single' subject.translate('xx', 'ab.e', :count => 2).should == 'plural' end it "interpolates a count without plural translations" do repo = {'ab.e' => 'existing %{count}'} repo.should_receive(:plural).and_return [] repo.stub(:pluralisation_rule).and_return lambda { |i| true } FastGettext.stub(:current_repository).and_return repo FastGettext.should_receive(:set_locale).with('xx').and_return('xx') FastGettext.should_receive(:set_locale).with(:en).and_return(:en) subject.translate('xx', 'ab.e', :count => 1).should == 'existing 1' end it "can translate with gettext using symbols" do FastGettext.should_receive(:current_repository).and_return 'xy.z.v'=>'a' subject.translate('xx',:v ,:scope=>['xy','z']).should == 'a' end it "can translate with gettext using a flat scope" do FastGettext.should_receive(:current_repository).and_return 'xy.z.x'=>'a' subject.translate('xx',:x ,:scope=>'xy.z').should == 'a' end it "passes non-gettext keys to default backend" do subject.backend.should_receive(:translate).with('xx', 'c', {}).and_return 'd' # TODO track down why this is called 3 times on 1.8 (only 1 time on 1.9) FastGettext.stub(:current_repository).and_return 'a'=>'b' subject.translate('xx', 'c', {}).should == 'd' end it "passes non-gettext keys to default backend without modifying frozen translation" do subject.backend.should_receive(:translate).with('xx', 'c', {}).and_return 'd'.freeze # TODO track down why this is called 3 times on 1.8 (only 1 time on 1.9) FastGettext.stub(:current_repository).and_return 'a'=>'b' subject.translate('xx', 'c', {}).should == 'd' end it 'temporarily sets the given locale' do FastGettext.should_receive(:set_locale).with('xx').and_return('xy') FastGettext.should_receive(:set_locale).with('xy').and_return('xx') FastGettext.should_receive(:set_locale).with(:en).and_return('xx') subject.backend.should_receive(:translate).with('xx', 'c', {}).and_return 'd' FastGettext.locale= 'xy' FastGettext.stub(:current_repository).and_return 'a'=>'b' subject.translate('xx', 'c', {}).should == 'd' end if RUBY_VERSION > "1.9" it "produces UTF-8 when not using FastGettext to fix weird encoding bug" do subject.backend.should_receive(:translate).with('xx', 'c', {}).and_return 'ü'.force_encoding("US-ASCII") FastGettext.should_receive(:set_locale).with('xx').and_return('xx') FastGettext.should_receive(:set_locale).with(:en).and_return(:en) FastGettext.should_receive(:current_repository).and_return 'a'=>'b' result = subject.translate('xx', 'c', {}) result.should == 'ü' end it "does not force_encoding on non-strings" do subject.backend.should_receive(:translate).with('xx', 'c', {}).and_return ['aa'] FastGettext.should_receive(:set_locale).with('xx').and_return('xx') FastGettext.should_receive(:set_locale).with(:en).and_return(:en) FastGettext.should_receive(:current_repository).and_return 'a'=>'b' result = subject.translate('xx', 'c', {}) result.should == ['aa'] end end # TODO NameError is raised <-> wtf ? xit "uses the super when the key is not translatable" do lambda{subject.translate('xx','y',:scope=>['xy','z'])}.should raise_error(I18n::MissingTranslationData) end end describe :interpolate do it "act as an identity function for an array" do translation = [:month, :day, :year] subject.send(:interpolate, translation, {}).should == translation end end end grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/haml_parser_spec.rb000066400000000000000000000061151510251553000275670ustar00rootroot00000000000000require "spec_helper" require "gettext_i18n_rails/haml_parser" describe GettextI18nRails::HamlParser do let(:parser){ GettextI18nRails::HamlParser } describe "#target?" do it "targets .haml" do parser.target?('foo/bar/xxx.haml').should == true end it "does not target anything else" do parser.target?('foo/bar/xxx.erb').should == false end end describe "#parse" do ["haml", "hamlit"].each do |library| context "with #{library} library only" do before do GettextI18nRails::HamlParser.stub(:libraries).and_return([library]) GettextI18nRails::HamlParser.instance_variable_set(:@library_loaded, false) end it "finds messages in haml" do with_file '= _("xxxx")', '.haml' do |path| po = parser.parse(path, {}, []) po.entries.should match_array([ have_attributes({ msgctxt: nil, msgid: "xxxx", type: :normal, references: ["#{path}:1"] }) ]) end end it "finds messages with concatenation" do with_file '= _("xxxx" + "yyyy" + "zzzz")', '.haml' do |path| po = parser.parse(path, {}, []) po.entries.should match_array([ have_attributes({ msgctxt: nil, msgid: "xxxxyyyyzzzz", type: :normal, references: ["#{path}:1"] }) ]) end end it "finds messages with context in haml" do with_file '= p_("My context", "idkey")', '.haml' do |path| po = parser.parse(path, {}, []) po.entries.should match_array([ have_attributes({ msgctxt: "My context", msgid: "idkey", type: :msgctxt, references: ["#{path}:1"] }) ]) end end it "should parse the 1.9 if ruby_version is 1.9" do if RUBY_VERSION =~ /^1\.9/ || RUBY_VERSION > "2" with_file '= _("xxxx", x: 1)', '.haml' do |path| po = parser.parse(path, {}, []) po.entries.should match_array([ have_attributes({ msgctxt: nil, msgid: "xxxx", type: :normal, references: ["#{path}:1"] }) ]) end end end it "does not find messages in text" do with_file '_("xxxx")', '.haml' do |path| po = parser.parse(path, {}, []) po.entries.empty?.should == true end end it "does not include parser options into parsed output" do with_file '= _("xxxx")' do |path| GetText::RubyParser.stub(:new).and_return(double("mockparser", parse_source: [])) parser.parse(path, { comment_tag: "TRANSLATORS:" }) GetText::RubyParser.should have_received(:new).with(path, { comment_tag: "TRANSLATORS:" }) end end end end end end grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/model_attributes_finder_spec.rb000066400000000000000000000031451510251553000321670ustar00rootroot00000000000000# coding: utf-8 require "spec_helper" require "gettext_i18n_rails/model_attributes_finder" if Rails::VERSION::MAJOR > 2 module Test class Application < Rails::Application end end end describe GettextI18nRails::ModelAttributesFinder do let(:finder) { GettextI18nRails::ModelAttributesFinder.new } before do Rails.application rescue nil end # Rails < 3.0 doesn't have DescendantsTracker. # Instead of iterating over ObjectSpace (slow) the decision was made NOT to support # class hierarchies with abstract base classes in Rails 2.x describe "#find" do it "returns all AR models" do keys = finder.find({}).keys expected = [CarSeat, Part, StiParent] expected.concat [AbstractParentClass, NotConventional] if Rails::VERSION::MAJOR >= 3 expected.concat [ActiveRecord::SchemaMigration] if Rails::VERSION::MAJOR >= 4 && !(Rails::VERSION::MAJOR == 7 && Rails::VERSION::MINOR > 0) expected.concat [ActiveRecord::InternalMetadata] if Rails::VERSION::MAJOR >= 5 && !(Rails::VERSION::MAJOR == 7 && Rails::VERSION::MINOR > 0) keys.should =~ expected end it "returns all columns for each model" do attributes = finder.find({}) attributes[CarSeat].should == ['id', 'seat_color'] attributes[NotConventional].should == ['id', 'name'] if Rails::VERSION::MAJOR > 2 attributes[Part].should == ['car_seat_id', 'id', 'name'] attributes[StiParent].should == ['child_attribute', 'id', 'type'] attributes[AbstractParentClass].should == ['another_child_attribute', 'child_attribute', 'id'] if Rails::VERSION::MAJOR > 2 end end end grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/railtie_spec.rb000066400000000000000000000007361510251553000267260ustar00rootroot00000000000000require 'spec_helper' describe GettextI18nRails::Railtie do describe 'auto-reload configuration' do it 'can be set to true or false' do config = GettextI18nRails::Railtie.config.gettext_i18n_rails config.auto_reload = true config.auto_reload.should == true end it 'can be disabled' do config = GettextI18nRails::Railtie.config.gettext_i18n_rails config.auto_reload = false config.auto_reload.should == false end end end grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/slim_parser_spec.rb000066400000000000000000000024301510251553000276060ustar00rootroot00000000000000require "spec_helper" require "gettext_i18n_rails/slim_parser" describe GettextI18nRails::SlimParser do let(:parser){ GettextI18nRails::SlimParser } describe "#target?" do it "targets .slim" do parser.target?('foo/bar/xxx.slim').should == true end it "does not target anything else" do parser.target?('foo/bar/xxx.erb').should == false end end describe "#parse" do it "finds messages in slim" do with_file 'div = _("xxxx")' do |path| po = parser.parse(path, {}, []) po.entries.should match_array([ have_attributes({ msgctxt: nil, msgid: "xxxx", type: :normal, references: ["#{path}:1"] }) ]) end end it "can parse 1.9 syntax" do with_file 'div = _("xxxx", foo: :bar)' do |path| po = parser.parse(path, {}, []) po.entries.should match_array([ have_attributes({ msgctxt: nil, msgid: "xxxx", type: :normal, references: ["#{path}:1"] }) ]) end end it "does not find messages in text" do with_file 'div _("xxxx")' do |path| po = parser.parse(path, {}, []) po.entries.empty?.should == true end end end end grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb000066400000000000000000000015321510251553000320520ustar00rootroot00000000000000require "spec_helper" require "gettext_i18n_rails/string_interpolate_fix" describe "String#%" do it "is not safe if it was not safe" do result = ("
%{x}" % {:x => 'a'}) result.should == '
a' result.html_safe?.should == false end xit "stays safe if it was safe" do result = ("
%{x}".html_safe % {:x => 'a'}) result.should == '
a' result.html_safe?.should == true end xit "escapes unsafe added to safe" do result = ("
%{x}".html_safe % {:x => '
'}) result.should == '
<br/>' result.html_safe?.should == true end it "does not escape unsafe if it was unsafe" do result = ("
%{x}" % {:x => '
'}) result.should == '

' result.html_safe?.should == false end it "does not break array replacement" do "%ssd" % ['a'].should == "asd" end end grosser-gettext_i18n_rails-885ef82/spec/gettext_i18n_rails_spec.rb000066400000000000000000000076311510251553000252760ustar00rootroot00000000000000require "spec_helper" FastGettext.silence_errors describe GettextI18nRails do before do GettextI18nRails.translations_are_html_safe = nil end it "extends all classes with fast_gettext" do _('test') end describe 'translations_are_html_safe' do before do GettextI18nRails.translations_are_html_safe = nil end it "makes translations not html_safe by default" do _('x').html_safe?.should == false s_('x').html_safe?.should == false n_('x','y',2).html_safe?.should == false String._('x').html_safe?.should == false String.s_('x').html_safe?.should == false String.n_('x','y',2).html_safe?.should == false end it "makes instance translations html_safe when wanted" do GettextI18nRails.translations_are_html_safe = true _('x').html_safe?.should == true s_('x').html_safe?.should == true n_('x','y',2).html_safe?.should == true end it "makes class translations html_safe when wanted" do GettextI18nRails.translations_are_html_safe = true String._('x').html_safe?.should == true String.s_('x').html_safe?.should == true String.n_('x','y',2).html_safe?.should == true end it "does not make everything html_safe" do 'x'.html_safe?.should == false end end it "sets up out backend" do I18n.backend.is_a?(GettextI18nRails::Backend).should == true end it "has a VERSION" do GettextI18nRails::VERSION.should =~ /^\d+\.\d+\.\d+$/ end describe 'FastGettext I18n interaction' do before do FastGettext.available_locales = nil FastGettext.locale = 'de' end it "links FastGettext with I18n locale" do FastGettext.locale = 'xx' I18n.locale.should == :xx end it "does not set an not-accepted locale to I18n.locale" do FastGettext.available_locales = ['de'] FastGettext.locale = 'xx' I18n.locale.should == :de end it "links I18n.locale and FastGettext.locale" do I18n.locale = :yy FastGettext.locale.should == 'yy' end it "does not set a non-available locale though I18n.locale" do FastGettext.available_locales = ['de'] I18n.locale = :xx FastGettext.locale.should == 'de' I18n.locale.should == :de end it "converts gettext to i18n style for nested locales" do FastGettext.available_locales = ['de_CH'] I18n.locale = :"de-CH" FastGettext.locale.should == 'de_CH' I18n.locale.should == :"de-CH" end end describe "GetText PO file creation" do before do require "gettext_i18n_rails/haml_parser" require "gettext_i18n_rails/slim_parser" end it "parses haml" do haml_content = <<~EOR = _("xxxx") = p_("Context", "key") _("JustText") EOR with_file haml_content, '.haml' do |path| po = GettextI18nRails::GettextHooks.xgettext.new.parse(path) po.entries.should match_array([ have_attributes({ msgctxt: nil, msgid: "xxxx", type: :normal, references: ["#{path}:1"] }), have_attributes({ msgctxt: "Context", msgid: "key", type: :msgctxt, references: ["#{path}:2"] }) ]) end end it "parses slim" do slim_content = <<~EOR div = _("xxxx") div = p_("Context", "key") div _("JustText") EOR with_file slim_content, '.slim' do |path| po = GettextI18nRails::GettextHooks.xgettext.new.parse(path) po.entries.should match_array([ have_attributes({ msgctxt: nil, msgid: "xxxx", type: :normal, references: ["#{path}:1"] }), have_attributes({ msgctxt: "Context", msgid: "key", type: :msgctxt, references: ["#{path}:2"] }) ]) end end end end grosser-gettext_i18n_rails-885ef82/spec/spec_helper.rb000066400000000000000000000062621510251553000230370ustar00rootroot00000000000000require 'active_support/version' if RUBY_VERSION > "2" && ActiveSupport::VERSION::MAJOR == 2 warn "Not running ruby 2 vs rails 2 tests" exit 0 end require 'tempfile' require 'active_support' require 'active_support/core_ext/string/output_safety' require 'rails/railtie' require 'active_record' require 'action_controller' require 'action_mailer' require 'fast_gettext' # Define minimal Rails stub for library compatibility # Rails::VERSION::MAJOR is checked by action_controller.rb at load time module Rails module VERSION MAJOR = 7 end def self.root File.dirname(__FILE__) end def self.env ActiveSupport::StringInquirer.new('test') end end require 'gettext_i18n_rails' # Manually load ActiveRecord/ActiveModel extensions since we're not running full Rails initialization # In a real Rails app, these would be loaded via the Railtie's after_initialize hook require 'gettext_i18n_rails/active_model' require 'gettext_i18n_rails/active_record' require 'temple' if ActiveSupport::VERSION::MAJOR >= 3 I18n.enforce_available_locales = false # maybe true ... not sure end RSpec.configure do |config| config.expect_with(:rspec) { |c| c.syntax = :should } config.mock_with(:rspec) { |c| c.syntax = :should } end begin Gem.all_load_paths rescue module Gem;def self.all_load_paths;[];end;end end # make temple not blow up in rails 2 env class << Temple::Templates alias_method :method_missing_old, :method_missing def method_missing(name, engine, options = {}) name == :Rails || method_missing_old(name, engine, options) end end def with_file(content, extension = '') Tempfile.open(['gettext_i18n_rails_specs', extension]) do |f| f.write(content) f.close yield f.path end end ActiveRecord::Base.establish_connection( :adapter => "sqlite3", :database => ":memory:" ) ActiveRecord::Schema.verbose = false ActiveRecord::Schema.define(:version => 1) do create_table :car_seats, :force=>true do |t| t.string :seat_color end create_table :parts, :force=>true do |t| t.string :name t.references :car_seat end create_table :not_at_all_conventionals, :force=>true do |t| t.string :name end create_table :sti_parents, :force => true do |t| t.string :type t.string :child_attribute end create_table :concrete_child_classes, :force => true do |t| t.string :child_attribute end create_table :other_concrete_child_classes, :force => true do |t| t.string :another_child_attribute end end class CarSeat < ActiveRecord::Base validates_presence_of :seat_color, :message=>"translate me" has_many :parts accepts_nested_attributes_for :parts end class Part < ActiveRecord::Base belongs_to :car_seat end class StiParent < ActiveRecord::Base; end class StiChild < StiParent; end class AbstractParentClass < ActiveRecord::Base self.abstract_class = true end class ConcreteChildClass < AbstractParentClass; end class OtherConcreteChildClass < AbstractParentClass; end class NotConventional < ActiveRecord::Base if ActiveRecord::VERSION::MAJOR == 2 set_table_name :not_at_all_conventionals else self.table_name = :not_at_all_conventionals end end class Idea < ActiveRecord::Base self.abstract_class = true end