-
Notifications
You must be signed in to change notification settings - Fork 166
LG-7832: Transliterate name, address, and city for USPS API (w/ FF) #7935
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
Changes from all commits
306b9ad
0f5103b
3b1bb95
ce32726
923e77b
36c5cab
05b579c
2b42b45
e15cb28
63df395
cad7a75
8bbf6bd
8bda24e
fc48a3e
969c2f4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| module UspsInPersonProofing | ||
| class Transliterator | ||
| # This is the default. May not be able to override this in current version. | ||
| REPLACEMENT = '?'.freeze | ||
|
|
||
| # Container to hold the results of transliteration | ||
| TransliterationResult = Struct.new( | ||
| # Was the value different after transliteration? | ||
| :changed?, | ||
| # Original value submtted for transliteration | ||
| :original, | ||
| # Transliterated value | ||
| :transliterated, | ||
| # Characters from the original that could not be transliterated | ||
| :unsupported_chars, | ||
| keyword_init: true, | ||
| ) | ||
NavaTim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Transliterate values for usage in the USPS API. This will additionally strip/reduce | ||
| # excess whitespace and check for special characters that are unsupported by transliteration. | ||
| # Additional validation may be necessary depending on the specific field being transliterated. | ||
| # | ||
| # @param [String,#to_s] value The value to transliterate for USPS | ||
| # @return [TransliterationResult] The transliterated value | ||
| def transliterate(value) | ||
| stripped = value.to_s.gsub(/\s+/, ' ').strip | ||
| transliterated = I18n.transliterate(stripped, locale: :en) | ||
|
|
||
| unsupported_chars = [] | ||
| unless stripped.count(REPLACEMENT) == transliterated.count(REPLACEMENT) | ||
zachmargolis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| transliterated.chars.zip(stripped.chars).each do |val, stripped| | ||
| unsupported_chars.append(stripped) if val == REPLACEMENT && stripped != REPLACEMENT | ||
| end | ||
| end | ||
|
|
||
| # Using struct instead of exception here to reduce likelihood of logging PII | ||
| TransliterationResult.new( | ||
| changed?: value != transliterated, | ||
| original: value, | ||
| transliterated: transliterated, | ||
| unsupported_chars: unsupported_chars, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it make more sense for unsupported_chars to be a boolean? Are we going to refer to the array values to update the characters in the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No, we need to the list of characters to generate the error message required by the story.
No. Monitoring transliteration in-detail is out-of-scope, and the characters could in some cases amount to additional recorded PII. |
||
| ) | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| en: | ||
| i18n: | ||
| transliterate: | ||
| rule: | ||
| # Convert okina to apostrophe | ||
| ʻ: "'" | ||
| # Convert quotation marks | ||
| ’: "'" | ||
| ‘: "'" | ||
| ‛: "'" | ||
| “: '"' | ||
| ‟: '"' | ||
| ”: '"' | ||
| # Convert hyphens | ||
| ‐: '-' | ||
| ‑: '-' | ||
| ‒: '-' | ||
| –: '-' | ||
| —: '-' | ||
| ﹘: '-' | ||
| # Convert number signs | ||
| ﹟: '#' | ||
| #: '#' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is stateless, so we could micro-optimize and save a few allocations by memoizing
or, we could probably just make
transliteratea static method?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is exactly what I tried before, and it caused the mock to be preserved between tests (and therefore the tests failed). I also don't think this micro-optimization has a high payoff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh I just saw that there's a
class << selfaround all of this, no wonder there was test pollution. It's probably time to maybe split this class up and maybe maybe it stateful (exInPersonEnroller.new(user).create_enrollmentvs genericHelper), but that's definitely outside the scope of this PR