i18n_feedback 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c389e87f5f47b445f94f6ea242e803159bb34b2e0847d2ccc87883d05b3a666
4
- data.tar.gz: 62ef3573c3d1a2070b151bbd77848e6f3c2db2c3db2abe532b6c32f0e8afb78f
3
+ metadata.gz: b7fcc717fd98e35452b32dced0c863804d92a13c6c50986004c74ffad64189ca
4
+ data.tar.gz: 00fa165a3e61bd18e773458cc00c7e38d324e3b00387b1eb0b78269738b73369
5
5
  SHA512:
6
- metadata.gz: 67b4232a078ccb30b36de48123023151659301f6036bbac5069ea46db65dabc094cdfff3f3bd6267d63efd43f98b2aaed6c7912d384fdff1da8979f5788c738c
7
- data.tar.gz: 8f575349159537f6ee689d6abea8397ad425bfca692822c1ae93286934fa36bc8edba846b6a65572c5caf74e0fa6ce5ee752d29ad5e0c7df800329992355cae3
6
+ metadata.gz: 8b2dcf16cb6edcec67828d8294cf670205c5b61b591cbeded1eb6605519a0a16b485d644c8b60d7b24d3134088396a22657a653acdeac7dc95b2aeeae64ea1ff
7
+ data.tar.gz: 8a60071cfafc8fd341723f4d92f132caa2b71953de672bb3f508b2923315e698ccdac7431acf5f07724c330cb2a70223abb34d560b65e61aa40350875c754b18
data/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.3.1]
6
+
7
+ - Fix the widget showing raw key markers (e.g. `⟦i18n_feedback.title⟧`) in its own
8
+ popover while suggest mode was on. The key-marking backend was tagging the
9
+ tool's own `i18n_feedback.*` strings; those are not part of the host app's
10
+ translatable copy, so they're now always skipped — the widget never marks or
11
+ offers to edit its own UI.
12
+ - Fix the popover not following the page's language under auto-injection. The
13
+ widget is injected in middleware *after* the controller action, so an
14
+ `around_action { I18n.with_locale(...) }` had already reset `I18n.locale` back
15
+ to the default — the popover (and the saved suggestion's `locale`) came out in
16
+ the wrong language. The locale is now read from the page's rendered
17
+ `<html lang>` attribute and labels resolve under it explicitly.
18
+
5
19
  ## [0.3.0]
6
20
 
7
21
  - Localize the widget's own UI. Every string in the pill and the suggestion
data/README.md CHANGED
@@ -181,7 +181,8 @@ It renders nothing unless the tool is available for the request.
181
181
 
182
182
  The pill and the suggestion popover speak the app's language: every string
183
183
  resolves through Rails I18n under the `i18n_feedback.*` scope and follows the
184
- current `I18n.locale`. Translations ship out of the box for English plus 20 more
184
+ language the page was rendered in (its `<html lang>`, falling back to
185
+ `I18n.locale`). Translations ship out of the box for English plus 20 more
185
186
  languages — Arabic, Bengali, Chinese (Simplified), Dutch, French, German, Hindi,
186
187
  Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Russian, Spanish,
187
188
  Thai, Turkish, Ukrainian, Urdu and Vietnamese — so the tool is already localized
@@ -11,8 +11,11 @@ module I18nFeedback
11
11
  RIGHT = '⟧'
12
12
 
13
13
  # Skip format/lookup namespaces — marking these would corrupt number, date,
14
- # and currency formatting and interpolation strings.
15
- SKIP = /(\A|\.)(number|date|time|datetime|support)(\.|\z)|formats?\z/
14
+ # and currency formatting and interpolation strings. The tool's own
15
+ # `i18n_feedback.*` strings are skipped too: they aren't part of the host
16
+ # app's translatable copy, so the widget must never mark (or offer to edit)
17
+ # its own UI.
18
+ SKIP = /(\A|\.)(number|date|time|datetime|support|i18n_feedback)(\.|\z)|formats?\z/
16
19
 
17
20
  class << self
18
21
  def enabled?
@@ -101,6 +101,24 @@ module I18nFeedback
101
101
  content_type(headers).to_s.include?('text/html')
102
102
  end
103
103
 
104
+ # The locale the page was actually rendered in, read from its `<html lang>`
105
+ # attribute. Auto-injection runs after the controller action, so I18n.locale
106
+ # may already have been reset from whatever the request used — the rendered
107
+ # `lang` is the reliable record of the page's language. Falls back to the
108
+ # ambient locale when the page declares none.
109
+ def page_locale(html)
110
+ lang = html[/<html[^>]*\blang=["']([^"']+)["']/i, 1]
111
+ (lang && normalize_locale(lang)) || I18n.locale
112
+ end
113
+
114
+ # Map an HTML lang value ("es", "pt-BR") to a locale the app actually offers,
115
+ # trying the value as-is, its underscore form, then its language subtag. nil
116
+ # if none match, so the caller can fall back rather than emit an unknown one.
117
+ def normalize_locale(lang)
118
+ available = I18n.available_locales.map(&:to_s)
119
+ [lang, lang.tr('-', '_'), lang.split(/[-_]/).first].uniq.find { |c| available.include?(c) }&.to_sym
120
+ end
121
+
104
122
  def content_type(headers)
105
123
  headers['Content-Type'] || headers['content-type']
106
124
  end
@@ -112,7 +130,7 @@ module I18nFeedback
112
130
 
113
131
  snippet = Widget.snippet(
114
132
  endpoint: I18nFeedback.config.suggestions_endpoint,
115
- locale: I18n.locale,
133
+ locale: page_locale(html),
116
134
  active: marking,
117
135
  nonce: nonce
118
136
  )
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module I18nFeedback
4
- VERSION = '0.3.0'
4
+ VERSION = '0.3.1'
5
5
  end
@@ -38,7 +38,7 @@ module I18nFeedback
38
38
  showPill: I18nFeedback.config.show_pill ? true : false,
39
39
  pillLabel: I18nFeedback.config.pill_label,
40
40
  toggleParam: I18nFeedback.config.toggle_param,
41
- labels: labels,
41
+ labels: labels(locale),
42
42
  rtl: rtl?(locale)
43
43
  }
44
44
  # Escape "</" so a value can't close the <script> block early.
@@ -52,28 +52,36 @@ module I18nFeedback
52
52
  private
53
53
 
54
54
  # Every user-facing string in the widget, resolved through Rails I18n so the
55
- # popover follows the app's current locale. Each lookup carries an English
56
- # default, so the widget stays fully worded even when the host app hasn't
57
- # loaded the gem's locale file or is missing a key for the active locale.
58
- def labels
55
+ # popover matches the locale the page was rendered in. The locale is passed
56
+ # explicitly (not read from I18n.locale) because auto-injection runs in
57
+ # middleware *after* the controller action, by which point an
58
+ # `around_action { I18n.with_locale(...) }` has reset the ambient locale
59
+ # back to the default. Each lookup carries an English default, so the widget
60
+ # stays fully worded even for a locale the gem ships no translation for.
61
+ def labels(locale)
59
62
  {
60
- pill: t(:pill, 'Suggest edits'),
61
- pillActive: t(:pill_active, 'Suggesting — tap to exit (Esc)'),
62
- title: t(:title, 'Suggest a translation fix'),
63
- currentText: t(:current_text, 'Current text'),
64
- suggestedText: t(:suggested_text, 'Suggested text'),
65
- comment: t(:comment, 'Comment'),
66
- commentPlaceholder: t(:comment_placeholder, 'Optional note for the developer'),
67
- priorTitle: t(:prior_title, 'Already suggested (pending)'),
68
- cancel: t(:cancel, 'Cancel'),
69
- save: t(:save, 'Send suggestion'),
70
- errorBlank: t(:error_blank, 'Please enter a suggestion.'),
71
- errorSave: t(:error_save, 'Could not save the suggestion.')
63
+ pill: t(locale, :pill, 'Suggest edits'),
64
+ pillActive: t(locale, :pill_active, 'Suggesting — tap to exit (Esc)'),
65
+ title: t(locale, :title, 'Suggest a translation fix'),
66
+ currentText: t(locale, :current_text, 'Current text'),
67
+ suggestedText: t(locale, :suggested_text, 'Suggested text'),
68
+ comment: t(locale, :comment, 'Comment'),
69
+ commentPlaceholder: t(locale, :comment_placeholder, 'Optional note for the developer'),
70
+ priorTitle: t(locale, :prior_title, 'Already suggested (pending)'),
71
+ cancel: t(locale, :cancel, 'Cancel'),
72
+ save: t(locale, :save, 'Send suggestion'),
73
+ errorBlank: t(locale, :error_blank, 'Please enter a suggestion.'),
74
+ errorSave: t(locale, :error_save, 'Could not save the suggestion.')
72
75
  }
73
76
  end
74
77
 
75
- def t(key, default)
76
- I18n.t(key, scope: :i18n_feedback, default: default)
78
+ # Resolve under the given locale, tolerating one the app doesn't list in
79
+ # available_locales (enforce_available_locales would otherwise raise) — the
80
+ # English default still applies.
81
+ def t(locale, key, default)
82
+ I18n.t(key, scope: :i18n_feedback, locale: locale, default: default)
83
+ rescue I18n::InvalidLocale
84
+ default
77
85
  end
78
86
 
79
87
  def rtl?(locale)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n_feedback
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yaroslav Shmarov