i18nema19 0.0.8
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.
- data/README.md +132 -0
- data/Rakefile +19 -0
- data/ext/i18nema/extconf.rb +5 -0
- data/ext/i18nema/i18nema.c +601 -0
- data/ext/i18nema/vendor/syck.h +453 -0
- data/ext/i18nema/vendor/uthash.h +940 -0
- data/lib/i18nema.rb +79 -0
- data/lib/i18nema/core_ext/hash.rb +8 -0
- data/lib/i18nema19.rb +1 -0
- data/test/helper.rb +5 -0
- data/test/i18nema_test.rb +97 -0
- metadata +90 -0
data/lib/i18nema.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'yaml' if RUBY_VERSION >= "2.0" # otherwise syck asplodes
|
2
|
+
require 'syck'
|
3
|
+
require 'i18n'
|
4
|
+
require File.dirname(__FILE__) + '/i18nema/core_ext/hash'
|
5
|
+
require File.dirname(__FILE__) + '/i18nema/i18nema'
|
6
|
+
|
7
|
+
module I18nema
|
8
|
+
module CoreMethods
|
9
|
+
RESERVED_KEY_MAP = Hash[I18n::RESERVED_KEYS.map{|k|[k,true]}]
|
10
|
+
|
11
|
+
def translate(locale, key, options = {})
|
12
|
+
raise I18n::InvalidLocale.new(locale) unless locale
|
13
|
+
entry = key && lookup(locale, key, options[:scope], options)
|
14
|
+
|
15
|
+
if options.empty?
|
16
|
+
entry = resolve(locale, key, entry, options)
|
17
|
+
else
|
18
|
+
count, default = options.values_at(:count, :default)
|
19
|
+
# significant speedup over Hash#except
|
20
|
+
values = options.reject { |key, value| RESERVED_KEY_MAP.key?(key) }
|
21
|
+
entry = entry.nil? && default ?
|
22
|
+
default(locale, key, default, options) : resolve(locale, key, entry, options)
|
23
|
+
end
|
24
|
+
|
25
|
+
throw(:exception, I18n::MissingTranslation.new(locale, key, options)) if entry.nil?
|
26
|
+
# no need to dup, since I18nema gives us a new string
|
27
|
+
|
28
|
+
entry = pluralize(locale, entry, count) if count
|
29
|
+
entry = interpolate(locale, entry, values) if values
|
30
|
+
entry
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Backend
|
35
|
+
include I18n::Backend::Base
|
36
|
+
include CoreMethods # defined in a module so that other modules (e.g. I18n::Backend::Fallbacks) can override them
|
37
|
+
|
38
|
+
def store_translations(locale, data, options = {})
|
39
|
+
# TODO: make this moar awesome
|
40
|
+
@initialized = true
|
41
|
+
load_yml_string({locale => data}.deep_stringify_keys.to_yaml)
|
42
|
+
end
|
43
|
+
|
44
|
+
def init_translations
|
45
|
+
load_translations
|
46
|
+
@initialized = true
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
def load_file(filename)
|
51
|
+
type = File.extname(filename).tr('.', '').downcase
|
52
|
+
raise I18n::UnknownFileType.new(type, filename) unless type == "yml"
|
53
|
+
load_yml(filename)
|
54
|
+
end
|
55
|
+
|
56
|
+
def load_yml(filename)
|
57
|
+
load_yml_string File.read(filename)
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialized?
|
61
|
+
@initialized
|
62
|
+
end
|
63
|
+
|
64
|
+
def lookup(locale, key, scope = [], options = {})
|
65
|
+
init_translations unless initialized?
|
66
|
+
keys = normalize_keys(locale, key, scope, options[:separator])
|
67
|
+
direct_lookup(*keys)
|
68
|
+
end
|
69
|
+
|
70
|
+
def normalize_keys(locale, key, scope, separator = nil)
|
71
|
+
separator ||= I18n.default_separator
|
72
|
+
|
73
|
+
keys = [locale.to_s]
|
74
|
+
keys.concat normalize_key(scope, separator) if scope && scope.size > 0
|
75
|
+
keys.concat normalize_key(key, separator)
|
76
|
+
keys
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/i18nema19.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'i18nema'
|
data/test/helper.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class I18nemaTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@data = {
|
7
|
+
foo: {
|
8
|
+
bar: "lol"
|
9
|
+
},
|
10
|
+
baz: %w{
|
11
|
+
asdf
|
12
|
+
qwerty
|
13
|
+
},
|
14
|
+
stuff: [
|
15
|
+
true,
|
16
|
+
true,
|
17
|
+
false,
|
18
|
+
nil,
|
19
|
+
1,
|
20
|
+
1.1,
|
21
|
+
:foo
|
22
|
+
]
|
23
|
+
}
|
24
|
+
@backend = I18nema::Backend.new
|
25
|
+
@backend.store_translations :en, @data
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_yaml_parity
|
29
|
+
assert_equal({en: @data}, @backend.direct_lookup)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_scoping
|
33
|
+
assert_equal({bar: "lol"},
|
34
|
+
@backend.direct_lookup("en", "foo"))
|
35
|
+
assert_equal "lol",
|
36
|
+
@backend.direct_lookup("en", "foo", "bar")
|
37
|
+
assert_equal nil,
|
38
|
+
@backend.direct_lookup("poo")
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_merging
|
42
|
+
@backend.store_translations :en, foo: "replaced!", wat: "added!"
|
43
|
+
assert_equal "replaced!",
|
44
|
+
@backend.direct_lookup("en", "foo")
|
45
|
+
assert_equal ["asdf", "qwerty"],
|
46
|
+
@backend.direct_lookup("en", "baz")
|
47
|
+
assert_equal "added!",
|
48
|
+
@backend.direct_lookup("en", "wat")
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_reload
|
52
|
+
@backend.reload!
|
53
|
+
assert_equal({}, @backend.direct_lookup)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_available_locales
|
57
|
+
@backend.store_translations :es, foo: "hola"
|
58
|
+
assert_equal ['en', 'es'],
|
59
|
+
@backend.available_locales.map(&:to_s).sort
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_invalid_yml
|
63
|
+
backend = I18nema::Backend.new
|
64
|
+
|
65
|
+
exception = assert_raise(I18nema::Backend::LoadError) {
|
66
|
+
backend.load_yml_string("string")
|
67
|
+
}
|
68
|
+
assert_equal("root yml node is not a hash", exception.message)
|
69
|
+
assert_equal({}, backend.direct_lookup)
|
70
|
+
|
71
|
+
exception = assert_raise(I18nema::Backend::LoadError) {
|
72
|
+
backend.load_yml_string("en:\n foo: \"lol\"\n\tbar: notabs!")
|
73
|
+
}
|
74
|
+
assert_match(/syntax error/, exception.message)
|
75
|
+
assert_equal({}, backend.direct_lookup)
|
76
|
+
|
77
|
+
exception = assert_raise(I18nema::Backend::LoadError) {
|
78
|
+
backend.load_yml_string("en:\n &a [*a]")
|
79
|
+
}
|
80
|
+
assert_match(/bad anchor `a'/, exception.message)
|
81
|
+
assert_equal({}, backend.direct_lookup)
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_normalize_key
|
85
|
+
backend = I18nema::Backend.new
|
86
|
+
assert_equal %w{asdf},
|
87
|
+
backend.normalize_key("asdf", ".")
|
88
|
+
assert_equal %w{asdf asdf},
|
89
|
+
backend.normalize_key("asdf.asdf", ".")
|
90
|
+
assert_equal %w{asdf.asdf},
|
91
|
+
backend.normalize_key("asdf.asdf", ",")
|
92
|
+
assert_equal %w{asdf asdf},
|
93
|
+
backend.normalize_key("asdf...asdf", ".")
|
94
|
+
assert_equal %w{asdf asdf asdf},
|
95
|
+
backend.normalize_key(%w{asdf asdf.asdf}, ".")
|
96
|
+
end
|
97
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: i18nema19
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.8
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jon Jensen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-01-16 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: i18n
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.5'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.5'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake-compiler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0.8'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.8'
|
46
|
+
description: drop-in replacement for I18n::Backend::Simple for faster lookups and
|
47
|
+
quicker gc runs. translations are stored outside of the ruby heap
|
48
|
+
email: jon@instructure.com
|
49
|
+
executables: []
|
50
|
+
extensions:
|
51
|
+
- ext/i18nema/extconf.rb
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- Rakefile
|
55
|
+
- README.md
|
56
|
+
- ext/i18nema/i18nema.c
|
57
|
+
- ext/i18nema/vendor/syck.h
|
58
|
+
- ext/i18nema/vendor/uthash.h
|
59
|
+
- ext/i18nema/extconf.rb
|
60
|
+
- lib/i18nema/core_ext/hash.rb
|
61
|
+
- lib/i18nema.rb
|
62
|
+
- lib/i18nema19.rb
|
63
|
+
- test/helper.rb
|
64
|
+
- test/i18nema_test.rb
|
65
|
+
homepage: http://github.com/instructure/i18nema
|
66
|
+
licenses: []
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.9.3
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.3.5
|
83
|
+
requirements: []
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 1.8.25
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: fast i18n backend that doesn't stop up the garbage collector
|
89
|
+
test_files: []
|
90
|
+
has_rdoc:
|