Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow language to be specified in the http accept_language header #223

Merged
merged 2 commits into from Apr 17, 2019

Conversation

elrayle
Copy link
Contributor

@elrayle elrayle commented Apr 16, 2019

Adds a few other improvements…

  • allow * as a wildcard for language processing which will prevent filtering of literals by language
  • do not include parameters that do not have a value when building URLs
  • clean template built URL to remove any occurances of ?&, &&, or ending with &

@elrayle elrayle self-assigned this Apr 16, 2019
@elrayle elrayle force-pushed the lang_improvements branch 3 times, most recently from ddbecbf to e34f01e Compare April 16, 2019 21:32
Adds a few other language improvements…
* do not include parameters that do not have a value when building URLs
* clean template built URL to remove any occurances of ?&, &&, or ending with &
* allow * as a wildcard for language processing which will prevent filtering of literals by language (TBD)
@elrayle elrayle force-pushed the lang_improvements branch 3 times, most recently from e87ad68 to 5cd213d Compare April 16, 2019 22:32
@@ -29,7 +29,7 @@ jobs:
project: qa

- samvera/engine_cart_generate:
cache_key: v1-internal-test-app-{{ checksum "qa.gemspec" }}-{{ checksum "spec/test_app_templates/lib/generators/test_app_generator.rb" }}-{{ checksum "lib/generators/qa/install/install_generator.rb" }}-<< parameters.rails_version >>-<< parameters.ruby_version >>
cache_key: v2-internal-test-app-{{ checksum "qa.gemspec" }}-{{ checksum "spec/test_app_templates/lib/generators/test_app_generator.rb" }}-{{ checksum "lib/generators/qa/install/install_generator.rb" }}-<< parameters.rails_version >>-<< parameters.ruby_version >>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required to force Circle CI cache to rebuild and pick up the new linked_data fixtures.

params[:lang]
request_language = request.env['HTTP_ACCEPT_LANGUAGE']
request_language = request_language.scan(/^[a-z]{2}/).first if request_language.present?
params[:lang] || request_language
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extends language specification to honor HTTP_ACCEPT_LANGUAGE if specified.

end

def subauthority
params[:subauthority]
end

def replacement_params
params.reject { |k, _v| ['q', 'vocab', 'controller', 'action', 'subauthority', 'language', 'id'].include?(k) }
params.reject { |k, _v| ['q', 'vocab', 'controller', 'action', 'subauthority', 'lang', 'id'].include?(k) }
Copy link
Contributor Author

@elrayle elrayle Apr 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have always been lang instead of language.

url = url.gsub("{#{key}}", m.simple_value(substitutions[key]))
url = url.gsub("{?#{key}}", m.parameter_value(substitutions[key]))
class << self
# Construct an url from an IriTemplate making identified substitutions
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly an indentation change by adding class << self. This allows the private methods to be specified under the private section.

# In the process of substitution, if a value is missing, you can end up with '?&', '&&', or ending with '&'. These are all removed this method.
def clean(url)
url.gsub(/&&*/, '&').chomp('&').gsub('?&', '?')
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clean method is the only change to this service.

substitutions[action_request_variable(action_config, action)] = action_request
substitutions[action_subauth_variable(action_config)] = action_subauth_variable_value(action_config, subauthority) if subauthority.present?
substitutions[action_subauth_variable(action_config)] = action_subauth_variable_value(action_config, subauthority) if supports_subauthorities?(action_config) && subauthority.present?
substitutions[action_language_variable(action_config)] = language_value(language) if supports_language_parameter?(action_config) && language.present?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lang used to be passed in as part of the substitutions. This was an artifact of lang failing to be removed in the controller. Now that it is properly removed, it has to be passed in by name. This is cleaner as it makes the language processing more visible.

@@ -22,6 +24,7 @@ def literal_has_language_marker?(literal)
def normalize_language(language)
return language if language.blank?
language = [language] unless language.is_a? Array
return nil if language.include?(WILDCARD)
Copy link
Contributor Author

@elrayle elrayle Apr 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By setting the language to nil, there will be no filtering. When an authority configuration sets the language to *, it overrides the site wide default and prevents filtering for that authority.

@@ -37,7 +37,7 @@ def initialize(term_config)
def find(id, language: nil, replacements: {}, subauth: nil, jsonld: false)
raise Qa::InvalidLinkedDataAuthority, "Unable to initialize linked data term sub-authority #{subauth}" unless subauth.nil? || term_subauthority?(subauth)
@language = Qa::LinkedData::LanguageService.preferred_language(user_language: language, authority_language: term_config.term_language)
url = Qa::LinkedData::AuthorityUrlService.build_url(action_config: term_config, action: :term, action_request: id, substitutions: replacements, subauthority: subauth)
url = Qa::LinkedData::AuthorityUrlService.build_url(action_config: term_config, action: :term, action_request: id, substitutions: replacements, subauthority: subauth, language: @language)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After determining the preferred_language, it was then being ignored by passing language to the AuthorityUrlService. Changing this to @language causes the preferred language to be correctly passed instead.

@@ -35,7 +35,7 @@ def search(query, language: nil, replacements: {}, subauth: nil, context: false)
raise Qa::InvalidLinkedDataAuthority, "Unable to initialize linked data search sub-authority #{subauth}" unless subauth.nil? || subauthority?(subauth)
@context = context
@language = language_service.preferred_language(user_language: language, authority_language: search_config.language)
url = authority_service.build_url(action_config: search_config, action: :search, action_request: query, substitutions: replacements, subauthority: subauth)
url = authority_service.build_url(action_config: search_config, action: :search, action_request: query, substitutions: replacements, subauthority: subauth, language: @language)
Copy link
Contributor Author

@elrayle elrayle Apr 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Needs to pass @language which is the preferred langauge, instead of always the user/http language which may be nil if not set.

@@ -12,7 +13,7 @@
url: {
:@context => 'http://www.w3.org/ns/hydra/context.jsonld',
:@type => 'IriTemplate',
template: 'http://localhost/test_default/search?{?subauth}&{?query}&{?param1}&{?param2}',
template: 'http://localhost/test_default/search?{?subauth}&{?query}&{?param1}&{?param2}&{?lang}',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updates to the expected full_config here corresponds to the changes to the lod_full_config.json fixture.

@@ -12,7 +13,7 @@
url: {
:@context => 'http://www.w3.org/ns/hydra/context.jsonld',
:@type => 'IriTemplate',
template: 'http://localhost/test_default/term/{subauth}/{term_id}?{?param1}&{?param2}',
template: 'http://localhost/test_default/term/{subauth}/{term_id}?{?param1}&{?param2}&{?lang}',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updates to the expected full_config here corresponds to the changes to the lod_full_config.json fixture.

@@ -156,7 +172,7 @@
expect(min_config.term_language).to eq nil
end
it 'returns the preferred language for selecting literal values if configured for term' do
expect(full_config.term_language).to eq [:en]
expect(full_config.term_language).to eq [:es]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value was changed in lod_full_config.json fixture to make each language different so we can be sure the language we are checking came for the right place in the config.

it 'returns default language from Qa configuration' do
expect(subject).to match_array [:en]
context 'and site wide default language is set' do
before do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These test changes are covering the various scenarios for setting language, including the new WILDCARD.

@cjcolvar cjcolvar self-requested a review April 17, 2019 16:30
Copy link
Contributor

@carolyncole carolyncole left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just had one question about the logic. Otherwise look solid.

end

def language_value(language)
return nil if language.blank? || !language.is_a?(Array)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elrayle Just checking the logic here. If the language is 'EN' you will return nil, but if the language is ['EN'] you will return 'EN' . Is this correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will return nil when language is... nil, :en, 'en'
Will return :en when language is... ['en']

The reason this is ok is because the parameter is expected to be an array of symbols (line 12)

         # @param language [Array<Symbol>] languages for filtering returned literals (optional) 

The language is normalized to be an Array<Symbol> by the language_service.

I could raise an exception if language is not nil or an Array<Symbol> to make this clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with removing || !language.is_a?(Array) since the param doc says it should be an array.

@carolyncole carolyncole merged commit b866dfc into master Apr 17, 2019
@carolyncole carolyncole deleted the lang_improvements branch April 17, 2019 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants