1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
# frozen_string_literal: true
require 'i18n_data/version'
module I18nData
class BaseException < StandardError
def to_s
"#{self.class} -- #{super}"
end
end
class NoTranslationAvailable < BaseException; end
class AccessDenied < BaseException; end
class Unknown < BaseException; end
class << self
def languages(language_code = 'EN')
fetch :languages, language_code do
data_provider.codes(:languages, normal_to_region_code(language_code.to_s.upcase))
end
end
def countries(language_code = 'EN')
fetch :countries, language_code do
data_provider.codes(:countries, normal_to_region_code(language_code.to_s.upcase))
end
end
def country_code(name)
recognise_code(:countries, name)
end
def language_code(name)
recognise_code(:languages, name)
end
def data_provider
@data_provider ||= begin
require 'i18n_data/file_data_provider'
FileDataProvider
end
end
def data_provider=(provider)
@cache = nil
@data_provider = provider
end
private
def fetch(type, language_code)
@cache ||= Hash.new { |h, k| h[k] = {} }
@cache[type].fetch(language_code) { @cache[type][language_code] = yield }
end
# hardcode languages that do not have a default type
# e.g. zh does not exist, but zh_CN does
def normal_to_region_code(normal)
{
"ZH" => "zh_CN",
"BN" => "bn_IN"
}[normal] || normal
end
def recognise_code(type, search)
search = search.strip
# common languages first <-> faster in majority of cases
language_codes = ['EN', 'ES', 'FR', 'DE', 'ZH'] | available_language_codes
language_codes.each do |language_code|
options =
begin
send(type, language_code)
rescue NoTranslationAvailable
next
end
options.each do |code, name|
# support "Dutch" and "Dutch; Flemish", checks for inclusion first to skip the splitting
# then check for exact match
return code if name.include?(search) && (name == search || name.split('; ').include?(search))
end
end
nil # not found
end
# NOTE: this is not perfect since the used provider might have more or less languages available
# but it's better than just using the available english language codes
def available_language_codes
@available_language_codes ||= begin
files = Dir[File.expand_path('../cache/file_data_provider/languages-*', __dir__)]
files.map! { |f| f[/languages-(.*)\./, 1] }
end
end
end
end
|