Skip to content

Commit 16c9132

Browse files
authored
Add YAML.safe_load config option (#1668)
* Add specs, better error handling * Added docs, changelog, better messages
1 parent 4339d30 commit 16c9132

File tree

8 files changed

+63
-2
lines changed

8 files changed

+63
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Changes since the last non-beta release.
3333
- Enables progressive page loading and improved performance for server-rendered React components
3434
- Added support for replaying console logs that occur during server rendering of streamed React components. This enables debugging of server-side rendering issues by capturing and displaying console output on the client and on the server output. [PR #1647](https://github.com/shakacode/react_on_rails/pull/1647) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
3535
- Added support for handling errors happening during server rendering of streamed React components. It handles errors that happen during the initial render and errors that happen inside suspense boundaries. [PR #1648](https://github.com/shakacode/react_on_rails/pull/1648) by [AbanoubGhadban](https://github.com/AbanoubGhadban).
36+
- Added support for passing options to `YAML.safe_load` when loading locale files with `config.i18n_yml_safe_load_options`. [PR #1668](https://github.com/shakacode/react_on_rails/pull/1668) by [dzirtusss](https://github.com/dzirtusss).
3637

3738
#### Changed
3839
- Console replay script generation now awaits the render request promise before generating, allowing it to capture console logs from asynchronous operations. This requires using a version of the Node renderer that supports replaying async console logs. [PR #1649](https://github.com/shakacode/react_on_rails/pull/1649) by [AbanoubGhadban](https://github.com/AbanoubGhadban).

docs/guides/configuration.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ ReactOnRails.configure do |config|
213213
# The default format is json
214214
config.i18n_output_format = 'json'
215215

216+
# Possible YAML.safe_load options pass-through for locales
217+
# config.i18n_yml_safe_load_options = { permitted_classes: [Symbol] }
218+
216219
################################################################################
217220
################################################################################
218221
# TEST CONFIGURATION OPTIONS

docs/guides/i18n.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ You can use [Rails internationalization (i18n)](https://guides.rubyonrails.org/i
3131
1) run the rake task to build the translations before running the lint command or
3232
2) to run the tests first.
3333
34+
4. If your locale files (or one of the gems locale files) contains unsafe YAML, you may need to configure `config.i18n_yml_safe_load_options` if you can't fix such yamls properly.
35+
```rb
36+
config.i18n_yml_safe_load_options = { permitted_classes: [Symbol] }
37+
```
38+
3439
By default, the locales are generated as JSON, but you can also generate them as JavaScript with [`react-intl`](https://formatjs.io/docs/getting-started/installation/) support:
3540

3641
1. Specify the i18n output format in `config/initializers/react_on_rails.rb`:

lib/react_on_rails/configuration.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Configuration
5252
:generated_assets_dirs, :generated_assets_dir, :components_subdirectory,
5353
:webpack_generated_files, :rendering_extension, :build_test_command,
5454
:build_production_command, :i18n_dir, :i18n_yml_dir, :i18n_output_format,
55+
:i18n_yml_safe_load_options,
5556
:server_render_method, :random_dom_id, :auto_load_bundle,
5657
:same_bundle_for_client_and_server, :rendering_props_extension,
5758
:make_generated_server_bundle_the_entrypoint,
@@ -69,7 +70,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
6970
rendering_extension: nil, build_test_command: nil,
7071
build_production_command: nil, defer_generated_component_packs: nil,
7172
same_bundle_for_client_and_server: nil,
72-
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil,
73+
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil, i18n_yml_safe_load_options: nil,
7374
random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil,
7475
components_subdirectory: nil, auto_load_bundle: nil, force_load: nil)
7576
self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
@@ -80,6 +81,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
8081
self.i18n_dir = i18n_dir
8182
self.i18n_yml_dir = i18n_yml_dir
8283
self.i18n_output_format = i18n_output_format
84+
self.i18n_yml_safe_load_options = i18n_yml_safe_load_options
8385

8486
self.random_dom_id = random_dom_id
8587
self.prerender = prerender

lib/react_on_rails/locales/base.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,17 @@ def generate_translations
115115
translations = {}
116116
defaults = {}
117117
locale_files.each do |f|
118-
translation = YAML.safe_load(File.open(f))
118+
safe_load_options = ReactOnRails.configuration.i18n_yml_safe_load_options || {}
119+
translation = YAML.safe_load(File.open(f), **safe_load_options)
119120
key = translation.keys[0]
120121
val = flatten(translation[key])
121122
translations = translations.deep_merge(key => val)
122123
defaults = defaults.deep_merge(flatten_defaults(val)) if key == default_locale
124+
rescue Psych::Exception => e
125+
raise ReactOnRails::Error, <<~MSG
126+
Error parsing #{f}: #{e.message}
127+
Consider fixing unsafe YAML or permitting with config.i18n_yml_safe_load_options
128+
MSG
123129
end
124130
[translations.to_json, defaults.to_json]
125131
end
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
de:
2+
:hello: "Hallo welt"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
en:
2+
:hello: "Hello world"
3+
:argument: "I am %{age} years old."
4+
:day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
5+
:blank:
6+
:number: 2
7+
:bool: true
8+
:float: 2.0

spec/react_on_rails/locales_to_js_spec.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,39 @@ module ReactOnRails
9696

9797
it_behaves_like "locale to js"
9898
end
99+
100+
describe "with symbols in yaml" do
101+
let(:locale_dir) { File.expand_path("fixtures/i18n/locales_symbols", __dir__) }
102+
103+
before do
104+
ReactOnRails.configure do |config|
105+
config.i18n_dir = i18n_dir
106+
config.i18n_yml_dir = locale_dir
107+
end
108+
end
109+
110+
after do
111+
ReactOnRails.configure do |config|
112+
config.i18n_dir = nil
113+
config.i18n_yml_dir = nil
114+
config.i18n_yml_safe_load_options = nil
115+
end
116+
end
117+
118+
it "handles unsafe locale loading" do
119+
ReactOnRails.configure do |config|
120+
config.i18n_yml_safe_load_options = { permitted_classes: [Symbol] }
121+
end
122+
123+
expect { described_class.new }.not_to raise_error
124+
end
125+
126+
it "raises error with filename when not permitted" do
127+
expect { described_class.new }.to raise_error(ReactOnRails::Error, <<~MSG)
128+
Error parsing #{locale_dir}/de.yml: Tried to load unspecified class: Symbol
129+
Consider fixing unsafe YAML or permitting with config.i18n_yml_safe_load_options
130+
MSG
131+
end
132+
end
99133
end
100134
end

0 commit comments

Comments
 (0)