hyper-i18n 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1193cae43340ca57e63da28dda7ebbf6907c040e163dbcc68857ac69e514c242
4
+ data.tar.gz: a74f53c1a7b4033b176680579c19cea5efdc1fe22d93c24150eaa3c3c7a6a326
5
+ SHA512:
6
+ metadata.gz: 759752fc152695232d89ae9ccd40fbcd2cc3d1e8b2d0dbbdfb90933ad6d4faf7ce5ef4dcc94c106fd28ab630b5a925c7975f5838a58ef2b74b2cb98f496493bd
7
+ data.tar.gz: a14c1d40440f5a41bd193956740dde59fd539c48282399e94d7ea674f70cfba8686d3943f7736a8fbeca5d938349dc271a0cb509adae421fc1c117041ee98775
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.gem
data/.rubocop.yml ADDED
@@ -0,0 +1,141 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'db/schema.rb'
4
+ - 'db/seeds.rb'
5
+
6
+
7
+ ## Lint
8
+
9
+ Lint/AmbiguousBlockAssociation:
10
+ Enabled: false
11
+
12
+
13
+ ## Metrics
14
+
15
+ Metrics/AbcSize:
16
+ # The ABC size is a calculated magnitude, so this number can be a Fixnum or
17
+ # a Float.
18
+ Max: 20
19
+
20
+ Metrics/BlockLength:
21
+ Description: 'Avoid long blocks with many lines.'
22
+ Enabled: false
23
+
24
+ Metrics/LineLength:
25
+ Max: 100
26
+
27
+
28
+ ## Performance
29
+
30
+ Performance/RegexpMatch:
31
+ Enabled: false
32
+
33
+
34
+ ## Style
35
+
36
+ Style/BlockDelimiters:
37
+ EnforcedStyle: line_count_based
38
+ SupportedStyles:
39
+ # The `line_count_based` style enforces braces around single line blocks and
40
+ # do..end around multi-line blocks.
41
+ - line_count_based
42
+ # The `semantic` style enforces braces around functional blocks, where the
43
+ # primary purpose of the block is to return a value and do..end for
44
+ # procedural blocks, where the primary purpose of the block is its
45
+ # side-effects.
46
+ #
47
+ # This looks at the usage of a block's method to determine its type (e.g. is
48
+ # the result of a `map` assigned to a variable or passed to another
49
+ # method) but exceptions are permitted in the `ProceduralMethods`,
50
+ # `FunctionalMethods` and `IgnoredMethods` sections below.
51
+ - semantic
52
+ # The `braces_for_chaining` style enforces braces around single line blocks
53
+ # and do..end around multi-line blocks, except for multi-line blocks whose
54
+ # return value is being chained with another method (in which case braces
55
+ # are enforced).
56
+ - braces_for_chaining
57
+ ProceduralMethods:
58
+ # Methods that are known to be procedural in nature but look functional from
59
+ # their usage, e.g.
60
+ #
61
+ # time = Benchmark.realtime do
62
+ # foo.bar
63
+ # end
64
+ #
65
+ # Here, the return value of the block is discarded but the return value of
66
+ # `Benchmark.realtime` is used.
67
+ - benchmark
68
+ - bm
69
+ - bmbm
70
+ - create
71
+ - each_with_object
72
+ - measure
73
+ - new
74
+ - realtime
75
+ - tap
76
+ - with_object
77
+ FunctionalMethods:
78
+ # Methods that are known to be functional in nature but look procedural from
79
+ # their usage, e.g.
80
+ #
81
+ # let(:foo) { Foo.new }
82
+ #
83
+ # Here, the return value of `Foo.new` is used to define a `foo` helper but
84
+ # doesn't appear to be used from the return value of `let`.
85
+ - let
86
+ - let!
87
+ - subject
88
+ - watch
89
+ IgnoredMethods:
90
+ # Methods that can be either procedural or functional and cannot be
91
+ # categorised from their usage alone, e.g.
92
+ #
93
+ # foo = lambda do |x|
94
+ # puts "Hello, #{x}"
95
+ # end
96
+ #
97
+ # foo = lambda do |x|
98
+ # x * 100
99
+ # end
100
+ #
101
+ # Here, it is impossible to tell from the return value of `lambda` whether
102
+ # the inner block's return value is significant.
103
+ - lambda
104
+ - proc
105
+ - it
106
+
107
+ Style/Documentation:
108
+ Description: 'Document classes and non-namespace modules.'
109
+ Enabled: false
110
+ Exclude:
111
+ - 'spec/**/*'
112
+ - 'test/**/*'
113
+
114
+ # Multi-line method chaining should be done with trailing dots.
115
+ Style/DotPosition:
116
+ EnforcedStyle: leading
117
+ SupportedStyles:
118
+ - leading
119
+ - trailing
120
+
121
+ Style/DoubleNegation:
122
+ Description: 'Avoid the use of double negation (`!!`).'
123
+ Enabled: false
124
+
125
+ Style/FileName:
126
+ Enabled: false
127
+
128
+ Style/FrozenStringLiteralComment:
129
+ Enabled: false
130
+
131
+ Style/MultilineBlockChain:
132
+ Description: 'Avoid multi-line chains of blocks.'
133
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#single-line-blocks'
134
+ Enabled: false
135
+
136
+ Style/MutableConstant:
137
+ Description: 'Do not assign mutable objects to constants.'
138
+ Enabled: false
139
+
140
+ Style/SafeNavigation:
141
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,43 @@
1
+ dist: trusty
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.4
5
+ - 2.5.1
6
+ - ruby-head
7
+ env:
8
+ - DRIVER=google-chrome TZ=Europe/Berlin
9
+ matrix:
10
+ fast_finish: true
11
+ allow_failures:
12
+ - rvm: ruby-head
13
+ before_install:
14
+ - if [[ "$DRIVER" == "google-chrome" ]]; then wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -; fi
15
+ - if [[ "$DRIVER" == "google-chrome" ]]; then echo "deb http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list; fi
16
+ - if [[ "$DRIVER" == "google-chrome" ]]; then sudo apt-get update -qq && sudo apt-get install -qq -y google-chrome-stable; fi
17
+ - if [[ "$DRIVER" == "firefox" ]]; then sudo apt-get update -qq && sudo apt-get install -qq -y firefox; fi
18
+ - if [[ "$DRIVER" == "firefox" ]]; then wget -q https://github.com/mozilla/geckodriver/releases/download/v0.21.0/geckodriver-v0.21.0-linux64.tar.gz; fi
19
+ - if [[ "$DRIVER" == "firefox" ]]; then tar zxf geckodriver-v0.21.0-linux64.tar.gz; fi
20
+ - if [[ "$DRIVER" == "firefox" ]]; then sudo mv geckodriver /usr/local/bin/; fi
21
+ - gem install bundler
22
+ before_script:
23
+ - bundle install --jobs=3 --retry=3
24
+ - if [[ "$DRIVER" == "google-chrome" ]]; then chromedriver-update; fi
25
+ - if [[ "$DRIVER" == "google-chrome" ]]; then ls -lR ~/.chromedriver-helper/; fi
26
+ - if [[ "$DRIVER" == "google-chrome" ]]; then chromedriver --version; fi
27
+ - if [[ "$DRIVER" == "google-chrome" ]]; then google-chrome --version; fi
28
+ - if [[ "$DRIVER" == "google-chrome" ]]; then which chromedriver; fi
29
+ - if [[ "$DRIVER" == "google-chrome" ]]; then which google-chrome; fi
30
+ - if [[ "$DRIVER" == "firefox" ]]; then firefox --version; fi
31
+ - if [[ "$DRIVER" == "firefox" ]]; then geckodriver --version; fi
32
+ - if [[ "$DRIVER" == "firefox" ]]; then which firefox; fi
33
+ - if [[ "$DRIVER" == "firefox" ]]; then which geckodriver; fi
34
+ script: bundle exec rspec
35
+ deploy:
36
+ provider: rubygems
37
+ gem: hyper-i18n
38
+ gemspec: hyper-i18n.gemspec
39
+ api_key:
40
+ secure: R2JQCFGu2E2bb9vEk66UwJy6sr3B7wFvxrHqulh2t0gCG0TK/3C5kwcPoHgz/7kQAgisresL5GGENCqLHrFvn30MOmVvv32cBr+jiPKdl9c0P4xxkD4SkrStZrukFd3hGCXRLptSg/aWYMMfmYgv826BKgsYfRaYuQnzgjkYXyJ8wcaWiZIffNnwUoteKPLSqxKl1+LQvw8LklG/2rv0SkZmKyE99lef7XSKTbhhB+kgutqHnYoYcS+Zs90ev5EDPNad5t8LdE/f6H14u8YpI3ouOPWfT6dGERvRPVatggPZMmW2lMaY48slDY4Um2sHUhtbJcTqGpaG2UGoth2Nb6vqVTRp7NF5b0lMKEWiZj15ZG798ACYGin3Y6yBhBq9s/6HYmfyKDzspXdr9VwfW4w4vt6RkcQa59I5s9qAEZNeQOPW4WGgM+K5S++dOn3ThfZDjabyHyJtxXeAgswGQQ78ymUCSQIfna4psjEObX5HyRZiG/OuzpjCBF7xIoQmaeu3oZnFeVHfNI4WMw+x5GRrFeCDmAKlRxHf6kEPjKvj/PC0AGvQ00x5dj+uqATCL4jl8AxvbpbAmLri5o4bmVsgPfcwogXO4Darni4z23N+4ZDBT6N9IunsTGthR6Dk5+MyPiYyMB0dYY/yyS6Jt44jTXvOJkHg2dFYmIvRejQ=
41
+ on:
42
+ tags: true
43
+ rvm: 2.4.4
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at adamgeorge.31@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in hyper-i18n.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 adamcreekroad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # HyperI18n
2
+ [![Build Status](https://travis-ci.org/ruby-hyperloop/hyper-i18n.svg?branch=master)](https://travis-ci.org/ruby-hyperloop/hyper-i18n)
3
+ [![Gem Version](https://badge.fury.io/rb/hyper-i18n.svg)](https://badge.fury.io/rb/hyper-i18n)
4
+
5
+ ## HyperI18n gem
6
+
7
+ HyperI18n seamlessly brings Rails I18n into your Hyperloop application.
8
+
9
+
10
+ ## Documentation and Help
11
+
12
+ + Please see the [ruby-hyperloop.org](http://ruby-hyperloop.org/) website for documentation.
13
+ + Join the Hyperloop [gitter.io](https://gitter.im/ruby-hyperloop/chat) chat for help and support.
14
+
15
+
16
+ ## Installation and Setup
17
+
18
+ 1. Add `gem 'hyper-i18n', git: 'https://github.com/ruby-hyperloop/hyper-i18n.git'` to your `Gemfile`
19
+ 2. Install the Gem: `bundle install`
20
+ 3. Add `require 'hyper-i18n'` to your components manifest
21
+
22
+
23
+ ## Note!
24
+
25
+ This gem is in it's very early stages, and only a handful of the API has been implemented.
26
+ Contributions are very welcome!
27
+
28
+ ### Usage
29
+
30
+ Hyper-I18n brings in the standard ActiveSupport API.
31
+
32
+
33
+ #### ActiveRecord Models
34
+
35
+ The methods `Model.model_name.human` and `Model.human_attribute_name` are available:
36
+
37
+ ```yaml
38
+ # config/locales/models/en.yml
39
+ en:
40
+ activerecord:
41
+ models:
42
+ user: 'Customer'
43
+ attributes:
44
+ name: 'Name'
45
+ ```
46
+ ```ruby
47
+ User.model_name.human
48
+ # 'Customer'
49
+
50
+ User.human_attribute_name(:name)
51
+ # 'Name'
52
+ ```
53
+
54
+ #### Views
55
+
56
+ Hyper-I18n makes available the method `t` to components, just as ActiveSupport does for views.
57
+ It also implements the same lazy-loading pattern,
58
+ so if you name space your locale file the same as your components, it will just work:
59
+
60
+ ```yaml
61
+ # config/locales/views/en.yml
62
+ en:
63
+ users:
64
+ show:
65
+ title: 'Customer View'
66
+ ```
67
+ ```ruby
68
+ module Users
69
+ class Show < Hyperloop::Component
70
+ render do
71
+ H1 { t(:title) }
72
+ end
73
+ end
74
+ end
75
+
76
+ # <h1>Customer View</h1>
77
+ ```
78
+
79
+ ### Server Rendering
80
+
81
+ HyperI18n is fully compatible with server rendering!
82
+ All translations are also sent to the client, so as to bypass fetching/rendering again on the client.
83
+
84
+ ## Contributing
85
+
86
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby-hyperloop/hyper-i18n.
87
+ This project is intended to be a safe, welcoming space for collaboration,
88
+ and contributors are expected to adhere to the [Code of Conduct](https://github.com/ruby-hyperloop/hyper-operation/blob/master/CODE_OF_CONDUCT.md) code of conduct.
89
+
90
+ ## License
91
+
92
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "hyper/i18n"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'hyper-i18n/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'hyper-i18n'
9
+ spec.version = HyperI18n::VERSION
10
+ spec.authors = ['adamcreekroad']
11
+ spec.email = ['adamgeorge.31@gmail.com']
12
+
13
+ spec.summary = 'HyperI18n seamlessly brings Rails I18n into your Hyperloop application.'
14
+ spec.homepage = 'https://www.github.com/ruby-hyperloop/hyper-i18n'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split("\n")
18
+ spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'i18n'
23
+ spec.add_dependency 'hyper-component'
24
+ spec.add_dependency 'hyper-operation'
25
+ spec.add_dependency 'hyper-store'
26
+
27
+ spec.add_development_dependency 'bundler', '~> 1.15'
28
+ spec.add_development_dependency 'chromedriver-helper'
29
+ spec.add_development_dependency 'pry'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'rspec'
32
+ spec.add_development_dependency 'rubocop'
33
+ end
@@ -0,0 +1,20 @@
1
+ # TODO: This should really be in hyper-mesh
2
+ module ActiveModel
3
+ class Name
4
+ attr_reader :name, :klass, :i18n_key
5
+
6
+ def initialize(klass)
7
+ @name = klass.name
8
+ @klass = klass
9
+ @i18n_key = :"#{@name.underscore}"
10
+ end
11
+
12
+ def to_s
13
+ @name
14
+ end
15
+
16
+ def human
17
+ HyperI18n::I18n.t("activerecord.models.#{i18n_key}")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module ActiveRecord
2
+ module ClassMethods
3
+ # TODO: This should really be in hyper-mesh
4
+ def model_name
5
+ @model_name ||= ActiveModel::Name.new(self)
6
+ end
7
+
8
+ def human_attribute_name(attribute, opts = {})
9
+ attribute = "activerecord.attributes.#{model_name.i18n_key}.#{attribute}"
10
+
11
+ HyperI18n::I18n.t(attribute, opts)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ module HyperI18n
2
+ module HelperMethods
3
+ def formatted_date_or_time(date_or_time)
4
+ # If the date_or_time parameter is a String, we must parse it to the correct format.
5
+
6
+ return date_or_time unless date_or_time.is_a?(String)
7
+
8
+ if date_or_time =~ /^\d+\W\d+\W\d+T?\s?\d+:\d+:\d+/
9
+ Time.parse(date_or_time)
10
+ else
11
+ Date.parse(date_or_time)
12
+ end
13
+ end
14
+
15
+ def formatted_format(format)
16
+ # If a string is passed in it will use that as the pattern for formatting, ex:
17
+ #
18
+ # I18n.l(Time.now, format: "%b %d, %Y")
19
+ # => "Aug 20, 2017"
20
+ #
21
+ # If a symbol is passed in it will find that definition from the locales.
22
+
23
+ format =~ /%/ ? format : :"#{format}"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ module Hyperloop
2
+ class Component
3
+ module Mixin
4
+ def t(attribute, opts = {})
5
+ namespace = self.class.name.underscore.tr('/', '.')
6
+
7
+ HyperI18n::I18n.t("#{namespace}.#{attribute}", opts)
8
+ end
9
+
10
+ def l(time, format = :default, opts = {})
11
+ HyperI18n::I18n.l(time, format, opts)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,90 @@
1
+ module HyperI18n
2
+ class I18n
3
+ extend HelperMethods
4
+ include React::IsomorphicHelpers
5
+
6
+ before_first_mount do
7
+ if RUBY_ENGINE != 'opal'
8
+ @server_data_cache = { t: {}, l: {} }
9
+ else
10
+ unless on_opal_server? || no_initial_data?
11
+ I18nStore.mutate.translations(JSON.from_object(`window.HyperI18nInitialData.t`))
12
+ I18nStore.mutate.localizations(JSON.from_object(`window.HyperI18nInitialData.l`))
13
+ end
14
+ end
15
+ end
16
+
17
+ isomorphic_method(:t) do |f, attribute, opts = {}|
18
+ f.when_on_client do
19
+ return I18nStore.translations[attribute] if I18nStore.translations[attribute]
20
+
21
+ Translate
22
+ .run(attribute: attribute, opts: opts)
23
+ .then do |translation|
24
+ I18nStore.translations[attribute] = translation
25
+ I18nStore.mutate.translations(I18nStore.translations)
26
+ end
27
+
28
+ opts[:default] || ''
29
+ end
30
+
31
+ f.when_on_server do
32
+ @server_data_cache[:t][attribute] = ::I18n.t(attribute, opts.with_indifferent_access)
33
+ end
34
+ end
35
+
36
+ isomorphic_method(:l) do |f, date_or_time, format = :default, opts = {}|
37
+ format = formatted_format(format)
38
+ date_or_time = formatted_date_or_time(date_or_time)
39
+
40
+ f.when_on_client do
41
+ if I18nStore.localizations[date_or_time.to_s] &&
42
+ I18nStore.localizations[date_or_time.to_s][format]
43
+ return I18nStore.localizations[date_or_time.to_s][format]
44
+ end
45
+
46
+ Localize
47
+ .run(date_or_time: date_or_time, format: format, opts: {})
48
+ .then do |localization|
49
+ I18nStore.localizations[date_or_time.to_s] ||= {}
50
+ I18nStore.localizations[date_or_time.to_s][format] = localization
51
+
52
+ I18nStore.mutate.localizations(I18nStore.localizations)
53
+ end
54
+
55
+ opts[:default] || ''
56
+ end
57
+
58
+ f.when_on_server do
59
+ @server_data_cache[:l][date_or_time.to_s] ||= {}
60
+
61
+ @server_data_cache[:l][date_or_time.to_s][format] =
62
+ ::I18n.l(date_or_time, opts.with_indifferent_access.merge(format: format))
63
+ end
64
+ end
65
+
66
+ if RUBY_ENGINE != 'opal'
67
+ prerender_footer do
68
+ "<script type=\"text/javascript\">\n"\
69
+ "if (typeof window.HyperI18nInitialData === 'undefined') {\n"\
70
+ " window.HyperI18nInitialData = #{initial_data_json};\n"\
71
+ "}\n"\
72
+ "</script>\n"
73
+ end
74
+ end
75
+
76
+ class << self
77
+ def no_initial_data?
78
+ `typeof window.HyperI18nInitialData === 'undefined'`
79
+ end
80
+
81
+ def initial_data_json
82
+ if @server_data_cache
83
+ @server_data_cache.as_json.to_json
84
+ else
85
+ { t: {}, l: {} }.to_json
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,23 @@
1
+ module HyperI18n
2
+ class Localize < Hyperloop::ServerOp
3
+ include HelperMethods
4
+
5
+ param :acting_user, nils: true
6
+ param :date_or_time
7
+ param :format
8
+ param :opts
9
+ param :localization, default: nil
10
+
11
+ def date_or_time
12
+ @date_or_time ||= formatted_date_or_time(params.date_or_time)
13
+ end
14
+
15
+ def opts
16
+ @opts ||= params.opts.with_indifferent_access.merge(format: formatted_format(params.format))
17
+ end
18
+
19
+ step do
20
+ params.localization = ::I18n.l(date_or_time, opts)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module HyperI18n
2
+ class Translate < Hyperloop::ServerOp
3
+ param :acting_user, nils: true
4
+ param :attribute
5
+ param :opts
6
+ param :translation, default: nil
7
+
8
+ def opts
9
+ params.opts.with_indifferent_access
10
+ end
11
+
12
+ step do
13
+ params.translation = ::I18n.t(params.attribute, opts)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ module HyperI18n
2
+ class I18nStore < Hyperloop::Store
3
+ state translations: {}, scope: :class, reader: true
4
+ state localizations: {}, scope: :class, reader: true
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module HyperI18n
2
+ VERSION = '0.1.1'
3
+ end
data/lib/hyper-i18n.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'hyperloop-config'
2
+ Hyperloop.import 'hyper-i18n'
3
+
4
+ require 'hyper-component'
5
+ require 'hyper-operation'
6
+
7
+ require 'hyper-i18n/helper_methods'
8
+ require 'hyper-i18n/operations/localize'
9
+ require 'hyper-i18n/operations/translate'
10
+ require 'hyper-i18n/i18n'
11
+
12
+ if RUBY_ENGINE == 'opal'
13
+ require 'hyper-store'
14
+
15
+ require 'hyper-i18n/active_model/name'
16
+ require 'hyper-i18n/active_record/class_methods'
17
+ require 'hyper-i18n/hyperloop/component/mixin'
18
+
19
+ require 'hyper-i18n/stores/i18n_store'
20
+ else
21
+ require 'opal'
22
+
23
+ require 'hyper-i18n/version'
24
+
25
+ Opal.append_path File.expand_path('../', __FILE__).untaint
26
+ end
@@ -0,0 +1,39 @@
1
+ ENV["RAILS_ENV"] ||= 'test'
2
+
3
+ require 'rspec'
4
+ require 'pry'
5
+
6
+ RSpec.configure do |config|
7
+ config.color = true
8
+ config.fail_fast = ENV['FAIL_FAST'] || false
9
+ config.fixture_path = File.join(File.expand_path(File.dirname(__FILE__)), "fixtures")
10
+ config.infer_spec_type_from_file_location!
11
+ config.mock_with :rspec
12
+ config.raise_errors_for_deprecations!
13
+
14
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
15
+ # examples within a transaction, comment the following line or assign false
16
+ # instead of true.
17
+ config.use_transactional_fixtures = true
18
+
19
+ config.filter_run_including focus: true
20
+ config.filter_run_excluding opal: true
21
+ config.run_all_when_everything_filtered = true
22
+
23
+ # Fail tests on JavaScript errors in Chrome Headless
24
+ class JavaScriptError < StandardError; end
25
+
26
+ config.after(:each, js: true) do |spec|
27
+ logs = page.driver.browser.manage.logs.get(:browser)
28
+ errors = logs.select { |e| e.level == "SEVERE" && e.message.present? }
29
+ .map { |m| m.message.gsub(/\\n/, "\n") }.to_a
30
+ if client_options[:deprecation_warnings] == :on
31
+ warnings = logs.select { |e| e.level == "WARNING" && e.message.present? }
32
+ .map { |m| m.message.gsub(/\\n/, "\n") }.to_a
33
+ puts "\033[0;33;1m\nJavascript client console warnings:\n\n" + warnings.join("\n\n") + "\033[0;30;21m" if warnings.present?
34
+ end
35
+ unless client_options[:raise_on_js_errors] == :off
36
+ raise JavaScriptError, errors.join("\n\n") if errors.present?
37
+ end
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,208 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hyper-i18n
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - adamcreekroad
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-08-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: i18n
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: hyper-component
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: hyper-operation
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: hyper-store
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.15'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.15'
83
+ - !ruby/object:Gem::Dependency
84
+ name: chromedriver-helper
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '10.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '10.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description:
154
+ email:
155
+ - adamgeorge.31@gmail.com
156
+ executables:
157
+ - console
158
+ - setup
159
+ extensions: []
160
+ extra_rdoc_files: []
161
+ files:
162
+ - ".gitignore"
163
+ - ".rubocop.yml"
164
+ - ".travis.yml"
165
+ - CODE_OF_CONDUCT.md
166
+ - Gemfile
167
+ - LICENSE.txt
168
+ - README.md
169
+ - Rakefile
170
+ - bin/console
171
+ - bin/setup
172
+ - hyper-i18n.gemspec
173
+ - lib/hyper-i18n.rb
174
+ - lib/hyper-i18n/active_model/name.rb
175
+ - lib/hyper-i18n/active_record/class_methods.rb
176
+ - lib/hyper-i18n/helper_methods.rb
177
+ - lib/hyper-i18n/hyperloop/component/mixin.rb
178
+ - lib/hyper-i18n/i18n.rb
179
+ - lib/hyper-i18n/operations/localize.rb
180
+ - lib/hyper-i18n/operations/translate.rb
181
+ - lib/hyper-i18n/stores/i18n_store.rb
182
+ - lib/hyper-i18n/version.rb
183
+ - spec/spec_helper.rb
184
+ homepage: https://www.github.com/ruby-hyperloop/hyper-i18n
185
+ licenses:
186
+ - MIT
187
+ metadata: {}
188
+ post_install_message:
189
+ rdoc_options: []
190
+ require_paths:
191
+ - lib
192
+ required_ruby_version: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ required_rubygems_version: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ requirements: []
203
+ rubyforge_project:
204
+ rubygems_version: 2.7.6
205
+ signing_key:
206
+ specification_version: 4
207
+ summary: HyperI18n seamlessly brings Rails I18n into your Hyperloop application.
208
+ test_files: []