mova-i18n 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/.gitignore +14 -0
 - data/.yardopts +1 -0
 - data/CONTRIBUTING.md +47 -0
 - data/Gemfile +26 -0
 - data/LICENSE.txt +22 -0
 - data/README.md +93 -0
 - data/Rakefile +24 -0
 - data/lib/mova-i18n.rb +77 -0
 - data/lib/mova-i18n/bridge.rb +69 -0
 - data/lib/mova-i18n/config.rb +36 -0
 - data/mova-i18n.gemspec +21 -0
 - data/test/exists_test.rb +29 -0
 - data/test/locale/en.yml +2 -0
 - data/test/localize_test.rb +58 -0
 - data/test/mova_config_test.rb +17 -0
 - data/test/test_helper.rb +61 -0
 - data/test/transfer_translations_test.rb +27 -0
 - data/test/translate/default_test.rb +45 -0
 - data/test/translate/pluralization_test.rb +62 -0
 - data/test/translate/scope_test.rb +26 -0
 - data/test/translate_test.rb +61 -0
 - data/test/transliterate_test.rb +28 -0
 - data/test_rails/dummy/.gitignore +15 -0
 - data/test_rails/dummy/app/controllers/hello_controller.rb +2 -0
 - data/test_rails/dummy/app/views/hello/html_safe_key.html.erb +1 -0
 - data/test_rails/dummy/app/views/hello/html_safe_underscored.html.erb +1 -0
 - data/test_rails/dummy/app/views/hello/html_unsafe.html.erb +1 -0
 - data/test_rails/dummy/app/views/hello/locale_option.html.erb +1 -0
 - data/test_rails/dummy/app/views/hello/missing_translation.html.erb +1 -0
 - data/test_rails/dummy/app/views/hello/partial_scope.html.erb +1 -0
 - data/test_rails/dummy/app/views/hello/raise_error.html.erb +1 -0
 - data/test_rails/dummy/app/views/hello/translate.html.erb +1 -0
 - data/test_rails/dummy/config.ru +4 -0
 - data/test_rails/dummy/config/application.rb +13 -0
 - data/test_rails/dummy/config/environment.rb +5 -0
 - data/test_rails/dummy/config/environments/test.rb +10 -0
 - data/test_rails/dummy/config/locales/uk.rb +20 -0
 - data/test_rails/dummy/config/locales/uk.yml +252 -0
 - data/test_rails/dummy/config/locales/views.yml +11 -0
 - data/test_rails/helpers_test.rb +37 -0
 - data/test_rails/test_helper.rb +11 -0
 - data/test_rails/view_test.rb +55 -0
 - metadata +154 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 7f5ffd7156c6938db949bd1356541156f14cd25f
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: c9b80e1787bfa36cad7e9184b8ead9f4a0bd498b
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 25d4e0d8c815e7dd6580a72b82d5f1887d466f06e569dd60820cd03e4a9d3dd4128f808c0f9c20ea456ec135d913033d14f73cc930a354719f13160e6fe67de4
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: efb39f365dd204519860140b414d38d4cff408d6611c41da1057b065a948b3be382aaec838ba039a1d7c656e64e685162739d2df443b35493108066448de3492
         
     | 
    
        data/.gitignore
    ADDED
    
    
    
        data/.yardopts
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --no-private
         
     | 
    
        data/CONTRIBUTING.md
    ADDED
    
    | 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Contributing
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ## Adding a feature
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            1. Open an issue and explain what you're planning to do. It is better to discuss new idea first,
         
     | 
| 
      
 6 
     | 
    
         
            +
               rather when diving into code.
         
     | 
| 
      
 7 
     | 
    
         
            +
            2. Add some tests.
         
     | 
| 
      
 8 
     | 
    
         
            +
            3. Write the code.
         
     | 
| 
      
 9 
     | 
    
         
            +
            4. Make sure all tests pass.
         
     | 
| 
      
 10 
     | 
    
         
            +
            5. Commit with detailed explanation what you've done in a message.
         
     | 
| 
      
 11 
     | 
    
         
            +
            6. Open pull request.
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            ## Breaking/removing a feature
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            1. Add deprecation warning and fallback to old behaivour if possible.
         
     | 
| 
      
 16 
     | 
    
         
            +
            2. Explain how to migrate to the new code in CHANGELOG.
         
     | 
| 
      
 17 
     | 
    
         
            +
            3. Update/remove tests.
         
     | 
| 
      
 18 
     | 
    
         
            +
            4. Update the code.
         
     | 
| 
      
 19 
     | 
    
         
            +
            5. Make sure all tests pass.
         
     | 
| 
      
 20 
     | 
    
         
            +
            6. Commit with detailed explanation what you've done in a message.
         
     | 
| 
      
 21 
     | 
    
         
            +
            7. Open pull request.
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            ## Fixing a bug
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            1. Add failing test.
         
     | 
| 
      
 26 
     | 
    
         
            +
            2. Fix the bug.
         
     | 
| 
      
 27 
     | 
    
         
            +
            3. Make sure all tests pass.
         
     | 
| 
      
 28 
     | 
    
         
            +
            4. Commit with detailed explanation what you've done in a message.
         
     | 
| 
      
 29 
     | 
    
         
            +
            5. Open pull request.
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            ## Fixing a typo
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            1. Commit with a message that include "[ci skip]" remark.
         
     | 
| 
      
 34 
     | 
    
         
            +
            2. Open pull request.
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            ## Running the tests
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            ```
         
     | 
| 
      
 39 
     | 
    
         
            +
            rake bundle
         
     | 
| 
      
 40 
     | 
    
         
            +
            rake test
         
     | 
| 
      
 41 
     | 
    
         
            +
            ```
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            ## Working with documentation
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            ```
         
     | 
| 
      
 46 
     | 
    
         
            +
            yard server -dr
         
     | 
| 
      
 47 
     | 
    
         
            +
            open http://localhost:8808
         
     | 
    
        data/Gemfile
    ADDED
    
    | 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            source 'https://rubygems.org'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            gemspec
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            gem "rspec-mocks", "~> 3.0"
         
     | 
| 
      
 6 
     | 
    
         
            +
            gem "yard", "~> 0.8"
         
     | 
| 
      
 7 
     | 
    
         
            +
            gem "pry"
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            case ENV["RAILS"]
         
     | 
| 
      
 10 
     | 
    
         
            +
            when "3.2"
         
     | 
| 
      
 11 
     | 
    
         
            +
              version = "~> 3.2.19"
         
     | 
| 
      
 12 
     | 
    
         
            +
              gem "actionpack", version
         
     | 
| 
      
 13 
     | 
    
         
            +
              gem "railties", version
         
     | 
| 
      
 14 
     | 
    
         
            +
              gem "tzinfo", "~> 0.3.29"
         
     | 
| 
      
 15 
     | 
    
         
            +
              gem "minitest", "~> 4.2"
         
     | 
| 
      
 16 
     | 
    
         
            +
            when "4.0"
         
     | 
| 
      
 17 
     | 
    
         
            +
              version = '~> 4.0.0'
         
     | 
| 
      
 18 
     | 
    
         
            +
              gem 'actionpack', version
         
     | 
| 
      
 19 
     | 
    
         
            +
              gem 'railties', version
         
     | 
| 
      
 20 
     | 
    
         
            +
              gem "minitest", "~> 4.2"
         
     | 
| 
      
 21 
     | 
    
         
            +
            when nil, "4.1"
         
     | 
| 
      
 22 
     | 
    
         
            +
              version = '~> 4.1.0'
         
     | 
| 
      
 23 
     | 
    
         
            +
              gem 'actionpack', version
         
     | 
| 
      
 24 
     | 
    
         
            +
              gem 'railties', version
         
     | 
| 
      
 25 
     | 
    
         
            +
              gem "minitest", "~> 5.4"
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
    
        data/LICENSE.txt
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) 2014 Andrii Malyshko
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 6 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 7 
     | 
    
         
            +
            "Software"), to deal in the Software without restriction, including
         
     | 
| 
      
 8 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 9 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 10 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 11 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 14 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 17 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 18 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         
     | 
| 
      
 19 
     | 
    
         
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         
     | 
| 
      
 20 
     | 
    
         
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         
     | 
| 
      
 21 
     | 
    
         
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         
     | 
| 
      
 22 
     | 
    
         
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,93 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Mova-I18n
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            **Mova-I18n** overwrites `translate/t` method of [I18n][i18n] in a way that delegates it to
         
     | 
| 
      
 4 
     | 
    
         
            +
            [Mova][mova] internals without major breaking of I18n API. This speeds up translation
         
     | 
| 
      
 5 
     | 
    
         
            +
            lookups while staying compatible with libraries that rely on I18n.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ## Status
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Not tested in production.
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Add this line to your application's Gemfile and run `bundle`:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 16 
     | 
    
         
            +
            gem 'mova-i18n'
         
     | 
| 
      
 17 
     | 
    
         
            +
            ```
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ## Configuration
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            No configuration is needed if you have in-memory `I18n::Backend::Simple` backend (used in Rails
         
     | 
| 
      
 22 
     | 
    
         
            +
            apps by default). Mova-I18n will use I18n setup (including locale fallbacks) and automatically
         
     | 
| 
      
 23 
     | 
    
         
            +
            load translations stored in local files.
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            When using other persistent key-value storage, you probably need chain configuration like this:
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 28 
     | 
    
         
            +
            require "mova/storage/chain"
         
     | 
| 
      
 29 
     | 
    
         
            +
            require "mova/storage/readonly"
         
     | 
| 
      
 30 
     | 
    
         
            +
            require "mova/storage/memory"
         
     | 
| 
      
 31 
     | 
    
         
            +
            redis = ActiveSupport::Cache::RedisStore.new("localhost:6379/0")
         
     | 
| 
      
 32 
     | 
    
         
            +
            chain = Mova::Storage::Chain.new(Mova::Storage::Readonly.new(redis), Mova::Storage::Memory.new)
         
     | 
| 
      
 33 
     | 
    
         
            +
            I18n.mova.translator = Mova::I18nTranslator.new(storage: chain)
         
     | 
| 
      
 34 
     | 
    
         
            +
            ```
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            Note, that you must pass your storage wrapped in `Readonly`, otherwise `I18n.reload!` will clear
         
     | 
| 
      
 37 
     | 
    
         
            +
            all translations stored there when Rails boots up. It will also protect your storage from having 
         
     | 
| 
      
 38 
     | 
    
         
            +
            incompatible data written to it, such as hashes or procs (those are partially supported and can be 
         
     | 
| 
      
 39 
     | 
    
         
            +
            handled normally only with in-memory storage). Such configuration allows to override Rails default
         
     | 
| 
      
 40 
     | 
    
         
            +
            translations in your backend, since first storage takes precedence over next one.
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            ## Compatibility
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            ### Supported
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            * the following `I18n.translate` calls:
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 49 
     | 
    
         
            +
            I18n.t(:key)
         
     | 
| 
      
 50 
     | 
    
         
            +
            I18n.t("key")
         
     | 
| 
      
 51 
     | 
    
         
            +
            I18n.t(:key, locale: :fr)
         
     | 
| 
      
 52 
     | 
    
         
            +
            I18n.t(:key, raise: true)
         
     | 
| 
      
 53 
     | 
    
         
            +
            I18n.t(:key, throw: true)
         
     | 
| 
      
 54 
     | 
    
         
            +
            I18n.t(:key, fallback: true) # i.e. disabled locale fallback
         
     | 
| 
      
 55 
     | 
    
         
            +
            I18n.t(:key, default: :default_key_lookup)
         
     | 
| 
      
 56 
     | 
    
         
            +
            I18n.t(:key, default: "default translation")
         
     | 
| 
      
 57 
     | 
    
         
            +
            I18n.t(:key, default: [:default_key_lookup1, :default_key_lookup2])
         
     | 
| 
      
 58 
     | 
    
         
            +
            I18n.t(:key, default: [:default_key_lookup1, "default translation"])
         
     | 
| 
      
 59 
     | 
    
         
            +
            I18n.t(:key, scope: :key_scope)
         
     | 
| 
      
 60 
     | 
    
         
            +
            I18n.t(:key, scope: [:key_scope_part1, :key_scope_part2])
         
     | 
| 
      
 61 
     | 
    
         
            +
            I18n.t(:key, interpolation1: "value1", interpolation2: "value2")
         
     | 
| 
      
 62 
     | 
    
         
            +
            I18n.t(:key, count: 3)
         
     | 
| 
      
 63 
     | 
    
         
            +
            ```
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            Any combination of `locale`, `raise/throw`, `default`, `scope`, `count`, `fallback` options
         
     | 
| 
      
 66 
     | 
    
         
            +
            is also supported.
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            * `I18n.localize` and `I18n.transliterate`
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            * locale fallbacks
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            ### Partially supported
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            *  storing values other than String or nil is possible only with in-memory storage or with chain
         
     | 
| 
      
 75 
     | 
    
         
            +
            including in-memory storage (see "Configuration"). Although it violates one of the Mova design principles,
         
     | 
| 
      
 76 
     | 
    
         
            +
            Mova-I18n tries to be compatible with Rails localization helpers that require hashes to be
         
     | 
| 
      
 77 
     | 
    
         
            +
            returned from `I18n.t`, so it writes to and retrieves a couple of hashes from a storage.
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            ### Not supported
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            *  translations as procs, using procs in defaults. Actually, you can store them (see "Partially
         
     | 
| 
      
 82 
     | 
    
         
            +
            supported"), but they'll never be called. The only exception are the pluralization and transliteration
         
     | 
| 
      
 83 
     | 
    
         
            +
            rules (for compatibility with [Rails-I18n][rails-i18n] project).
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
               This means that **`default` option in Rails 4.x views won't work**, because Rails wraps it in a proc
         
     | 
| 
      
 86 
     | 
    
         
            +
            call. Although using `default` in a template is a bad practice anyway.
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
            *  bulk translation via `I18n.t([:first_key, :second_key])`. Use map instead.
         
     | 
| 
      
 89 
     | 
    
         
            +
            *  cascade lookup
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
            [mova]: https://github.com/mova-rb/mova
         
     | 
| 
      
 92 
     | 
    
         
            +
            [i18n]: https://github.com/svenfuchs/i18n
         
     | 
| 
      
 93 
     | 
    
         
            +
            [rails-i18n]: https://github.com/svenfuchs/rails-i18n
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "bundler/gem_tasks"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            rails_versions = %w(3.2 4.0 4.1)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            task :default => :test
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            task :bundle do
         
     | 
| 
      
 8 
     | 
    
         
            +
              rails_versions.each do |version|
         
     | 
| 
      
 9 
     | 
    
         
            +
                sh "RAILS=#{version} bundle"
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
            end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            task :test do
         
     | 
| 
      
 14 
     | 
    
         
            +
              $LOAD_PATH.unshift("test")
         
     | 
| 
      
 15 
     | 
    
         
            +
              Dir.glob("./test/**/*_test.rb").each { |file| require file}
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              rails_versions.each do |version|
         
     | 
| 
      
 18 
     | 
    
         
            +
                sh "RAILS=#{version} rake test:rails"
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            task "test:rails" do
         
     | 
| 
      
 23 
     | 
    
         
            +
              Dir.glob("./test_rails/**/*_test.rb").each { |file| require file}
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/mova-i18n.rb
    ADDED
    
    | 
         @@ -0,0 +1,77 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "i18n"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "mova"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "mova/interpolation/sprintf"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "mova-i18n/config"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "mova-i18n/bridge"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module I18n
         
     | 
| 
      
 8 
     | 
    
         
            +
              def self.mova
         
     | 
| 
      
 9 
     | 
    
         
            +
                Mova::I18nConfig
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              # make sure we can safely call `I18n.fallbacks` even
         
     | 
| 
      
 13 
     | 
    
         
            +
              # if `I18n::Backend::Fallbacks` was not required
         
     | 
| 
      
 14 
     | 
    
         
            +
              unless respond_to?(:fallbacks)
         
     | 
| 
      
 15 
     | 
    
         
            +
                def self.fallbacks
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @fallbacks ||= Hash.new { |h,k| h[k] = [k] }
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 21 
     | 
    
         
            +
                def translate(key, options = nil)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  options = options && options.dup || {}
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  locale = options[:locale] || config.locale
         
     | 
| 
      
 25 
     | 
    
         
            +
                  locale_with_fallbacks =
         
     | 
| 
      
 26 
     | 
    
         
            +
                    if options[:fallback]
         
     | 
| 
      
 27 
     | 
    
         
            +
                      # suppress locale fallbacks (inverted due to I18n fallbacks implementation)
         
     | 
| 
      
 28 
     | 
    
         
            +
                      [locale]
         
     | 
| 
      
 29 
     | 
    
         
            +
                    else
         
     | 
| 
      
 30 
     | 
    
         
            +
                      fallbacks[locale]
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  if (default = options[:default]) && !default.is_a?(Hash)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    defaults = Array(default)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    options[:default] = defaults.last.is_a?(String) ? defaults.pop : nil
         
     | 
| 
      
 36 
     | 
    
         
            +
                    key = Array(key).concat(defaults)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  if (count = options[:count])
         
     | 
| 
      
 40 
     | 
    
         
            +
                    zero_plural_key = :zero if count == 0
         
     | 
| 
      
 41 
     | 
    
         
            +
                    plural_key = mova.pluralizer(locale).call(count)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    key = Array(key).each_with_object([]) do |key, memo|
         
     | 
| 
      
 43 
     | 
    
         
            +
                      memo << Mova::Scope.join(key, zero_plural_key) if zero_plural_key
         
     | 
| 
      
 44 
     | 
    
         
            +
                      memo << Mova::Scope.join(key, plural_key)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      memo << key
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  if (scope = options[:scope])
         
     | 
| 
      
 50 
     | 
    
         
            +
                    scope = Array(scope)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    key = Array(key).map do |key|
         
     | 
| 
      
 52 
     | 
    
         
            +
                      Mova::Scope.join(scope + [key])
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  result = mova.translator.get(key, locale_with_fallbacks, options)
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  if result.is_a?(String) && !(interpolation_keys = options.keys - RESERVED_KEYS).empty?
         
     | 
| 
      
 59 
     | 
    
         
            +
                    mova.interpolator.call(result, options)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  else
         
     | 
| 
      
 61 
     | 
    
         
            +
                    result
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
                alias_method :t, :translate
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                def exists?(key, locale = config.locale)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  locale_with_fallbacks = fallbacks[locale]
         
     | 
| 
      
 68 
     | 
    
         
            +
                  result = mova.translator.get([key], locale_with_fallbacks, default: "")
         
     | 
| 
      
 69 
     | 
    
         
            +
                  Mova.presence(result)
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def reload!
         
     | 
| 
      
 73 
     | 
    
         
            +
                  super
         
     | 
| 
      
 74 
     | 
    
         
            +
                  mova.transfer_translations!
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Mova
         
     | 
| 
      
 2 
     | 
    
         
            +
              # `I18nBridge` name to explicitly avoid collision with root namespace, so we
         
     | 
| 
      
 3 
     | 
    
         
            +
              # don't need to type `::I18n`.
         
     | 
| 
      
 4 
     | 
    
         
            +
              module I18nBridge
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Translator
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def default(locales, keys, options)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    origin_locale = locales.first
         
     | 
| 
      
 8 
     | 
    
         
            +
                    origin_key = keys.first
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    if options[:raise]
         
     | 
| 
      
 11 
     | 
    
         
            +
                      raise I18n::MissingTranslationData.new(origin_locale, origin_key, options)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    if options[:throw]
         
     | 
| 
      
 15 
     | 
    
         
            +
                      throw :exception, I18n::MissingTranslation.new(origin_locale, origin_key, options)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    key_with_locale = Mova::Scope.join(origin_locale, origin_key)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    "missing translation: #{key_with_locale}"
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def put(translations)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    super
         
     | 
| 
      
 24 
     | 
    
         
            +
                    put_exact_translation(translations, "i18n.transliterate.rule")
         
     | 
| 
      
 25 
     | 
    
         
            +
                    put_exact_translation(translations, "number.format")
         
     | 
| 
      
 26 
     | 
    
         
            +
                    put_exact_translation(translations, "number.currency.format")
         
     | 
| 
      
 27 
     | 
    
         
            +
                    put_exact_translation(translations, "number.human.format")
         
     | 
| 
      
 28 
     | 
    
         
            +
                    put_exact_translation(translations, "number.human.decimal_units.units")
         
     | 
| 
      
 29 
     | 
    
         
            +
                    put_exact_translation(translations, "number.percentage.format")
         
     | 
| 
      
 30 
     | 
    
         
            +
                    put_exact_translation(translations, "number.precision.format")
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  # Stores exact value because {Mova::Translator#put} flattens hashes before writing
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # to the storage, while `I18n.transliterate` and Rails localization helpers rely on
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # ability of storing hashes as is.
         
     | 
| 
      
 36 
     | 
    
         
            +
                  def put_exact_translation(translations, key)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    scope_path = Mova::Scope.split(key).map &:to_sym
         
     | 
| 
      
 38 
     | 
    
         
            +
                    locales = translations.keys
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    locales.each do |locale|
         
     | 
| 
      
 41 
     | 
    
         
            +
                      full_path = [locale] + scope_path
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                      translation = full_path.inject(translations) do |memo, scope|
         
     | 
| 
      
 44 
     | 
    
         
            +
                        memo[scope] || {}
         
     | 
| 
      
 45 
     | 
    
         
            +
                      end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                      unless translation == {}
         
     | 
| 
      
 48 
     | 
    
         
            +
                        key_with_locale = Mova::Scope.join(full_path)
         
     | 
| 
      
 49 
     | 
    
         
            +
                        storage.write(key_with_locale, translation)
         
     | 
| 
      
 50 
     | 
    
         
            +
                      end
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                module Sprintf
         
     | 
| 
      
 56 
     | 
    
         
            +
                  def missing_placeholder(placeholder, values, string)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    raise I18n::MissingInterpolationArgument.new(placeholder, values, string)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              class I18nTranslator < Translator
         
     | 
| 
      
 63 
     | 
    
         
            +
                include I18nBridge::Translator
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              class I18nInterpolator < Interpolation::Sprintf
         
     | 
| 
      
 67 
     | 
    
         
            +
                include I18nBridge::Sprintf
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Mova
         
     | 
| 
      
 2 
     | 
    
         
            +
              module I18nConfig
         
     | 
| 
      
 3 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_writer :translator, :interpolator
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  # Transfer translations from `I18n::Backend::Simple`, since we can have enumerate all keys
         
     | 
| 
      
 7 
     | 
    
         
            +
                  # here. Other key-value storages should be passed to `I18n.mova.translator` directly.
         
     | 
| 
      
 8 
     | 
    
         
            +
                  #
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # @note Clears all current translations in `I18n.mova.translator.storage`. Use
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #   {Mova::Storage::Readonly} to protect certain storages if you have a chain of them.
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def transfer_translations!
         
     | 
| 
      
 12 
     | 
    
         
            +
                    # calling protected methods
         
     | 
| 
      
 13 
     | 
    
         
            +
                    I18n.backend.send(:init_translations) if I18n.backend.respond_to?(:init_translations, true)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    if I18n.backend.respond_to?(:translations, true)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      translations = I18n.backend.send(:translations)
         
     | 
| 
      
 16 
     | 
    
         
            +
                      translator.storage.clear
         
     | 
| 
      
 17 
     | 
    
         
            +
                      translator.put(translations)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def translator
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @translator ||= I18nTranslator.new
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def interpolator
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @interpolator ||= I18nInterpolator.new
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def pluralizer(locale)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    @pluralizers ||= {}
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @pluralizers[locale] ||= translator.storage.read("#{locale}.i18n.plural.rule") ||
         
     | 
| 
      
 32 
     | 
    
         
            +
                                             ->(count){ count == 1 ? :one : :other }
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
    
        data/mova-i18n.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 2 
     | 
    
         
            +
              spec.name          = "mova-i18n"
         
     | 
| 
      
 3 
     | 
    
         
            +
              spec.version       = "0.1.0"
         
     | 
| 
      
 4 
     | 
    
         
            +
              spec.authors       = ["Andrii Malyshko"]
         
     | 
| 
      
 5 
     | 
    
         
            +
              spec.email         = ["mail@nashbridges.me"]
         
     | 
| 
      
 6 
     | 
    
         
            +
              spec.summary       = "Seamless migration from I18n to Mova"
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.description   = spec.summary
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.homepage      = "https://github.com/mova-rb/mova-i18n"
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.license       = "MIT"
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              spec.files         = `git ls-files -z`.split("\x0")
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         
     | 
| 
      
 13 
     | 
    
         
            +
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.require_paths = ["lib"]
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              spec.add_development_dependency "bundler", "~> 1.6"
         
     | 
| 
      
 17 
     | 
    
         
            +
              spec.add_development_dependency "rake", "~> 10.0"
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              spec.add_dependency "i18n"
         
     | 
| 
      
 20 
     | 
    
         
            +
              spec.add_dependency "mova", "~> 0.1"
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     |