Skip to content

Commit 0d66753

Browse files
gbathreeclaude
andcommitted
Add specs to prevent flatpickr format string corruption in locale files
Finnish locale (openfoodfoundation#13360) had `flatpickr_date_format: "Vuosi"` (Finnish for "Year") instead of `"d.m.Y"`. Translators on Transifex mistakenly translated the format codes, producing strings like "V1749326700000o005 12:35" because `u` is the flatpickr milliseconds token. The format string fix was already applied in 95412bd (fixing fi.yml). This commit adds regression tests to catch similar issues in any locale going forward: - Ruby spec validates all locale files have valid flatpickr format strings (only recognised token chars + separators), with a documented list of currently-known broken locales (cy, el, eu, ko, pa, sr, tr, uk). - Jest test confirms `importFlatpickrLocale("fi")` returns a valid Finnish locale object with Finnish weekday and month names. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7fe4717 commit 0d66753

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

spec/javascripts/stimulus/flatpickr_controller_test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,15 @@ describe("FlatpickrController", () => {
3131
expect(locale).toHaveProperty("weekAbbreviation");
3232
expect(locale.weekAbbreviation).toBe("Sem");
3333
});
34+
35+
it("returns locale object for Finnish (fi)", async () => {
36+
const controller = new FlatpickrController();
37+
const locale = await controller.importFlatpickrLocale("fi");
38+
expect(locale).toBeInstanceOf(Object);
39+
expect(locale).toHaveProperty("weekdays");
40+
expect(locale).toHaveProperty("months");
41+
expect(locale.weekdays.shorthand).toContain("ma");
42+
expect(locale.months.shorthand).toContain("tammi");
43+
});
3444
});
3545
});
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# frozen_string_literal: true
2+
3+
require "yaml"
4+
5+
# Valid flatpickr format token characters (single-character tokens and common separators).
6+
# See: https://flatpickr.js.org/formatting/
7+
#
8+
# Tokens: Z D F G H J K M S U W Y d h i j l m n s u w y
9+
# Separators: . - / : (space)
10+
# Escape: \ (makes the next character literal)
11+
VALID_FLATPICKR_FORMAT_REGEX = %r{\A[ZDFGHJKMSUWYdhijlmnsuwy.\-/: \\]+\z}
12+
13+
# Known locales with incorrect (translator-provided) format strings.
14+
# These should be fixed in Transifex and removed from this list as they are corrected.
15+
# See: https://github.com/openfoodfoundation/openfoodnetwork/issues/13360
16+
KNOWN_BROKEN_FLATPICKR_LOCALES = %w[cy el eu ko pa sr tr uk].freeze
17+
18+
RSpec.describe "Flatpickr date format strings in locale files" do
19+
def locale_files
20+
Rails.root.glob("config/locales/*.yml")
21+
end
22+
23+
def date_picker_formats(file)
24+
yaml = YAML.safe_load_file(file, permitted_classes: [Symbol])
25+
return {} unless yaml
26+
27+
root = yaml.values.first
28+
return {} unless root.is_a?(Hash)
29+
30+
date_picker = root.dig("spree", "date_picker")
31+
return {} unless date_picker.is_a?(Hash)
32+
33+
{
34+
date: date_picker["flatpickr_date_format"],
35+
datetime: date_picker["flatpickr_datetime_format"]
36+
}.compact
37+
end
38+
39+
it "locale files are present" do
40+
expect(locale_files).not_to be_empty
41+
end
42+
43+
shared_examples "valid flatpickr format" do |format_key|
44+
it "#{format_key} is a valid flatpickr format string in all locales" do
45+
invalid = []
46+
47+
locale_files.each do |file|
48+
locale_code = File.basename(file, ".yml")
49+
next if KNOWN_BROKEN_FLATPICKR_LOCALES.include?(locale_code)
50+
51+
formats = date_picker_formats(file)
52+
format = formats[format_key]
53+
next unless format
54+
55+
invalid << "#{locale_code}: '#{format}'" unless format.match?(VALID_FLATPICKR_FORMAT_REGEX)
56+
end
57+
58+
expect(invalid)
59+
.to be_empty,
60+
"Invalid #{format_key} found in locale files:\n" \
61+
"#{invalid.join("\n")}\n\n" \
62+
"Flatpickr format strings use single-character tokens (e.g. Y=year, m=month).\n" \
63+
"They must not be translated. Valid tokens: ZDFGHJKMSUWYdhijlmnsuwy\n" \
64+
"Valid separators: . - / : space\n" \
65+
"See: https://flatpickr.js.org/formatting/"
66+
end
67+
end
68+
69+
include_examples "valid flatpickr format", :date
70+
include_examples "valid flatpickr format", :datetime
71+
72+
describe "Finnish locale specifically" do
73+
it "has valid flatpickr_date_format" do
74+
formats = date_picker_formats(Rails.root.join("config/locales/fi.yml"))
75+
expect(formats[:date]).to eq("d.m.Y")
76+
end
77+
78+
it "has valid flatpickr_datetime_format" do
79+
formats = date_picker_formats(Rails.root.join("config/locales/fi.yml"))
80+
expect(formats[:datetime]).to eq("d.m.Y H:i")
81+
end
82+
end
83+
end

0 commit comments

Comments
 (0)