Skip to content

Commit

Permalink
Merge pull request #25 from michieldewit/master
Browse files Browse the repository at this point in the history
Load all default fallbacks for a specific locale, by including all prefix subpatterns
  • Loading branch information
onomojo authored Aug 29, 2016
2 parents cd938ae + 2d1c033 commit 0c62991
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 7 deletions.
1 change: 1 addition & 0 deletions lib/i18n_country_translations.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'i18n_country_translations/locale_files_pattern_generator'
require 'i18n_country_translations/railtie'

module I18nCountryTranslations
Expand Down
32 changes: 32 additions & 0 deletions lib/i18n_country_translations/locale_files_pattern_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module I18nCountryTranslations

# Generates patterns for locale files, bases on a list of supported locales
class LocaleFilesPatternGenerator

attr_reader :base_pattern, :extension

def initialize(base_pattern, extension = '.yml')
@base_pattern = base_pattern
@extension = extension
end

# Generates a glob file pattern for the specified list of locales (i.e. IETF language tags)
def pattern_from(locales)
locales = Array(locales || [])
locales = locales.map { |locale| subpatterns_from locale }.flatten
pattern = locales.blank? ? '*' : "{#{locales.join ','}}"
"#{base_pattern}#{pattern}#{extension}"
end

protected

# Generates subpatterns for the specified locale (i.e. IETF language tag).
# Subpatterns are all more generic variations of a locale.
# E.g. subpatterns for en-US are en-US and en. Subpatterns for az-Latn-IR are az-Latn-IR, az-Latn and az
def subpatterns_from(locale)
parts = locale.to_s.split('-')
parts.map.with_index { |part,index| parts[0..index].join('-') }
end

end
end
9 changes: 2 additions & 7 deletions lib/i18n_country_translations/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ module I18nCountryTranslations
class Railtie < ::Rails::Railtie #:nodoc:
initializer 'i18n-country-translations' do |app|
I18nCountryTranslations::Railtie.instance_eval do
pattern = pattern_from app.config.i18n.available_locales

add("rails/locale/**/#{pattern}.yml")
generator = LocaleFilesPatternGenerator.new('rails/locale/**/')
add generator.pattern_from app.config.i18n.available_locales
end
end

Expand All @@ -17,9 +16,5 @@ def self.add(pattern)
I18n.load_path.concat(files)
end

def self.pattern_from(args)
array = Array(args || [])
array.blank? ? '*' : "{#{array.join ','}}"
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require 'i18n_country_translations/locale_files_pattern_generator'

describe I18nCountryTranslations::LocaleFilesPatternGenerator do

context "with given locale" do
let(:generator) { I18nCountryTranslations::LocaleFilesPatternGenerator.new('base/', '.yml') }

def test_pattern(pattern, sample)
if File.const_defined? 'FNM_EXTGLOB'
# Use proper way to test, by calling fnmatch and actually executing the pattern.
# This only works in Ruby 2.1.0 and upwards
File.fnmatch(pattern, sample, File::FNM_EXTGLOB)
else
# Roughly approximate pattern matching using regular expressions. Only recognizes the braces { } syntax.
# Other glob syntax (e.g. * and ** is not recognized). So keep test cases simple!
pattern = '^' + pattern.split(/\{(.+?)\}/).each_with_index.map do |part, index|
if index.even?
# Pattern part outside of { }
Regexp.escape(part)
else
'(' + part.split(',').map { |option| Regexp.escape(option) }.join('|') + ')'
end
end.join + '$'

# Test against regular expression pattern
(sample =~ Regexp.new(pattern)) == 0
end
end

it "generates a pattern for simple locales" do
locales = ['en', 'fr']
pattern = generator.pattern_from(locales)

# Make sure pattern matches locales
locales.each do |locale|
expect(test_pattern(pattern, "base/#{locale}.yml")).to be true
end

# Make sure pattern does not match other locales
['nl', 'en-US', 'fra', 'cen'].each do |locale|
expect(test_pattern(pattern, "base/#{locale}.yml")).to be false
end
end

it "generates a pattern for locales with tags" do
locales = ['en-US', 'az-Latn-IR']
sublocales = ['en', 'en-US', 'az', 'az-Latn', 'az-Latn-IR']
pattern = generator.pattern_from(locales)

# Make sure pattern matches locales
sublocales.each do |locale|
expect(test_pattern(pattern, "base/#{locale}.yml")).to be true
end

# Make sure pattern does not match other locales
['en-AU', 'az-IR'].each do |locale|
expect(test_pattern(pattern, "base/#{locale}.yml")).to be false
end
end
end

end

0 comments on commit 0c62991

Please sign in to comment.