Skip to content

Commit

Permalink
Add YAML.safe_load config option (#1668)
Browse files Browse the repository at this point in the history
* Add specs, better error handling
* Added docs, changelog, better messages
  • Loading branch information
dzirtusss authored Dec 31, 2024
1 parent 4339d30 commit 16c9132
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Changes since the last non-beta release.
- Enables progressive page loading and improved performance for server-rendered React components
- 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).
- 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).
- 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).

#### Changed
- 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).
Expand Down
3 changes: 3 additions & 0 deletions docs/guides/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ ReactOnRails.configure do |config|
# The default format is json
config.i18n_output_format = 'json'

# Possible YAML.safe_load options pass-through for locales
# config.i18n_yml_safe_load_options = { permitted_classes: [Symbol] }

################################################################################
################################################################################
# TEST CONFIGURATION OPTIONS
Expand Down
5 changes: 5 additions & 0 deletions docs/guides/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ You can use [Rails internationalization (i18n)](https://guides.rubyonrails.org/i
1) run the rake task to build the translations before running the lint command or
2) to run the tests first.
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.
```rb
config.i18n_yml_safe_load_options = { permitted_classes: [Symbol] }
```

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:

1. Specify the i18n output format in `config/initializers/react_on_rails.rb`:
Expand Down
4 changes: 3 additions & 1 deletion lib/react_on_rails/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Configuration
:generated_assets_dirs, :generated_assets_dir, :components_subdirectory,
:webpack_generated_files, :rendering_extension, :build_test_command,
:build_production_command, :i18n_dir, :i18n_yml_dir, :i18n_output_format,
:i18n_yml_safe_load_options,
:server_render_method, :random_dom_id, :auto_load_bundle,
:same_bundle_for_client_and_server, :rendering_props_extension,
:make_generated_server_bundle_the_entrypoint,
Expand All @@ -69,7 +70,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
rendering_extension: nil, build_test_command: nil,
build_production_command: nil, defer_generated_component_packs: nil,
same_bundle_for_client_and_server: nil,
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil,
i18n_dir: nil, i18n_yml_dir: nil, i18n_output_format: nil, i18n_yml_safe_load_options: nil,
random_dom_id: nil, server_render_method: nil, rendering_props_extension: nil,
components_subdirectory: nil, auto_load_bundle: nil, force_load: nil)
self.node_modules_location = node_modules_location.present? ? node_modules_location : Rails.root
Expand All @@ -80,6 +81,7 @@ def initialize(node_modules_location: nil, server_bundle_js_file: nil, prerender
self.i18n_dir = i18n_dir
self.i18n_yml_dir = i18n_yml_dir
self.i18n_output_format = i18n_output_format
self.i18n_yml_safe_load_options = i18n_yml_safe_load_options

self.random_dom_id = random_dom_id
self.prerender = prerender
Expand Down
8 changes: 7 additions & 1 deletion lib/react_on_rails/locales/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,17 @@ def generate_translations
translations = {}
defaults = {}
locale_files.each do |f|
translation = YAML.safe_load(File.open(f))
safe_load_options = ReactOnRails.configuration.i18n_yml_safe_load_options || {}
translation = YAML.safe_load(File.open(f), **safe_load_options)
key = translation.keys[0]
val = flatten(translation[key])
translations = translations.deep_merge(key => val)
defaults = defaults.deep_merge(flatten_defaults(val)) if key == default_locale
rescue Psych::Exception => e
raise ReactOnRails::Error, <<~MSG
Error parsing #{f}: #{e.message}
Consider fixing unsafe YAML or permitting with config.i18n_yml_safe_load_options
MSG
end
[translations.to_json, defaults.to_json]
end
Expand Down
2 changes: 2 additions & 0 deletions spec/react_on_rails/fixtures/i18n/locales_symbols/de.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
de:
:hello: "Hallo welt"
8 changes: 8 additions & 0 deletions spec/react_on_rails/fixtures/i18n/locales_symbols/en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
en:
:hello: "Hello world"
:argument: "I am %{age} years old."
:day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
:blank:
:number: 2
:bool: true
:float: 2.0
34 changes: 34 additions & 0 deletions spec/react_on_rails/locales_to_js_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,39 @@ module ReactOnRails

it_behaves_like "locale to js"
end

describe "with symbols in yaml" do
let(:locale_dir) { File.expand_path("fixtures/i18n/locales_symbols", __dir__) }

before do
ReactOnRails.configure do |config|
config.i18n_dir = i18n_dir
config.i18n_yml_dir = locale_dir
end
end

after do
ReactOnRails.configure do |config|
config.i18n_dir = nil
config.i18n_yml_dir = nil
config.i18n_yml_safe_load_options = nil
end
end

it "handles unsafe locale loading" do
ReactOnRails.configure do |config|
config.i18n_yml_safe_load_options = { permitted_classes: [Symbol] }
end

expect { described_class.new }.not_to raise_error
end

it "raises error with filename when not permitted" do
expect { described_class.new }.to raise_error(ReactOnRails::Error, <<~MSG)
Error parsing #{locale_dir}/de.yml: Tried to load unspecified class: Symbol
Consider fixing unsafe YAML or permitting with config.i18n_yml_safe_load_options
MSG
end
end
end
end

0 comments on commit 16c9132

Please sign in to comment.