fast_gettext 1.8.0 → 2.0.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 +4 -4
- data/CHANGELOG +4 -3
- data/Readme.md +140 -49
- data/lib/fast_gettext.rb +16 -16
- data/lib/fast_gettext/cache.rb +4 -2
- data/lib/fast_gettext/mo_file.rb +28 -19
- data/lib/fast_gettext/po_file.rb +17 -14
- data/lib/fast_gettext/storage.rb +38 -32
- data/lib/fast_gettext/translation.rb +79 -113
- data/lib/fast_gettext/translation_repository.rb +5 -5
- data/lib/fast_gettext/translation_repository/base.rb +9 -6
- data/lib/fast_gettext/translation_repository/chain.rb +11 -5
- data/lib/fast_gettext/translation_repository/db.rb +11 -12
- data/lib/fast_gettext/translation_repository/db_models/translation_key.rb +11 -8
- data/lib/fast_gettext/translation_repository/db_models/translation_text.rb +4 -2
- data/lib/fast_gettext/translation_repository/logger.rb +4 -2
- data/lib/fast_gettext/translation_repository/merge.rb +9 -4
- data/lib/fast_gettext/translation_repository/mo.rb +8 -4
- data/lib/fast_gettext/translation_repository/po.rb +5 -2
- data/lib/fast_gettext/translation_repository/yaml.rb +10 -4
- data/lib/fast_gettext/version.rb +3 -1
- metadata +45 -3
@@ -1,16 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module FastGettext
|
2
4
|
# Responsibility:
|
3
5
|
# - decide which repository to choose from given input
|
4
6
|
module TranslationRepository
|
5
|
-
|
6
|
-
|
7
|
-
def build(name, options)
|
7
|
+
def self.build(name, options)
|
8
8
|
type = options[:type] || :mo
|
9
9
|
class_name = type.to_s.split('_').map(&:capitalize).join
|
10
|
-
unless FastGettext::TranslationRepository.constants.map
|
10
|
+
unless FastGettext::TranslationRepository.constants.map(&:to_s).include?(class_name)
|
11
11
|
require "fast_gettext/translation_repository/#{type}"
|
12
12
|
end
|
13
|
-
|
13
|
+
const_get(class_name).new(name, options)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -1,13 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module FastGettext
|
2
4
|
module TranslationRepository
|
3
5
|
# Responsibility:
|
4
6
|
# - base for all repositories
|
5
7
|
# - fallback as empty repository, that cannot translate anything but does not crash
|
6
8
|
class Base
|
7
|
-
|
8
9
|
attr_reader :name, :options
|
9
10
|
|
10
|
-
def initialize(name,options={})
|
11
|
+
def initialize(name, options = {})
|
11
12
|
@name = name
|
12
13
|
@options = options
|
13
14
|
end
|
@@ -38,17 +39,19 @@ module FastGettext
|
|
38
39
|
MoFile.empty
|
39
40
|
end
|
40
41
|
|
41
|
-
def find_files_in_locale_folders(relative_file_path,path)
|
42
|
+
def find_files_in_locale_folders(relative_file_path, path)
|
42
43
|
path ||= "locale"
|
43
44
|
raise "path #{path} could not be found!" unless File.exist?(path)
|
44
45
|
|
45
46
|
@files = {}
|
46
|
-
Dir[File.join(path,'*')].each do |locale_folder|
|
47
|
+
Dir[File.join(path, '*')].each do |locale_folder|
|
47
48
|
next unless File.basename(locale_folder) =~ LOCALE_REX
|
48
|
-
|
49
|
+
|
50
|
+
file = File.join(locale_folder, relative_file_path).untaint
|
49
51
|
next unless File.exist? file
|
52
|
+
|
50
53
|
locale = File.basename(locale_folder)
|
51
|
-
@files[locale] = yield(locale,file)
|
54
|
+
@files[locale] = yield(locale, file)
|
52
55
|
end
|
53
56
|
end
|
54
57
|
end
|
@@ -1,32 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fast_gettext/translation_repository/base'
|
2
4
|
|
3
5
|
module FastGettext
|
4
6
|
module TranslationRepository
|
5
7
|
# Responsibility:
|
6
8
|
# - delegate calls to members of the chain in turn
|
7
|
-
#TODO cache should be expired after a repo was added
|
9
|
+
# TODO cache should be expired after a repo was added
|
8
10
|
class Chain < Base
|
9
11
|
attr_accessor :chain
|
10
12
|
|
11
|
-
def initialize(name,options={})
|
13
|
+
def initialize(name, options = {})
|
12
14
|
super
|
13
15
|
self.chain = options[:chain]
|
14
16
|
end
|
15
17
|
|
16
18
|
def available_locales
|
17
|
-
chain.map
|
19
|
+
chain.map(&:available_locales).flatten.uniq
|
18
20
|
end
|
19
21
|
|
20
22
|
def pluralisation_rule
|
21
23
|
chain.each do |c|
|
22
|
-
result = c.pluralisation_rule
|
24
|
+
if result = c.pluralisation_rule
|
25
|
+
return result
|
26
|
+
end
|
23
27
|
end
|
24
28
|
nil
|
25
29
|
end
|
26
30
|
|
27
31
|
def [](key)
|
28
32
|
chain.each do |c|
|
29
|
-
result = c[key]
|
33
|
+
if result = c[key]
|
34
|
+
return result
|
35
|
+
end
|
30
36
|
end
|
31
37
|
nil
|
32
38
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record'
|
2
4
|
module FastGettext
|
3
5
|
module TranslationRepository
|
@@ -11,13 +13,14 @@ module FastGettext
|
|
11
13
|
# key: find_by_key, translations
|
12
14
|
# translation: text, locale
|
13
15
|
class Db
|
14
|
-
def initialize(
|
16
|
+
def initialize(_name, options = {})
|
15
17
|
@model = options[:model]
|
16
18
|
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
@separator = '||||' # string that separates multiple plurals
|
21
|
+
class << self
|
22
|
+
attr_accessor :separator
|
23
|
+
end
|
21
24
|
|
22
25
|
def available_locales
|
23
26
|
if @model.respond_to? :available_locales
|
@@ -28,11 +31,7 @@ module FastGettext
|
|
28
31
|
end
|
29
32
|
|
30
33
|
def pluralisation_rule
|
31
|
-
if @model.respond_to? :pluralsation_rule
|
32
|
-
@model.pluralsation_rule
|
33
|
-
else
|
34
|
-
nil
|
35
|
-
end
|
34
|
+
@model.pluralsation_rule if @model.respond_to? :pluralsation_rule
|
36
35
|
end
|
37
36
|
|
38
37
|
def [](key)
|
@@ -40,8 +39,8 @@ module FastGettext
|
|
40
39
|
end
|
41
40
|
|
42
41
|
def plural(*args)
|
43
|
-
if translation = @model.translation(args*self.class.
|
44
|
-
translation.to_s.split(self.class.
|
42
|
+
if translation = @model.translation(args * self.class.separator, FastGettext.locale)
|
43
|
+
translation.to_s.split(self.class.separator)
|
45
44
|
else
|
46
45
|
[]
|
47
46
|
end
|
@@ -56,7 +55,7 @@ module FastGettext
|
|
56
55
|
require "#{folder}/translation_key"
|
57
56
|
require "#{folder}/translation_text"
|
58
57
|
Module.new do
|
59
|
-
def self.included(
|
58
|
+
def self.included(_base)
|
60
59
|
puts "you no longer need to include the result of require_models"
|
61
60
|
end
|
62
61
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class TranslationKey < ActiveRecord::Base
|
2
|
-
has_many :translations, :
|
4
|
+
has_many :translations, class_name: 'TranslationText', dependent: :destroy
|
3
5
|
|
4
|
-
accepts_nested_attributes_for :translations, :
|
6
|
+
accepts_nested_attributes_for :translations, allow_destroy: true
|
5
7
|
|
6
8
|
validates_uniqueness_of :key
|
7
9
|
validates_presence_of :key
|
@@ -13,25 +15,26 @@ class TranslationKey < ActiveRecord::Base
|
|
13
15
|
def self.translation(key, locale)
|
14
16
|
return unless translation_key = find_by_key(newline_normalize(key))
|
15
17
|
return unless translation_text = translation_key.translations.find_by_locale(locale)
|
18
|
+
|
16
19
|
translation_text.text
|
17
20
|
end
|
18
21
|
|
19
22
|
def self.available_locales
|
20
|
-
|
23
|
+
@available_locales ||= begin
|
21
24
|
if ActiveRecord::VERSION::MAJOR >= 3
|
22
25
|
TranslationText.group(:locale).count
|
23
26
|
else
|
24
|
-
TranslationText.count(:
|
27
|
+
TranslationText.count(group: :locale)
|
25
28
|
end.keys.sort
|
26
29
|
end
|
27
30
|
end
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
def self.newline_normalize(s)
|
32
|
-
s.to_s.gsub("\r\n", "\n")
|
32
|
+
def self.newline_normalize(string)
|
33
|
+
string.to_s.gsub("\r\n", "\n")
|
33
34
|
end
|
34
35
|
|
36
|
+
protected
|
37
|
+
|
35
38
|
def normalize_newlines
|
36
39
|
self.key = self.class.newline_normalize(key)
|
37
40
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class TranslationText < ActiveRecord::Base
|
2
|
-
belongs_to :translation_key, :
|
4
|
+
belongs_to :translation_key, class_name: 'TranslationKey'
|
3
5
|
validates_presence_of :locale
|
4
|
-
validates_uniqueness_of :locale, :
|
6
|
+
validates_uniqueness_of :locale, scope: :translation_key_id
|
5
7
|
attr_accessible :text, :locale, :translation_key, :translation_key_id if ActiveRecord::VERSION::MAJOR == 3 || defined?(ProtectedAttributes)
|
6
8
|
after_update :expire_cache
|
7
9
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fast_gettext/translation_repository/base'
|
2
4
|
|
3
5
|
module FastGettext
|
@@ -8,7 +10,7 @@ module FastGettext
|
|
8
10
|
class Logger < Base
|
9
11
|
attr_accessor :callback
|
10
12
|
|
11
|
-
def initialize(name,options={})
|
13
|
+
def initialize(name, options = {})
|
12
14
|
super
|
13
15
|
self.callback = options[:callback]
|
14
16
|
end
|
@@ -24,4 +26,4 @@ module FastGettext
|
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
27
|
-
end
|
29
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fast_gettext/translation_repository/po'
|
2
4
|
|
3
5
|
module FastGettext
|
@@ -7,7 +9,7 @@ module FastGettext
|
|
7
9
|
# - can be used instead of searching for translations in multiple domains
|
8
10
|
# - requires reload when current locale is changed
|
9
11
|
class Merge < Base
|
10
|
-
def initialize(name, options={})
|
12
|
+
def initialize(name, options = {})
|
11
13
|
clear
|
12
14
|
super(name, options)
|
13
15
|
options.fetch(:chain, []).each do |repo|
|
@@ -21,7 +23,9 @@ module FastGettext
|
|
21
23
|
|
22
24
|
def pluralisation_rule
|
23
25
|
@repositories.each do |r|
|
24
|
-
result = r.pluralisation_rule
|
26
|
+
if result = r.pluralisation_rule
|
27
|
+
return result
|
28
|
+
end
|
25
29
|
end
|
26
30
|
nil
|
27
31
|
end
|
@@ -45,6 +49,7 @@ module FastGettext
|
|
45
49
|
|
46
50
|
def add_repo(repo)
|
47
51
|
raise "Unsupported repository" unless repo_supported?(repo)
|
52
|
+
|
48
53
|
@repositories << repo
|
49
54
|
load_repo(repo)
|
50
55
|
true
|
@@ -65,8 +70,8 @@ module FastGettext
|
|
65
70
|
repo.respond_to?(:all_translations)
|
66
71
|
end
|
67
72
|
|
68
|
-
def load_repo(
|
69
|
-
@data =
|
73
|
+
def load_repo(repo)
|
74
|
+
@data = repo.all_translations.merge(@data)
|
70
75
|
end
|
71
76
|
end
|
72
77
|
end
|
@@ -1,11 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fast_gettext/translation_repository/base'
|
2
4
|
module FastGettext
|
3
5
|
module TranslationRepository
|
4
|
-
|
6
|
+
# Responsibility:
|
5
7
|
# - find and store mo files
|
6
8
|
# - provide access to translations in mo files
|
7
9
|
class Mo < Base
|
8
|
-
|
10
|
+
CONTEXT_SEPARATOR = "\u0004"
|
11
|
+
|
12
|
+
def initialize(name, options = {})
|
9
13
|
super
|
10
14
|
@eager_load = options.fetch(:eager_load, false)
|
11
15
|
reload
|
@@ -30,9 +34,9 @@ module FastGettext
|
|
30
34
|
|
31
35
|
protected
|
32
36
|
|
33
|
-
def find_and_store_files(name,options)
|
37
|
+
def find_and_store_files(name, options)
|
34
38
|
# parse all .mo files with the right name, that sit in locale/LC_MESSAGES folders
|
35
|
-
find_files_in_locale_folders(File.join('LC_MESSAGES',"#{name}.mo"), options[:path]) do |
|
39
|
+
find_files_in_locale_folders(File.join('LC_MESSAGES', "#{name}.mo"), options[:path]) do |_locale, file|
|
36
40
|
MoFile.new(file, eager_load: @eager_load)
|
37
41
|
end
|
38
42
|
end
|
@@ -1,15 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fast_gettext/translation_repository/base'
|
2
4
|
require 'fast_gettext/translation_repository/mo'
|
3
5
|
module FastGettext
|
4
6
|
module TranslationRepository
|
5
|
-
|
7
|
+
# Responsibility:
|
6
8
|
# - find and store po files
|
7
9
|
# - provide access to translations in po files
|
8
10
|
class Po < Mo
|
9
11
|
protected
|
12
|
+
|
10
13
|
def find_and_store_files(name, options)
|
11
14
|
require 'fast_gettext/po_file'
|
12
|
-
find_files_in_locale_folders("#{name}.po", options[:path]) do |
|
15
|
+
find_files_in_locale_folders("#{name}.po", options[:path]) do |_locale, file|
|
13
16
|
PoFile.new(file, options)
|
14
17
|
end
|
15
18
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fast_gettext/translation_repository/base'
|
2
4
|
require 'yaml'
|
3
5
|
|
@@ -7,7 +9,7 @@ module FastGettext
|
|
7
9
|
# - find and store yaml files
|
8
10
|
# - provide access to translations in yaml files
|
9
11
|
class Yaml < Base
|
10
|
-
def initialize(name,options={})
|
12
|
+
def initialize(name, options = {})
|
11
13
|
super
|
12
14
|
reload
|
13
15
|
end
|
@@ -23,7 +25,11 @@ module FastGettext
|
|
23
25
|
end
|
24
26
|
|
25
27
|
def pluralisation_rule
|
26
|
-
|
28
|
+
return unless rule = self['pluralisation_rule']
|
29
|
+
|
30
|
+
->(n) do # rubocop:disable Lint/UnusedBlockArgument n can be used from pluralisation_rule code
|
31
|
+
eval(rule) # rubocop:disable Security/Eval TODO remove eval
|
32
|
+
end
|
27
33
|
end
|
28
34
|
|
29
35
|
def reload
|
@@ -64,7 +70,7 @@ module FastGettext
|
|
64
70
|
|
65
71
|
def add_yaml_key(result, prefix, hash)
|
66
72
|
hash.each_pair do |key, value|
|
67
|
-
if value.
|
73
|
+
if value.is_a?(Hash)
|
68
74
|
add_yaml_key(result, yaml_dot_notation(prefix, key), value)
|
69
75
|
else
|
70
76
|
result[yaml_dot_notation(prefix, key)] = value
|
@@ -73,7 +79,7 @@ module FastGettext
|
|
73
79
|
result
|
74
80
|
end
|
75
81
|
|
76
|
-
def yaml_dot_notation(a,b)
|
82
|
+
def yaml_dot_notation(a, b) # rubocop:disable Naming/UncommunicativeMethodParamName
|
77
83
|
a ? "#{a}.#{b}" : b
|
78
84
|
end
|
79
85
|
end
|
data/lib/fast_gettext/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fast_gettext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -108,6 +108,48 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: single_cov
|
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: forking_test_runner
|
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'
|
111
153
|
description:
|
112
154
|
email: michael@grosser.it
|
113
155
|
executables: []
|
@@ -153,7 +195,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
195
|
requirements:
|
154
196
|
- - ">="
|
155
197
|
- !ruby/object:Gem::Version
|
156
|
-
version: 2.
|
198
|
+
version: 2.3.0
|
157
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
200
|
requirements:
|
159
201
|
- - ">="
|