polish 0.0.1
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/LICENSE +20 -0
- data/README.md +25 -0
- data/Rakefile +56 -0
- data/TODO +5 -0
- data/init.rb +1 -0
- data/lib/polish.rb +104 -0
- data/lib/polish/action_view_ext/helpers/date_helper.rb +94 -0
- data/lib/polish/backend/advanced.rb +105 -0
- data/lib/polish/locale/actionview.yml +81 -0
- data/lib/polish/locale/activerecord.yml +27 -0
- data/lib/polish/locale/activesupport.yml +11 -0
- data/lib/polish/locale/datetime.yml +25 -0
- data/lib/polish/locale/pluralize.rb +16 -0
- data/lib/vendor/i18n/CHANGELOG.textile +57 -0
- data/lib/vendor/i18n/MIT-LICENSE +20 -0
- data/lib/vendor/i18n/README.textile +42 -0
- data/lib/vendor/i18n/Rakefile +21 -0
- data/lib/vendor/i18n/VERSION +1 -0
- data/lib/vendor/i18n/i18n.gemspec +141 -0
- data/lib/vendor/i18n/lib/i18n.rb +270 -0
- data/lib/vendor/i18n/lib/i18n/backend/base.rb +251 -0
- data/lib/vendor/i18n/lib/i18n/backend/cache.rb +71 -0
- data/lib/vendor/i18n/lib/i18n/backend/chain.rb +64 -0
- data/lib/vendor/i18n/lib/i18n/backend/fallbacks.rb +53 -0
- data/lib/vendor/i18n/lib/i18n/backend/gettext.rb +65 -0
- data/lib/vendor/i18n/lib/i18n/backend/pluralization.rb +56 -0
- data/lib/vendor/i18n/lib/i18n/backend/simple.rb +23 -0
- data/lib/vendor/i18n/lib/i18n/exceptions.rb +61 -0
- data/lib/vendor/i18n/lib/i18n/gettext.rb +25 -0
- data/lib/vendor/i18n/lib/i18n/helpers/gettext.rb +35 -0
- data/lib/vendor/i18n/lib/i18n/locale/fallbacks.rb +100 -0
- data/lib/vendor/i18n/lib/i18n/locale/tag.rb +27 -0
- data/lib/vendor/i18n/lib/i18n/locale/tag/parents.rb +24 -0
- data/lib/vendor/i18n/lib/i18n/locale/tag/rfc4646.rb +78 -0
- data/lib/vendor/i18n/lib/i18n/locale/tag/simple.rb +44 -0
- data/lib/vendor/i18n/lib/i18n/string.rb +95 -0
- data/lib/vendor/i18n/test/all.rb +5 -0
- data/lib/vendor/i18n/test/api/basics.rb +15 -0
- data/lib/vendor/i18n/test/api/interpolation.rb +85 -0
- data/lib/vendor/i18n/test/api/lambda.rb +52 -0
- data/lib/vendor/i18n/test/api/link.rb +47 -0
- data/lib/vendor/i18n/test/api/localization/date.rb +65 -0
- data/lib/vendor/i18n/test/api/localization/date_time.rb +63 -0
- data/lib/vendor/i18n/test/api/localization/lambda.rb +26 -0
- data/lib/vendor/i18n/test/api/localization/time.rb +63 -0
- data/lib/vendor/i18n/test/api/pluralization.rb +37 -0
- data/lib/vendor/i18n/test/api/translation.rb +51 -0
- data/lib/vendor/i18n/test/backend/cache/cache_test.rb +57 -0
- data/lib/vendor/i18n/test/backend/chain/api_test.rb +80 -0
- data/lib/vendor/i18n/test/backend/chain/chain_test.rb +64 -0
- data/lib/vendor/i18n/test/backend/fallbacks/api_test.rb +79 -0
- data/lib/vendor/i18n/test/backend/fallbacks/fallbacks_test.rb +29 -0
- data/lib/vendor/i18n/test/backend/pluralization/api_test.rb +81 -0
- data/lib/vendor/i18n/test/backend/pluralization/pluralization_test.rb +39 -0
- data/lib/vendor/i18n/test/backend/simple/all.rb +5 -0
- data/lib/vendor/i18n/test/backend/simple/api_test.rb +90 -0
- data/lib/vendor/i18n/test/backend/simple/lookup_test.rb +24 -0
- data/lib/vendor/i18n/test/backend/simple/setup.rb +147 -0
- data/lib/vendor/i18n/test/backend/simple/translations_test.rb +89 -0
- data/lib/vendor/i18n/test/fixtures/locales/de.po +61 -0
- data/lib/vendor/i18n/test/fixtures/locales/en.rb +3 -0
- data/lib/vendor/i18n/test/fixtures/locales/en.yml +3 -0
- data/lib/vendor/i18n/test/fixtures/locales/plurals.rb +112 -0
- data/lib/vendor/i18n/test/gettext/api_test.rb +78 -0
- data/lib/vendor/i18n/test/gettext/backend_test.rb +35 -0
- data/lib/vendor/i18n/test/i18n_exceptions_test.rb +97 -0
- data/lib/vendor/i18n/test/i18n_load_path_test.rb +23 -0
- data/lib/vendor/i18n/test/i18n_test.rb +163 -0
- data/lib/vendor/i18n/test/locale/fallbacks_test.rb +128 -0
- data/lib/vendor/i18n/test/locale/tag/rfc4646_test.rb +147 -0
- data/lib/vendor/i18n/test/locale/tag/simple_test.rb +35 -0
- data/lib/vendor/i18n/test/string_test.rb +94 -0
- data/lib/vendor/i18n/test/test_helper.rb +71 -0
- data/lib/vendor/i18n/test/with_options.rb +34 -0
- data/lib/vendor/i18n/vendor/po_parser.rb +329 -0
- data/spec/fixtures/en.yml +4 -0
- data/spec/fixtures/pl.yml +4 -0
- data/spec/i18n/locale/datetime_spec.rb +91 -0
- data/spec/i18n/locale/pluralization_spec.rb +41 -0
- data/spec/locale_spec.rb +124 -0
- data/spec/polish_spec.rb +141 -0
- data/spec/spec_helper.rb +4 -0
- metadata +138 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# I18n locale fallbacks are useful when you want your application to use
|
|
4
|
+
# translations from other locales when translations for the current locale are
|
|
5
|
+
# missing. E.g. you might want to use :en translations when translations in
|
|
6
|
+
# your applications main locale :de are missing.
|
|
7
|
+
#
|
|
8
|
+
# To enable locale specific pluralizations you can simply include the
|
|
9
|
+
# Pluralization module to the Simple backend - or whatever other backend you
|
|
10
|
+
# are using.
|
|
11
|
+
#
|
|
12
|
+
# I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
|
|
13
|
+
#
|
|
14
|
+
# You also need to make sure to provide pluralization algorithms to the
|
|
15
|
+
# backend, i.e. include them to your I18n.load_path accordingly.
|
|
16
|
+
module I18n
|
|
17
|
+
module Backend
|
|
18
|
+
module Pluralization
|
|
19
|
+
# Overwrites the Base backend translate method so that it will check the
|
|
20
|
+
# translation meta data space (:i18n) for locale specific pluralizers
|
|
21
|
+
# and use them to pluralize the given entry.
|
|
22
|
+
#
|
|
23
|
+
# Pluralizers are expected to respond to #call(entry, count) and return
|
|
24
|
+
# a pluralization key. Valid keys depend on the translation data hash
|
|
25
|
+
# (entry) but it is generally recommended to follow CLDR's style, i.e.
|
|
26
|
+
# return one of the keys :zero, :one, :few, :many, :other.
|
|
27
|
+
#
|
|
28
|
+
# The :zero key is always picked directly when count equals 0 AND the
|
|
29
|
+
# translation data has the key :zero. This way translators are free to
|
|
30
|
+
# either pick a special :zero translation even for languages where the
|
|
31
|
+
# pluralizer does not return a :zero key.
|
|
32
|
+
def pluralize(locale, entry, count)
|
|
33
|
+
return entry unless entry.is_a?(Hash) and count
|
|
34
|
+
|
|
35
|
+
pluralizer = pluralizer(locale)
|
|
36
|
+
if pluralizer.respond_to?(:call)
|
|
37
|
+
key = count == 0 && entry.has_key?(:zero) ? :zero : pluralizer.call(count)
|
|
38
|
+
raise InvalidPluralizationData.new(entry, count) unless entry.has_key?(key)
|
|
39
|
+
entry[key]
|
|
40
|
+
else
|
|
41
|
+
super
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
protected
|
|
46
|
+
|
|
47
|
+
def pluralizers
|
|
48
|
+
@pluralizers ||= {}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def pluralizer(locale)
|
|
52
|
+
pluralizers[locale] ||= lookup(locale, :"i18n.pluralize")
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'i18n/backend/base'
|
|
4
|
+
|
|
5
|
+
# Stub class for the Simple backend. The actual implementation is provided by
|
|
6
|
+
# the backend Base class. This makes it easier to extend the Simple backend's
|
|
7
|
+
# behaviour by including modules. E.g.:
|
|
8
|
+
#
|
|
9
|
+
# module I18n::Backend::Pluralization
|
|
10
|
+
# def pluralize(*args)
|
|
11
|
+
# # extended pluralization logic
|
|
12
|
+
# super
|
|
13
|
+
# end
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
|
|
17
|
+
|
|
18
|
+
module I18n
|
|
19
|
+
module Backend
|
|
20
|
+
class Simple < Base
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
class KeyError < IndexError
|
|
4
|
+
def initialize(message = nil)
|
|
5
|
+
super(message || "key not found")
|
|
6
|
+
end
|
|
7
|
+
end unless defined?(KeyError)
|
|
8
|
+
|
|
9
|
+
module I18n
|
|
10
|
+
class ArgumentError < ::ArgumentError; end
|
|
11
|
+
|
|
12
|
+
class InvalidLocale < ArgumentError
|
|
13
|
+
attr_reader :locale
|
|
14
|
+
def initialize(locale)
|
|
15
|
+
@locale = locale
|
|
16
|
+
super "#{locale.inspect} is not a valid locale"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class MissingTranslationData < ArgumentError
|
|
21
|
+
attr_reader :locale, :key, :options
|
|
22
|
+
def initialize(locale, key, options)
|
|
23
|
+
@key, @locale, @options = key, locale, options
|
|
24
|
+
keys = I18n.send(:normalize_translation_keys, locale, key, options[:scope])
|
|
25
|
+
keys << 'no key' if keys.size < 2
|
|
26
|
+
super "translation missing: #{keys.join(', ')}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class InvalidPluralizationData < ArgumentError
|
|
31
|
+
attr_reader :entry, :count
|
|
32
|
+
def initialize(entry, count)
|
|
33
|
+
@entry, @count = entry, count
|
|
34
|
+
super "translation data #{entry.inspect} can not be used with :count => #{count}"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class MissingInterpolationArgument < ArgumentError
|
|
39
|
+
attr_reader :values, :string
|
|
40
|
+
def initialize(values, string)
|
|
41
|
+
@values, @string = values, string
|
|
42
|
+
super "missing interpolation argument in #{string.inspect} (#{values.inspect} given)"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class ReservedInterpolationKey < ArgumentError
|
|
47
|
+
attr_reader :key, :string
|
|
48
|
+
def initialize(key, string)
|
|
49
|
+
@key, @string = key, string
|
|
50
|
+
super "reserved key #{key.inspect} used in #{string.inspect}"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class UnknownFileType < ArgumentError
|
|
55
|
+
attr_reader :type, :filename
|
|
56
|
+
def initialize(type, filename)
|
|
57
|
+
@type, @filename = type, filename
|
|
58
|
+
super "can not load translations from #{filename}, the file type #{type} is not known"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module I18n
|
|
4
|
+
module Gettext
|
|
5
|
+
PLURAL_SEPARATOR = "\001"
|
|
6
|
+
CONTEXT_SEPARATOR = "\004"
|
|
7
|
+
|
|
8
|
+
@@plural_keys = { :en => [:one, :other] }
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
# returns an array of plural keys for the given locale so that we can
|
|
12
|
+
# convert from gettext's integer-index based style
|
|
13
|
+
# TODO move this information to the pluralization module
|
|
14
|
+
def plural_keys(locale)
|
|
15
|
+
@@plural_keys[locale] || @@plural_keys[:en]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def extract_scope(msgid, separator = nil)
|
|
19
|
+
scope = msgid.to_s.split(separator || '|')
|
|
20
|
+
msgid = scope.pop
|
|
21
|
+
[scope, msgid]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module I18n
|
|
4
|
+
module Helpers
|
|
5
|
+
# Implements classical Gettext style accessors. To use this include the
|
|
6
|
+
# module to the global namespace or wherever you want to use it.
|
|
7
|
+
#
|
|
8
|
+
# include I18n::Helpers::Gettext
|
|
9
|
+
module Gettext
|
|
10
|
+
def _(msgid, options = {})
|
|
11
|
+
I18n.t(msgid, { :default => msgid, :separator => '|' }.merge(options))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def sgettext(msgid, separator = '|')
|
|
15
|
+
scope, msgid = I18n::Gettext.extract_scope(msgid, separator)
|
|
16
|
+
I18n.t(msgid, :scope => scope, :default => msgid)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def pgettext(msgctxt, msgid, separator = I18n::Gettext::CONTEXT_SEPARATOR)
|
|
20
|
+
sgettext([msgctxt, msgid].join(separator), separator)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def ngettext(msgid, msgid_plural, n = 1)
|
|
24
|
+
nsgettext(msgid, msgid_plural, n, nil)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def nsgettext(msgid, msgid_plural, n = 1, separator = nil)
|
|
28
|
+
scope, msgid = I18n::Gettext.extract_scope(msgid, separator)
|
|
29
|
+
default = { :one => msgid, :other => msgid_plural }
|
|
30
|
+
msgid = [msgid, I18n::Gettext::PLURAL_SEPARATOR, msgid_plural].join
|
|
31
|
+
I18n.t(msgid, :default => default, :count => n, :scope => scope)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'i18n/locale/tag'
|
|
4
|
+
|
|
5
|
+
# Locale Fallbacks
|
|
6
|
+
#
|
|
7
|
+
# Extends the I18n module to hold a fallbacks instance which is set to an
|
|
8
|
+
# instance of I18n::Locale::Fallbacks by default but can be swapped with a
|
|
9
|
+
# different implementation.
|
|
10
|
+
#
|
|
11
|
+
# Locale fallbacks will compute a number of fallback locales for a given locale.
|
|
12
|
+
# For example:
|
|
13
|
+
#
|
|
14
|
+
# <pre><code>
|
|
15
|
+
# I18n.fallbacks[:"es-MX"] # => [:"es-MX", :es, :en] </code></pre>
|
|
16
|
+
#
|
|
17
|
+
# Locale fallbacks always fall back to
|
|
18
|
+
#
|
|
19
|
+
# * all parent locales of a given locale (e.g. :es for :"es-MX") first,
|
|
20
|
+
# * the current default locales and all of their parents second
|
|
21
|
+
#
|
|
22
|
+
# The default locales are set to [I18n.default_locale] by default but can be
|
|
23
|
+
# set to something else.
|
|
24
|
+
#
|
|
25
|
+
# One can additionally add any number of additional fallback locales manually.
|
|
26
|
+
# These will be added before the default locales to the fallback chain. For
|
|
27
|
+
# example:
|
|
28
|
+
#
|
|
29
|
+
# # using the default locale as default fallback locale
|
|
30
|
+
#
|
|
31
|
+
# I18n.default_locale = :"en-US"
|
|
32
|
+
# I18n.fallbacks = I18n::Fallbacks.new(:"de-AT" => :"de-DE")
|
|
33
|
+
# I18n.fallbacks[:"de-AT"] # => [:"de-AT", :"de-DE", :de, :"en-US", :en]
|
|
34
|
+
#
|
|
35
|
+
# # using a custom locale as default fallback locale
|
|
36
|
+
#
|
|
37
|
+
# I18n.fallbacks = I18n::Fallbacks.new(:"en-GB", :"de-AT" => :de, :"de-CH" => :de)
|
|
38
|
+
# I18n.fallbacks[:"de-AT"] # => [:"de-AT", :de, :"en-GB", :en]
|
|
39
|
+
# I18n.fallbacks[:"de-CH"] # => [:"de-CH", :de, :"en-GB", :en]
|
|
40
|
+
#
|
|
41
|
+
# # mapping fallbacks to an existing instance
|
|
42
|
+
#
|
|
43
|
+
# # people speaking Catalan also speak Spanish as spoken in Spain
|
|
44
|
+
# fallbacks = I18n.fallbacks
|
|
45
|
+
# fallbacks.map(:ca => :"es-ES")
|
|
46
|
+
# fallbacks[:ca] # => [:ca, :"es-ES", :es, :"en-US", :en]
|
|
47
|
+
#
|
|
48
|
+
# # people speaking Arabian as spoken in Palestine also speak Hebrew as spoken in Israel
|
|
49
|
+
# fallbacks.map(:"ar-PS" => :"he-IL")
|
|
50
|
+
# fallbacks[:"ar-PS"] # => [:"ar-PS", :ar, :"he-IL", :he, :"en-US", :en]
|
|
51
|
+
# fallbacks[:"ar-EG"] # => [:"ar-EG", :ar, :"en-US", :en]
|
|
52
|
+
#
|
|
53
|
+
# # people speaking Sami as spoken in Finnland also speak Swedish and Finnish as spoken in Finnland
|
|
54
|
+
# fallbacks.map(:sms => [:"se-FI", :"fi-FI"])
|
|
55
|
+
# fallbacks[:sms] # => [:sms, :"se-FI", :se, :"fi-FI", :fi, :"en-US", :en]
|
|
56
|
+
|
|
57
|
+
module I18n
|
|
58
|
+
module Locale
|
|
59
|
+
class Fallbacks < Hash
|
|
60
|
+
def initialize(*mappings)
|
|
61
|
+
@map = {}
|
|
62
|
+
map(mappings.pop) if mappings.last.is_a?(Hash)
|
|
63
|
+
self.defaults = mappings.empty? ? [I18n.default_locale.to_sym] : mappings
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def defaults=(defaults)
|
|
67
|
+
@defaults = defaults.map { |default| compute(default, false) }.flatten
|
|
68
|
+
end
|
|
69
|
+
attr_reader :defaults
|
|
70
|
+
|
|
71
|
+
def [](locale)
|
|
72
|
+
raise InvalidLocale.new(locale) if locale.nil?
|
|
73
|
+
locale = locale.to_sym
|
|
74
|
+
super || store(locale, compute(locale))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def map(mappings)
|
|
78
|
+
mappings.each do |from, to|
|
|
79
|
+
from, to = from.to_sym, Array(to)
|
|
80
|
+
to.each do |to|
|
|
81
|
+
@map[from] ||= []
|
|
82
|
+
@map[from] << to.to_sym
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
protected
|
|
88
|
+
|
|
89
|
+
def compute(tags, include_defaults = true)
|
|
90
|
+
result = Array(tags).collect do |tag|
|
|
91
|
+
tags = I18n::Locale::Tag.tag(tag).self_and_parents.map! { |t| t.to_sym }
|
|
92
|
+
tags.each { |tag| tags += compute(@map[tag]) if @map[tag] }
|
|
93
|
+
tags
|
|
94
|
+
end.flatten
|
|
95
|
+
result.push(*defaults) if include_defaults
|
|
96
|
+
result.uniq
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'i18n/locale/tag/simple'
|
|
4
|
+
require 'i18n/locale/tag/rfc4646'
|
|
5
|
+
|
|
6
|
+
module I18n
|
|
7
|
+
module Locale
|
|
8
|
+
module Tag
|
|
9
|
+
class << self
|
|
10
|
+
# Returns the current locale tag implementation. Defaults to +I18n::Locale::Tag::Simple+.
|
|
11
|
+
def implementation
|
|
12
|
+
@@implementation ||= Simple
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Sets the current locale tag implementation. Use this to set a different locale tag implementation.
|
|
16
|
+
def implementation=(implementation)
|
|
17
|
+
@@implementation = implementation
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Factory method for locale tags. Delegates to the current locale tag implementation.
|
|
21
|
+
def tag(tag)
|
|
22
|
+
implementation.tag(tag)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module I18n
|
|
4
|
+
module Locale
|
|
5
|
+
module Tag
|
|
6
|
+
module Parents
|
|
7
|
+
def parent
|
|
8
|
+
@parent ||= begin
|
|
9
|
+
segs = to_a.compact
|
|
10
|
+
segs.length > 1 ? self.class.tag(*segs[0..(segs.length-2)].join('-')) : nil
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self_and_parents
|
|
15
|
+
@self_and_parents ||= [self] + parents
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parents
|
|
19
|
+
@parents ||= ([parent] + (parent ? parent.parents : [])).compact
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# RFC 4646/47 compliant Locale tag implementation that parses locale tags to
|
|
4
|
+
# subtags such as language, script, region, variant etc.
|
|
5
|
+
#
|
|
6
|
+
# For more information see by http://en.wikipedia.org/wiki/IETF_language_tag
|
|
7
|
+
#
|
|
8
|
+
# Rfc4646::Parser does not implement grandfathered tags.
|
|
9
|
+
|
|
10
|
+
require 'i18n/locale/tag/parents'
|
|
11
|
+
|
|
12
|
+
module I18n
|
|
13
|
+
module Locale
|
|
14
|
+
module Tag
|
|
15
|
+
RFC4646_SUBTAGS = [ :language, :script, :region, :variant, :extension, :privateuse, :grandfathered ]
|
|
16
|
+
RFC4646_FORMATS = { :language => :downcase, :script => :capitalize, :region => :upcase, :variant => :downcase }
|
|
17
|
+
|
|
18
|
+
class Rfc4646 < Struct.new(*RFC4646_SUBTAGS)
|
|
19
|
+
class << self
|
|
20
|
+
# Parses the given tag and returns a Tag instance if it is valid.
|
|
21
|
+
# Returns false if the given tag is not valid according to RFC 4646.
|
|
22
|
+
def tag(tag)
|
|
23
|
+
matches = parser.match(tag)
|
|
24
|
+
new(*matches) if matches
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def parser
|
|
28
|
+
@@parser ||= Rfc4646::Parser
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def parser=(parser)
|
|
32
|
+
@@parser = parser
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
include Parents
|
|
37
|
+
|
|
38
|
+
RFC4646_FORMATS.each do |name, format|
|
|
39
|
+
define_method(name) { self[name].send(format) unless self[name].nil? }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def to_sym
|
|
43
|
+
to_s.to_sym
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_s
|
|
47
|
+
@tag ||= to_a.compact.join("-")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def to_a
|
|
51
|
+
members.collect { |attr| self.send(attr) }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
module Parser
|
|
55
|
+
PATTERN = %r{\A(?:
|
|
56
|
+
([a-z]{2,3}(?:(?:-[a-z]{3}){0,3})?|[a-z]{4}|[a-z]{5,8}) # language
|
|
57
|
+
(?:-([a-z]{4}))? # script
|
|
58
|
+
(?:-([a-z]{2}|\d{3}))? # region
|
|
59
|
+
(?:-([0-9a-z]{5,8}|\d[0-9a-z]{3}))* # variant
|
|
60
|
+
(?:-([0-9a-wyz](?:-[0-9a-z]{2,8})+))* # extension
|
|
61
|
+
(?:-(x(?:-[0-9a-z]{1,8})+))?| # privateuse subtag
|
|
62
|
+
(x(?:-[0-9a-z]{1,8})+)| # privateuse tag
|
|
63
|
+
/* ([a-z]{1,3}(?:-[0-9a-z]{2,8}){1,2}) */ # grandfathered
|
|
64
|
+
)\z}xi
|
|
65
|
+
|
|
66
|
+
class << self
|
|
67
|
+
def match(tag)
|
|
68
|
+
c = PATTERN.match(tag.to_s).captures
|
|
69
|
+
c[0..4] << (c[5].nil? ? c[6] : c[5]) << c[7] # TODO c[7] is grandfathered, throw a NotImplemented exception here?
|
|
70
|
+
rescue
|
|
71
|
+
false
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'i18n/locale/tag/parents'
|
|
4
|
+
|
|
5
|
+
# Simple Locale tag implementation that computes subtags by simply splitting
|
|
6
|
+
# the locale tag at '-' occurences.
|
|
7
|
+
|
|
8
|
+
module I18n
|
|
9
|
+
module Locale
|
|
10
|
+
module Tag
|
|
11
|
+
class Simple
|
|
12
|
+
class << self
|
|
13
|
+
def tag(tag)
|
|
14
|
+
new(tag)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
include Parents
|
|
19
|
+
|
|
20
|
+
attr_reader :tag
|
|
21
|
+
|
|
22
|
+
def initialize(*tag)
|
|
23
|
+
@tag = tag.join('-').to_sym
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def subtags
|
|
27
|
+
@subtags = tag.to_s.split('-').map { |subtag| subtag.to_s }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_sym
|
|
31
|
+
tag
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_s
|
|
35
|
+
tag.to_s
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_a
|
|
39
|
+
subtags
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|