Module: Mova::Scope
Overview
In YAML (and other storages that map to a hash) you can’t store a value for a nesting level itself.
errors: !can't have translation here
blank: Please enter a value
Other key-value storages usually don’t have such limitation, however, it’s better to not introduce incompatibles in this area.
Translation keys are usually organized in a tree, where each nesting level corresponds to a specific part of your application. Such hierarchical organization allows to reuse the keys and keep their names relatively short.
Full path to a key forms a scope. Think of a scope as a namespace.
# here we have an example YAML file with "blank" keys within different scopes
activemodel:
errors:
blank: Can't be blank
message:
blank: Please provide a message
Since Mova is designed to work with any key-value storage, we need to store a key with its own full scope and a locale. We use dot-separated strings as it’s a common format in Ruby community.
"en.activemodel.errors.blank"
"en.activemodel.errors.message.blank"
Constant Summary collapse
- SEPARATOR =
".".freeze
Instance Method Summary collapse
-
#cross_join(locales, keys) ⇒ Array<String>
Combines each locale with all keys.
-
#flatten(translations, current_scope = nil) ⇒ Hash{String => String}
Recurrently flattens hash by converting its keys to fully scoped ones.
-
#join(*parts) ⇒ String
Makes a new scope from given parts.
-
#split(scope) ⇒ Array<String>
Split a scope into parts.
Instance Method Details
#cross_join(locales, keys) ⇒ Array<String>
Combines each locale with all keys.
88 89 90 91 92 |
# File 'lib/mova/scope.rb', line 88 def cross_join(locales, keys) locales.map do |locale| keys.map { |key| join(locale, key) } end.flatten end |
#flatten(translations, current_scope = nil) ⇒ Hash{String => String}
Recurrently flattens hash by converting its keys to fully scoped ones.
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/mova/scope.rb', line 68 def flatten(translations, current_scope = nil) translations.each_with_object({}) do |(key, value), memo| scope = current_scope ? join(current_scope, key) : key.to_s if value.is_a?(Hash) memo.merge!(flatten(value, scope)) else memo[scope] = value end end end |
#join(*parts) ⇒ String
Makes a new scope from given parts.
43 44 45 |
# File 'lib/mova/scope.rb', line 43 def join(*parts) parts.join(SEPARATOR) end |
#split(scope) ⇒ Array<String>
Split a scope into parts.
54 55 56 |
# File 'lib/mova/scope.rb', line 54 def split(scope) scope.split(SEPARATOR) end |