Skip to content

Commit c4317ef

Browse files
author
Arnaud Fernandés
authored
fix(date): apply ISO 8601 (#16)
* fix(date): apply ISO 8601
1 parent 30e1629 commit c4317ef

File tree

7 files changed

+51
-38
lines changed

7 files changed

+51
-38
lines changed

README.md

+9-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
Internationalization API
55

6+
## Breaking changes from 0.2 to 0.3
7+
- The first day of the week is now Monday according to ISO 8601.
8+
- The nil value in `month_names` and `abbr_month_names` was removed.
9+
610
## Installation
711

812
Add this to your application's `shard.yml`:
@@ -101,6 +105,7 @@ I18n.localize(Time.now, scope: :date, format: :long)
101105
> By default `Time` will be localized with `:time` scope.
102106
103107
To specify formats and all need localization information (like day or month names) fill your file in following way:
108+
> NOTE: According to ISO 8601, Monday is the first day of the week
104109
105110
```yaml
106111
__formats__:
@@ -109,7 +114,6 @@ __formats__:
109114
default: '%Y-%m-%d' # is used by default
110115
long: '%A, %d de %B %Y'
111116
month_names: # long month names
112-
-
113117
- Janeiro
114118
- Fevereiro
115119
- Março
@@ -123,16 +127,13 @@ __formats__:
123127
- Novembro
124128
- Dezembro
125129
abbr_month_names: # month abbreviations
126-
-
127130
- Jan
128131
- Fev
129132
# ...
130133
day_names: # fool day names
131-
- Domingo
132134
- Segunda
133135
# ...
134136
abbr_day_names: # short day names
135-
- Dom
136137
- Seg
137138
# ...
138139
```
@@ -170,14 +171,16 @@ I18n.translate("message", count: 0) # 0 messages
170171

171172
To store several alternative objects under one localization key they could be just listed in the file and later retrieved using `iter` argument:
172173

174+
> NOTE : The first index is `0`
175+
173176
```yaml
174177
__formats__:
175178
date:
176-
day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
179+
day_names: [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]
177180
```
178181

179182
```crystal
180-
I18n.translate("__formats__.date.day_names", iter: 2) "Tuesday"
183+
I18n.translate("__formats__.date.day_names", iter: 2) # >>> "Wednesday"
181184
```
182185

183186
### Embedding translations inside your binary

shard.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name: i18n
2-
version: 0.2.0
2+
version: 0.3
33

44
authors:
55
- Arnaud Fernandés <arnaud.fernandes@laposte.net>
66

7-
crystal: 0.28.0
7+
crystal: 0.29.0
88

99
license: MIT

spec/backend/yaml_spec.cr

+8-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ describe I18n::Backend::Yaml do
4242

4343
it { backend.translate("en", "messages.with_2_arguments", {attr: "a", attr2: "b"}).should eq("a and b") }
4444
it { backend.translate("pt", "hello").should(eq("olá")) }
45-
it { backend.translate("pt", "__formats__.date.day_names", iter: 2).should eq("Terça") }
45+
46+
it {
47+
# this usage is not recommended
48+
backend.translate("pt", "__formats__.date.day_names", iter: 1).should eq("Terça")
49+
}
4650
end
4751

4852
describe "#localize" do
@@ -62,17 +66,17 @@ describe I18n::Backend::Yaml do
6266

6367
context "with time format" do
6468
it "time default format" do
65-
backend.localize("pt", time, scope: :time).should(eq(time.to_s("%H:%M:%S")))
69+
backend.localize("pt", time, scope: :time).should(eq("12:13:14"))
6670
end
6771
end
6872

6973
context "with date format" do
7074
it "date default format" do
71-
backend.localize("pt", time, scope: :date).should(eq(time.to_s("%Y-%m-%d")))
75+
backend.localize("pt", time, scope: :date).should(eq("2010-10-11"))
7276
end
7377

7478
it "date long format" do
75-
backend.localize("en", time, scope: :date, format: "long").should(eq(time.to_s("%A, %d of %B %Y")))
79+
backend.localize("pt", time, scope: :date, format: "long").should(eq("Segunda, 11 de Outubro 2010"))
7680
end
7781
end
7882

spec/i18n_spec.cr

+5-5
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe I18n do
3434
end
3535

3636
describe ".localize" do
37-
time = Time.now
37+
time = Time.local(2019, 7, 14, 20, 1, 3)
3838

3939
it "format number" do
4040
I18n.localize(1234).should(eq("1.234"))
@@ -49,18 +49,18 @@ describe I18n do
4949
end
5050

5151
it "time default format" do
52-
I18n.localize(time, scope: :time).should(eq(time.to_s("%H:%M:%S")))
52+
I18n.localize(time, scope: :time).should(eq("20:01:03"))
5353
end
5454

5555
it "date default format" do
56-
I18n.localize(time, scope: :date).should(eq(time.to_s("%Y-%m-%d")))
56+
I18n.localize(time, scope: :date).should(eq("2019-07-14"))
5757
end
5858

5959
it "date long format" do
60-
I18n.localize(time, scope: :date, force_locale: "en", format: "long").should(eq(time.to_s("%A, %d of %B %Y")))
60+
I18n.localize(time, scope: :date, force_locale: "en", format: "long").should(eq("Sunday, 14 of July 2019"))
6161
end
6262

63-
it { I18n.localize(time, "en", :date, "long").should(eq(time.to_s("%A, %d of %B %Y"))) }
63+
it { I18n.localize(time, "en", :date, "long").should(eq("Sunday, 14 of July 2019")) }
6464
end
6565

6666
describe ".with_locale" do

spec/locales/en.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ __formats__:
2323
default: "%Y-%m-%d"
2424
long: "%A, %d of %B %Y"
2525

26-
month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
27-
abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
26+
month_names: [January, February, March, April, May, June, July, August, September, October, November, December]
27+
abbr_month_names: [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
2828

29-
day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
30-
abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
29+
day_names: [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]
30+
abbr_day_names: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]
3131

3232
time:
3333
formats:

spec/locales/pt.yml

+2-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ __formats__:
1717
default: '%Y-%m-%d'
1818
long: '%A, %d de %B %Y'
1919
month_names:
20-
-
2120
- Janeiro
2221
- Fevereiro
2322
- Março
@@ -31,7 +30,6 @@ __formats__:
3130
- Novembro
3231
- Dezembro
3332
abbr_month_names:
34-
-
3533
- Jan
3634
- Fev
3735
- Mar
@@ -45,21 +43,21 @@ __formats__:
4543
- Nov
4644
- Dez
4745
day_names:
48-
- Domingo
4946
- Segunda
5047
- Terça
5148
- Quarta
5249
- Quinta
5350
- Sexta
5451
- Sábado
52+
- Domingo
5553
abbr_day_names:
56-
- Dom
5754
- Seg
5855
- Ter
5956
- Qua
6057
- Qui
6158
- Sex
6259
- Sáb
60+
- Dom
6361
time:
6462
formats:
6563
default: '%H:%M:%S'

src/i18n/backend/yaml.cr

+21-13
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ module I18n
2121
{% end %}
2222
end
2323

24+
# Read files, normalize and merge all the translations
2425
def load(*args)
2526
if args[0].is_a?(String)
2627
files = Dir.glob(args[0] + "/*.yml")
@@ -67,9 +68,11 @@ module I18n
6768

6869
# Localize a number or a currency
6970
# Use the format if given
70-
# scope can be one of :number ( default ), :currency
71+
# scope can be one of `:number` ( default ), `:currency`
72+
#
7173
# Following keys are required :
7274
#
75+
# ```yaml
7376
# __formats__:
7477
# number:
7578
# decimal_separator: ','
@@ -79,6 +82,7 @@ module I18n
7982
# symbol: '€'
8083
# name: 'euro'
8184
# format: '%s€'
85+
# ```
8286
def localize(locale : String, object : Number, scope = :number, format = nil) : String
8387
return object.to_s if scope != :number && scope != :currency
8488

@@ -90,36 +94,39 @@ module I18n
9094
number
9195
end
9296

93-
# Localize a date or a datetime
94-
# Use the format if given
95-
# scope can be one of :time ( default ), :date, :datetime
96-
# Following keys are required :
97+
# Localize a date or a datetime using the *format* if provided.
98+
# *scope* can be one of :time ( default ), :date, :datetime
9799
#
100+
# NOTE: According to ISO 8601, Monday is the first day of the week
101+
#
102+
# Following keys are required :
103+
# ```yaml
98104
# __formats__:
99105
# date:
100106
# formats:
101107
# default: "%Y-%m-%d"
102108
# long: "%A, %d of %B %Y"
103109
#
104-
# month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
105-
# abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
110+
# month_names: [January, February, March, April, May, June, July, August, September, October, November, December]
111+
# abbr_month_names: [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
106112
#
107-
# day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
108-
# abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
113+
# day_names: [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]
114+
# abbr_day_names: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]
109115
#
110116
# time:
111117
# formats:
112118
# default: "%I:%M:%S %p"
119+
# ```
113120
def localize(locale : String, object : Time, scope = :time, format = nil) : String
114121
base_key = "__formats__." + scope.to_s + (format ? ".formats." + format.to_s : ".formats.default")
115122

116123
format = translate(locale, base_key)
117124
format = format.to_s.gsub(/%[aAbBpP]/) do |match|
118125
case match
119-
when "%a" then translate(locale, "__formats__.date.abbr_day_names", iter: object.day_of_week.to_i)
120-
when "%A" then translate(locale, "__formats__.date.day_names", iter: object.day_of_week.to_i)
121-
when "%b" then translate(locale, "__formats__.date.abbr_month_names", iter: object.month)
122-
when "%B" then translate(locale, "__formats__.date.month_names", iter: object.month)
126+
when "%a" then translate(locale, "__formats__.date.abbr_day_names", iter: object.day_of_week.value - 1)
127+
when "%A" then translate(locale, "__formats__.date.day_names", iter: object.day_of_week.value - 1)
128+
when "%b" then translate(locale, "__formats__.date.abbr_month_names", iter: object.month - 1)
129+
when "%B" then translate(locale, "__formats__.date.month_names", iter: object.month - 1)
123130
when "%p" then translate(locale, "__formats__.time.#{object.hour < 12 ? :am : :pm}").upcase if object.responds_to? :hour
124131
when "%P" then translate(locale, "__formats__.time.#{object.hour < 12 ? :am : :pm}").downcase if object.responds_to? :hour
125132
end
@@ -182,6 +189,7 @@ module I18n
182189
end
183190
end
184191

192+
# Flatten paths
185193
def self.normalize(data : YAML::Any, path : String = "", final = Hash(String, YAML::Any).new)
186194
data.as_h.keys.each do |k|
187195
newp = path.size == 0 ? k.to_s : path + "." + k.to_s

0 commit comments

Comments
 (0)