i18n_feedback 0.2.2 → 0.3.0
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 +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +43 -0
- data/app/assets/i18n_feedback/widget.js +44 -12
- data/config/locales/i18n_feedback.ar.yml +14 -0
- data/config/locales/i18n_feedback.bn.yml +14 -0
- data/config/locales/i18n_feedback.de.yml +14 -0
- data/config/locales/i18n_feedback.en.yml +14 -0
- data/config/locales/i18n_feedback.es.yml +14 -0
- data/config/locales/i18n_feedback.fr.yml +14 -0
- data/config/locales/i18n_feedback.hi.yml +14 -0
- data/config/locales/i18n_feedback.id.yml +14 -0
- data/config/locales/i18n_feedback.it.yml +14 -0
- data/config/locales/i18n_feedback.ja.yml +14 -0
- data/config/locales/i18n_feedback.ko.yml +14 -0
- data/config/locales/i18n_feedback.nl.yml +14 -0
- data/config/locales/i18n_feedback.pl.yml +14 -0
- data/config/locales/i18n_feedback.pt.yml +14 -0
- data/config/locales/i18n_feedback.ru.yml +14 -0
- data/config/locales/i18n_feedback.th.yml +14 -0
- data/config/locales/i18n_feedback.tr.yml +14 -0
- data/config/locales/i18n_feedback.uk.yml +14 -0
- data/config/locales/i18n_feedback.ur.yml +14 -0
- data/config/locales/i18n_feedback.vi.yml +14 -0
- data/config/locales/i18n_feedback.zh-CN.yml +14 -0
- data/lib/i18n_feedback/configuration.rb +3 -2
- data/lib/i18n_feedback/version.rb +1 -1
- data/lib/i18n_feedback/widget.rb +38 -1
- metadata +22 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c389e87f5f47b445f94f6ea242e803159bb34b2e0847d2ccc87883d05b3a666
|
|
4
|
+
data.tar.gz: 62ef3573c3d1a2070b151bbd77848e6f3c2db2c3db2abe532b6c32f0e8afb78f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67b4232a078ccb30b36de48123023151659301f6036bbac5069ea46db65dabc094cdfff3f3bd6267d63efd43f98b2aaed6c7912d384fdff1da8979f5788c738c
|
|
7
|
+
data.tar.gz: 8f575349159537f6ee689d6abea8397ad425bfca692822c1ae93286934fa36bc8edba846b6a65572c5caf74e0fa6ce5ee752d29ad5e0c7df800329992355cae3
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.3.0]
|
|
6
|
+
|
|
7
|
+
- Localize the widget's own UI. Every string in the pill and the suggestion
|
|
8
|
+
popover now resolves through Rails I18n under the `i18n_feedback.*` scope and
|
|
9
|
+
follows the app's current `I18n.locale`, so the tool speaks the same language as
|
|
10
|
+
the app being proofread. Any key a host hasn't translated falls back to English
|
|
11
|
+
— so nothing goes blank in a locale you haven't fully covered. Override any
|
|
12
|
+
string by defining the matching key in your own locale files.
|
|
13
|
+
- Ship translations out of the box for 20 languages in addition to English:
|
|
14
|
+
Arabic, Bengali, Chinese (Simplified), Dutch, French, German, Hindi, Indonesian,
|
|
15
|
+
Italian, Japanese, Korean, Polish, Portuguese, Russian, Spanish, Thai, Turkish,
|
|
16
|
+
Ukrainian, Urdu and Vietnamese.
|
|
17
|
+
- Render the popover right-to-left for RTL locales (Arabic, Urdu, and other RTL
|
|
18
|
+
scripts), detected from the active locale's language subtag. The i18n key stays
|
|
19
|
+
left-to-right, since it's a code identifier rather than prose.
|
|
20
|
+
- `config.pill_label` now defaults to `nil`, meaning "use the localized default".
|
|
21
|
+
Setting it to a string still overrides the pill text as before.
|
|
22
|
+
- The widget now follows the operating system's light/dark/system appearance via
|
|
23
|
+
`prefers-color-scheme`. The pill and popover render with a dark surface when the
|
|
24
|
+
reviewer's system is in dark mode, with no configuration required.
|
|
25
|
+
|
|
5
26
|
## [0.2.2]
|
|
6
27
|
|
|
7
28
|
- Fix suggest mode desyncing under a nonce-based CSP on Turbo visits. The runtime
|
data/README.md
CHANGED
|
@@ -177,6 +177,49 @@ Set `config.auto_inject = false` and drop the helper at the end of your layout:
|
|
|
177
177
|
|
|
178
178
|
It renders nothing unless the tool is available for the request.
|
|
179
179
|
|
|
180
|
+
### Localizing the widget UI
|
|
181
|
+
|
|
182
|
+
The pill and the suggestion popover speak the app's language: every string
|
|
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
|
|
185
|
+
languages — Arabic, Bengali, Chinese (Simplified), Dutch, French, German, Hindi,
|
|
186
|
+
Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Russian, Spanish,
|
|
187
|
+
Thai, Turkish, Ukrainian, Urdu and Vietnamese — so the tool is already localized
|
|
188
|
+
for most apps. RTL locales (Arabic, Urdu, …) render the popover right-to-left
|
|
189
|
+
automatically.
|
|
190
|
+
|
|
191
|
+
Any key you haven't translated falls back to English, so a partially translated
|
|
192
|
+
locale never leaves a control blank. To add a language, or reword the bundled
|
|
193
|
+
copy, define the keys in your own locale files (yours win over the gem's):
|
|
194
|
+
|
|
195
|
+
```yaml
|
|
196
|
+
# config/locales/fr.yml
|
|
197
|
+
fr:
|
|
198
|
+
i18n_feedback:
|
|
199
|
+
pill: "Proposer des corrections"
|
|
200
|
+
pill_active: "En cours — appuyez pour quitter (Échap)"
|
|
201
|
+
title: "Proposer une correction de traduction"
|
|
202
|
+
current_text: "Texte actuel"
|
|
203
|
+
suggested_text: "Texte proposé"
|
|
204
|
+
comment: "Commentaire"
|
|
205
|
+
comment_placeholder: "Note facultative pour le développeur"
|
|
206
|
+
prior_title: "Déjà proposé (en attente)"
|
|
207
|
+
cancel: "Annuler"
|
|
208
|
+
save: "Envoyer la suggestion"
|
|
209
|
+
error_blank: "Veuillez saisir une suggestion."
|
|
210
|
+
error_save: "Impossible d'enregistrer la suggestion."
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
`config.pill_label` still overrides the pill text with a fixed string if you set
|
|
214
|
+
it; leave it `nil` (the default) to use the localized `i18n_feedback.pill` key.
|
|
215
|
+
|
|
216
|
+
### Light / dark / system appearance
|
|
217
|
+
|
|
218
|
+
The widget follows the reviewer's operating-system appearance via
|
|
219
|
+
`prefers-color-scheme` — no configuration needed. The pill and popover render on a
|
|
220
|
+
dark surface when the system is in dark mode and a light surface otherwise; the
|
|
221
|
+
blue accent stays the same in both.
|
|
222
|
+
|
|
180
223
|
## Reviewing suggestions
|
|
181
224
|
|
|
182
225
|
Suggestions are ordinary records:
|
|
@@ -158,13 +158,19 @@
|
|
|
158
158
|
var pill = document.createElement("button");
|
|
159
159
|
pill.type = "button";
|
|
160
160
|
pill.className = "i18nf-pill" + (config.active ? " i18nf-pill-on" : "");
|
|
161
|
-
pill.textContent = config.active ? "✓ Suggesting — tap to exit (Esc)" : "✎ " + labelText();
|
|
161
|
+
pill.textContent = config.active ? "✓ " + t("pillActive", "Suggesting — tap to exit (Esc)") : "✎ " + labelText();
|
|
162
162
|
pill.addEventListener("click", toggle);
|
|
163
163
|
document.body.appendChild(pill);
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
function labelText() {
|
|
167
|
-
return
|
|
167
|
+
return config.pillLabel || t("pill", "Suggest edits");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Resolve a server-translated label, falling back to English if the config
|
|
171
|
+
// predates the labels payload (e.g. a cached page from an older gem version).
|
|
172
|
+
function t(name, fallback) {
|
|
173
|
+
return (config.labels && config.labels[name]) || fallback;
|
|
168
174
|
}
|
|
169
175
|
|
|
170
176
|
// --- popover --------------------------------------------------------------
|
|
@@ -178,18 +184,21 @@
|
|
|
178
184
|
});
|
|
179
185
|
|
|
180
186
|
var panel = el("div", "i18nf-panel");
|
|
187
|
+
// Mirror the popover for right-to-left locales (Arabic, Urdu, …). The i18n
|
|
188
|
+
// key stays LTR — it's a code identifier, not prose (see heading()).
|
|
189
|
+
panel.dir = config.rtl ? "rtl" : "ltr";
|
|
181
190
|
panel.appendChild(heading(key));
|
|
182
191
|
|
|
183
192
|
priorNode = el("div");
|
|
184
193
|
panel.appendChild(priorNode);
|
|
185
194
|
|
|
186
|
-
panel.appendChild(field("Current text", readonly(currentValue)));
|
|
195
|
+
panel.appendChild(field(t("currentText", "Current text"), readonly(currentValue)));
|
|
187
196
|
|
|
188
197
|
proposedInput = textarea(currentValue);
|
|
189
|
-
panel.appendChild(field("Suggested text", proposedInput));
|
|
198
|
+
panel.appendChild(field(t("suggestedText", "Suggested text"), proposedInput));
|
|
190
199
|
|
|
191
|
-
commentInput = input("Optional note for the developer");
|
|
192
|
-
panel.appendChild(field("Comment", commentInput));
|
|
200
|
+
commentInput = input(t("commentPlaceholder", "Optional note for the developer"));
|
|
201
|
+
panel.appendChild(field(t("comment", "Comment"), commentInput));
|
|
193
202
|
|
|
194
203
|
errorNode = el("p", "i18nf-error");
|
|
195
204
|
errorNode.style.display = "none";
|
|
@@ -229,7 +238,7 @@
|
|
|
229
238
|
|
|
230
239
|
var box = el("div", "i18nf-prior");
|
|
231
240
|
var title = el("p", "i18nf-prior-title");
|
|
232
|
-
title.textContent = "Already suggested (pending)";
|
|
241
|
+
title.textContent = t("priorTitle", "Already suggested (pending)");
|
|
233
242
|
box.appendChild(title);
|
|
234
243
|
|
|
235
244
|
var list = el("ul", "i18nf-prior-list");
|
|
@@ -250,12 +259,12 @@
|
|
|
250
259
|
|
|
251
260
|
var cancel = el("button", "i18nf-btn i18nf-btn-ghost");
|
|
252
261
|
cancel.type = "button";
|
|
253
|
-
cancel.textContent = "Cancel";
|
|
262
|
+
cancel.textContent = t("cancel", "Cancel");
|
|
254
263
|
cancel.addEventListener("click", close);
|
|
255
264
|
|
|
256
265
|
saveButton = el("button", "i18nf-btn i18nf-btn-primary");
|
|
257
266
|
saveButton.type = "button";
|
|
258
|
-
saveButton.textContent = "Send suggestion";
|
|
267
|
+
saveButton.textContent = t("save", "Send suggestion");
|
|
259
268
|
saveButton.addEventListener("click", function () {
|
|
260
269
|
submit(key, currentValue);
|
|
261
270
|
});
|
|
@@ -268,7 +277,7 @@
|
|
|
268
277
|
function submit(key, currentValue) {
|
|
269
278
|
var proposed = proposedInput.value.trim();
|
|
270
279
|
if (!proposed) {
|
|
271
|
-
showError("Please enter a suggestion.");
|
|
280
|
+
showError(t("errorBlank", "Please enter a suggestion."));
|
|
272
281
|
return;
|
|
273
282
|
}
|
|
274
283
|
|
|
@@ -297,7 +306,7 @@
|
|
|
297
306
|
close();
|
|
298
307
|
} else {
|
|
299
308
|
saveButton.disabled = false;
|
|
300
|
-
showError("Could not save the suggestion.");
|
|
309
|
+
showError(t("errorSave", "Could not save the suggestion."));
|
|
301
310
|
}
|
|
302
311
|
})
|
|
303
312
|
.catch(function () {
|
|
@@ -316,8 +325,9 @@
|
|
|
316
325
|
function heading(key) {
|
|
317
326
|
var wrapper = el("div", "i18nf-heading");
|
|
318
327
|
var title = el("p", "i18nf-title");
|
|
319
|
-
title.textContent = "Suggest a translation fix";
|
|
328
|
+
title.textContent = t("title", "Suggest a translation fix");
|
|
320
329
|
var code = el("code", "i18nf-key");
|
|
330
|
+
code.dir = "ltr"; // the key is a code path, never RTL prose
|
|
321
331
|
code.textContent = key;
|
|
322
332
|
wrapper.appendChild(title);
|
|
323
333
|
wrapper.appendChild(code);
|
|
@@ -405,6 +415,28 @@
|
|
|
405
415
|
".i18nf-btn-ghost { background: transparent; color: #111; }",
|
|
406
416
|
".i18nf-btn-primary { background: #2563eb; color: #fff; }",
|
|
407
417
|
".i18nf-btn[disabled] { opacity: .6; cursor: default; }",
|
|
418
|
+
|
|
419
|
+
// Follow the OS light/dark/system setting via prefers-color-scheme, so the
|
|
420
|
+
// widget matches whatever the reviewer's system is set to without any extra
|
|
421
|
+
// configuration. Only the surfaces that carry their own background/color
|
|
422
|
+
// above are overridden here — the blue accents stay the same in both themes.
|
|
423
|
+
"@media (prefers-color-scheme: dark) {",
|
|
424
|
+
" .i18nf-pill { background: #1f1f23; color: #f4f4f5; border-color: rgba(255,255,255,.18);",
|
|
425
|
+
" box-shadow: 0 4px 14px rgba(0,0,0,.5); }",
|
|
426
|
+
" .i18nf-pill-on { background: #2563eb; color: #fff; border-color: #2563eb; }",
|
|
427
|
+
" .i18nf-overlay { background: rgba(0,0,0,.65); }",
|
|
428
|
+
" .i18nf-panel { background: #1f1f23; color: #f4f4f5;",
|
|
429
|
+
" box-shadow: 0 20px 60px rgba(0,0,0,.7); }",
|
|
430
|
+
" .i18nf-key { color: #a1a1aa; }",
|
|
431
|
+
" .i18nf-label { color: #a1a1aa; }",
|
|
432
|
+
" .i18nf-readonly { background: #2a2a30; }",
|
|
433
|
+
" .i18nf-input { background: #2a2a30; color: #f4f4f5; border-color: #3f3f46; }",
|
|
434
|
+
" .i18nf-input::placeholder { color: #71717a; }",
|
|
435
|
+
" .i18nf-prior { background: #2a2a30; }",
|
|
436
|
+
" .i18nf-prior-title { color: #d4d4d8; }",
|
|
437
|
+
" .i18nf-error { color: #f87171; }",
|
|
438
|
+
" .i18nf-btn-ghost { color: #f4f4f5; }",
|
|
439
|
+
"}",
|
|
408
440
|
].join("\n");
|
|
409
441
|
document.head.appendChild(style);
|
|
410
442
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ar:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "اقترح تعديلات"
|
|
4
|
+
pill_active: "وضع الاقتراح — اضغط للخروج (Esc)"
|
|
5
|
+
title: "اقترح تصحيحًا للترجمة"
|
|
6
|
+
current_text: "النص الحالي"
|
|
7
|
+
suggested_text: "النص المقترح"
|
|
8
|
+
comment: "تعليق"
|
|
9
|
+
comment_placeholder: "ملاحظة اختيارية للمطور"
|
|
10
|
+
prior_title: "تم اقتراحه مسبقًا (قيد الانتظار)"
|
|
11
|
+
cancel: "إلغاء"
|
|
12
|
+
save: "إرسال الاقتراح"
|
|
13
|
+
error_blank: "يرجى إدخال اقتراح."
|
|
14
|
+
error_save: "تعذّر حفظ الاقتراح."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
bn:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "সম্পাদনা প্রস্তাব করুন"
|
|
4
|
+
pill_active: "প্রস্তাব চলছে — বের হতে ট্যাপ করুন (Esc)"
|
|
5
|
+
title: "অনুবাদ সংশোধন প্রস্তাব করুন"
|
|
6
|
+
current_text: "বর্তমান লেখা"
|
|
7
|
+
suggested_text: "প্রস্তাবিত লেখা"
|
|
8
|
+
comment: "মন্তব্য"
|
|
9
|
+
comment_placeholder: "ডেভেলপারের জন্য ঐচ্ছিক নোট"
|
|
10
|
+
prior_title: "ইতিমধ্যে প্রস্তাবিত (অপেক্ষমাণ)"
|
|
11
|
+
cancel: "বাতিল"
|
|
12
|
+
save: "প্রস্তাব পাঠান"
|
|
13
|
+
error_blank: "অনুগ্রহ করে একটি প্রস্তাব লিখুন।"
|
|
14
|
+
error_save: "প্রস্তাব সংরক্ষণ করা যায়নি।"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
de:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Änderungen vorschlagen"
|
|
4
|
+
pill_active: "Vorschlagsmodus — zum Beenden tippen (Esc)"
|
|
5
|
+
title: "Übersetzungskorrektur vorschlagen"
|
|
6
|
+
current_text: "Aktueller Text"
|
|
7
|
+
suggested_text: "Vorgeschlagener Text"
|
|
8
|
+
comment: "Kommentar"
|
|
9
|
+
comment_placeholder: "Optionale Notiz für die Entwicklung"
|
|
10
|
+
prior_title: "Bereits vorgeschlagen (ausstehend)"
|
|
11
|
+
cancel: "Abbrechen"
|
|
12
|
+
save: "Vorschlag senden"
|
|
13
|
+
error_blank: "Bitte gib einen Vorschlag ein."
|
|
14
|
+
error_save: "Der Vorschlag konnte nicht gespeichert werden."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
en:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Suggest edits"
|
|
4
|
+
pill_active: "Suggesting — tap to exit (Esc)"
|
|
5
|
+
title: "Suggest a translation fix"
|
|
6
|
+
current_text: "Current text"
|
|
7
|
+
suggested_text: "Suggested text"
|
|
8
|
+
comment: "Comment"
|
|
9
|
+
comment_placeholder: "Optional note for the developer"
|
|
10
|
+
prior_title: "Already suggested (pending)"
|
|
11
|
+
cancel: "Cancel"
|
|
12
|
+
save: "Send suggestion"
|
|
13
|
+
error_blank: "Please enter a suggestion."
|
|
14
|
+
error_save: "Could not save the suggestion."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
es:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Sugerir cambios"
|
|
4
|
+
pill_active: "Sugiriendo — toca para salir (Esc)"
|
|
5
|
+
title: "Sugerir una corrección de traducción"
|
|
6
|
+
current_text: "Texto actual"
|
|
7
|
+
suggested_text: "Texto sugerido"
|
|
8
|
+
comment: "Comentario"
|
|
9
|
+
comment_placeholder: "Nota opcional para el desarrollador"
|
|
10
|
+
prior_title: "Ya sugerido (pendiente)"
|
|
11
|
+
cancel: "Cancelar"
|
|
12
|
+
save: "Enviar sugerencia"
|
|
13
|
+
error_blank: "Introduce una sugerencia."
|
|
14
|
+
error_save: "No se pudo guardar la sugerencia."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
fr:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Proposer des corrections"
|
|
4
|
+
pill_active: "En cours — appuyez pour quitter (Échap)"
|
|
5
|
+
title: "Proposer une correction de traduction"
|
|
6
|
+
current_text: "Texte actuel"
|
|
7
|
+
suggested_text: "Texte proposé"
|
|
8
|
+
comment: "Commentaire"
|
|
9
|
+
comment_placeholder: "Note facultative pour le développeur"
|
|
10
|
+
prior_title: "Déjà proposé (en attente)"
|
|
11
|
+
cancel: "Annuler"
|
|
12
|
+
save: "Envoyer la suggestion"
|
|
13
|
+
error_blank: "Veuillez saisir une suggestion."
|
|
14
|
+
error_save: "Impossible d'enregistrer la suggestion."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
hi:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "बदलाव सुझाएँ"
|
|
4
|
+
pill_active: "सुझाव मोड — बाहर निकलने के लिए टैप करें (Esc)"
|
|
5
|
+
title: "अनुवाद सुधार सुझाएँ"
|
|
6
|
+
current_text: "वर्तमान टेक्स्ट"
|
|
7
|
+
suggested_text: "सुझाया गया टेक्स्ट"
|
|
8
|
+
comment: "टिप्पणी"
|
|
9
|
+
comment_placeholder: "डेवलपर के लिए वैकल्पिक टिप्पणी"
|
|
10
|
+
prior_title: "पहले से सुझाया गया (लंबित)"
|
|
11
|
+
cancel: "रद्द करें"
|
|
12
|
+
save: "सुझाव भेजें"
|
|
13
|
+
error_blank: "कृपया एक सुझाव दर्ज करें।"
|
|
14
|
+
error_save: "सुझाव सहेजा नहीं जा सका।"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
id:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Sarankan perubahan"
|
|
4
|
+
pill_active: "Menyarankan — ketuk untuk keluar (Esc)"
|
|
5
|
+
title: "Sarankan perbaikan terjemahan"
|
|
6
|
+
current_text: "Teks saat ini"
|
|
7
|
+
suggested_text: "Teks yang disarankan"
|
|
8
|
+
comment: "Komentar"
|
|
9
|
+
comment_placeholder: "Catatan opsional untuk pengembang"
|
|
10
|
+
prior_title: "Sudah disarankan (menunggu)"
|
|
11
|
+
cancel: "Batal"
|
|
12
|
+
save: "Kirim saran"
|
|
13
|
+
error_blank: "Silakan masukkan saran."
|
|
14
|
+
error_save: "Tidak dapat menyimpan saran."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
it:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Suggerisci modifiche"
|
|
4
|
+
pill_active: "Suggerimento — tocca per uscire (Esc)"
|
|
5
|
+
title: "Suggerisci una correzione di traduzione"
|
|
6
|
+
current_text: "Testo attuale"
|
|
7
|
+
suggested_text: "Testo suggerito"
|
|
8
|
+
comment: "Commento"
|
|
9
|
+
comment_placeholder: "Nota facoltativa per lo sviluppatore"
|
|
10
|
+
prior_title: "Già suggerito (in sospeso)"
|
|
11
|
+
cancel: "Annulla"
|
|
12
|
+
save: "Invia suggerimento"
|
|
13
|
+
error_blank: "Inserisci un suggerimento."
|
|
14
|
+
error_save: "Impossibile salvare il suggerimento."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ja:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "修正を提案"
|
|
4
|
+
pill_active: "提案中 — タップで終了(Esc)"
|
|
5
|
+
title: "翻訳の修正を提案"
|
|
6
|
+
current_text: "現在のテキスト"
|
|
7
|
+
suggested_text: "提案するテキスト"
|
|
8
|
+
comment: "コメント"
|
|
9
|
+
comment_placeholder: "開発者への任意のメモ"
|
|
10
|
+
prior_title: "提案済み(保留中)"
|
|
11
|
+
cancel: "キャンセル"
|
|
12
|
+
save: "提案を送信"
|
|
13
|
+
error_blank: "提案を入力してください。"
|
|
14
|
+
error_save: "提案を保存できませんでした。"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ko:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "수정 제안"
|
|
4
|
+
pill_active: "제안 중 — 종료하려면 탭하세요 (Esc)"
|
|
5
|
+
title: "번역 수정 제안"
|
|
6
|
+
current_text: "현재 텍스트"
|
|
7
|
+
suggested_text: "제안 텍스트"
|
|
8
|
+
comment: "의견"
|
|
9
|
+
comment_placeholder: "개발자를 위한 선택 메모"
|
|
10
|
+
prior_title: "이미 제안됨 (대기 중)"
|
|
11
|
+
cancel: "취소"
|
|
12
|
+
save: "제안 보내기"
|
|
13
|
+
error_blank: "제안을 입력하세요."
|
|
14
|
+
error_save: "제안을 저장할 수 없습니다."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
nl:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Wijzigingen voorstellen"
|
|
4
|
+
pill_active: "Aan het voorstellen — tik om te sluiten (Esc)"
|
|
5
|
+
title: "Een vertaalcorrectie voorstellen"
|
|
6
|
+
current_text: "Huidige tekst"
|
|
7
|
+
suggested_text: "Voorgestelde tekst"
|
|
8
|
+
comment: "Opmerking"
|
|
9
|
+
comment_placeholder: "Optionele notitie voor de ontwikkelaar"
|
|
10
|
+
prior_title: "Al voorgesteld (in behandeling)"
|
|
11
|
+
cancel: "Annuleren"
|
|
12
|
+
save: "Suggestie versturen"
|
|
13
|
+
error_blank: "Voer een suggestie in."
|
|
14
|
+
error_save: "Kan de suggestie niet opslaan."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
pl:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Zaproponuj zmiany"
|
|
4
|
+
pill_active: "Tryb sugestii — dotknij, aby wyjść (Esc)"
|
|
5
|
+
title: "Zaproponuj poprawkę tłumaczenia"
|
|
6
|
+
current_text: "Bieżący tekst"
|
|
7
|
+
suggested_text: "Proponowany tekst"
|
|
8
|
+
comment: "Komentarz"
|
|
9
|
+
comment_placeholder: "Opcjonalna notatka dla programisty"
|
|
10
|
+
prior_title: "Już zaproponowano (oczekujące)"
|
|
11
|
+
cancel: "Anuluj"
|
|
12
|
+
save: "Wyślij sugestię"
|
|
13
|
+
error_blank: "Wprowadź sugestię."
|
|
14
|
+
error_save: "Nie udało się zapisać sugestii."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
pt:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Sugerir edições"
|
|
4
|
+
pill_active: "Sugerindo — toque para sair (Esc)"
|
|
5
|
+
title: "Sugerir uma correção de tradução"
|
|
6
|
+
current_text: "Texto atual"
|
|
7
|
+
suggested_text: "Texto sugerido"
|
|
8
|
+
comment: "Comentário"
|
|
9
|
+
comment_placeholder: "Nota opcional para o desenvolvedor"
|
|
10
|
+
prior_title: "Já sugerido (pendente)"
|
|
11
|
+
cancel: "Cancelar"
|
|
12
|
+
save: "Enviar sugestão"
|
|
13
|
+
error_blank: "Insira uma sugestão."
|
|
14
|
+
error_save: "Não foi possível salvar a sugestão."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ru:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Предложить правки"
|
|
4
|
+
pill_active: "Режим предложений — нажмите, чтобы выйти (Esc)"
|
|
5
|
+
title: "Предложить исправление перевода"
|
|
6
|
+
current_text: "Текущий текст"
|
|
7
|
+
suggested_text: "Предлагаемый текст"
|
|
8
|
+
comment: "Комментарий"
|
|
9
|
+
comment_placeholder: "Необязательная заметка для разработчика"
|
|
10
|
+
prior_title: "Уже предложено (в ожидании)"
|
|
11
|
+
cancel: "Отмена"
|
|
12
|
+
save: "Отправить предложение"
|
|
13
|
+
error_blank: "Введите предложение."
|
|
14
|
+
error_save: "Не удалось сохранить предложение."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
th:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "แนะนำการแก้ไข"
|
|
4
|
+
pill_active: "กำลังแนะนำ — แตะเพื่อออก (Esc)"
|
|
5
|
+
title: "แนะนำการแก้ไขคำแปล"
|
|
6
|
+
current_text: "ข้อความปัจจุบัน"
|
|
7
|
+
suggested_text: "ข้อความที่แนะนำ"
|
|
8
|
+
comment: "ความคิดเห็น"
|
|
9
|
+
comment_placeholder: "หมายเหตุเพิ่มเติมสำหรับนักพัฒนา"
|
|
10
|
+
prior_title: "แนะนำไปแล้ว (รอดำเนินการ)"
|
|
11
|
+
cancel: "ยกเลิก"
|
|
12
|
+
save: "ส่งคำแนะนำ"
|
|
13
|
+
error_blank: "โปรดป้อนคำแนะนำ"
|
|
14
|
+
error_save: "ไม่สามารถบันทึกคำแนะนำได้"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
tr:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Düzenleme öner"
|
|
4
|
+
pill_active: "Öneri modu — çıkmak için dokun (Esc)"
|
|
5
|
+
title: "Çeviri düzeltmesi öner"
|
|
6
|
+
current_text: "Mevcut metin"
|
|
7
|
+
suggested_text: "Önerilen metin"
|
|
8
|
+
comment: "Yorum"
|
|
9
|
+
comment_placeholder: "Geliştirici için isteğe bağlı not"
|
|
10
|
+
prior_title: "Zaten önerildi (beklemede)"
|
|
11
|
+
cancel: "İptal"
|
|
12
|
+
save: "Öneriyi gönder"
|
|
13
|
+
error_blank: "Lütfen bir öneri girin."
|
|
14
|
+
error_save: "Öneri kaydedilemedi."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
uk:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Запропонувати зміни"
|
|
4
|
+
pill_active: "Режим пропозицій — торкніться, щоб вийти (Esc)"
|
|
5
|
+
title: "Запропонувати виправлення перекладу"
|
|
6
|
+
current_text: "Поточний текст"
|
|
7
|
+
suggested_text: "Запропонований текст"
|
|
8
|
+
comment: "Коментар"
|
|
9
|
+
comment_placeholder: "Необов’язкова примітка для розробника"
|
|
10
|
+
prior_title: "Уже запропоновано (очікує)"
|
|
11
|
+
cancel: "Скасувати"
|
|
12
|
+
save: "Надіслати пропозицію"
|
|
13
|
+
error_blank: "Будь ласка, введіть пропозицію."
|
|
14
|
+
error_save: "Не вдалося зберегти пропозицію."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ur:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "ترامیم تجویز کریں"
|
|
4
|
+
pill_active: "تجویز موڈ — باہر نکلنے کے لیے تھپتھپائیں (Esc)"
|
|
5
|
+
title: "ترجمے کی اصلاح تجویز کریں"
|
|
6
|
+
current_text: "موجودہ متن"
|
|
7
|
+
suggested_text: "تجویز کردہ متن"
|
|
8
|
+
comment: "تبصرہ"
|
|
9
|
+
comment_placeholder: "ڈویلپر کے لیے اختیاری نوٹ"
|
|
10
|
+
prior_title: "پہلے ہی تجویز کیا جا چکا (زیر التوا)"
|
|
11
|
+
cancel: "منسوخ کریں"
|
|
12
|
+
save: "تجویز بھیجیں"
|
|
13
|
+
error_blank: "براہ کرم ایک تجویز درج کریں۔"
|
|
14
|
+
error_save: "تجویز محفوظ نہیں ہو سکی۔"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
vi:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "Đề xuất chỉnh sửa"
|
|
4
|
+
pill_active: "Đang đề xuất — chạm để thoát (Esc)"
|
|
5
|
+
title: "Đề xuất sửa bản dịch"
|
|
6
|
+
current_text: "Văn bản hiện tại"
|
|
7
|
+
suggested_text: "Văn bản đề xuất"
|
|
8
|
+
comment: "Nhận xét"
|
|
9
|
+
comment_placeholder: "Ghi chú tùy chọn cho nhà phát triển"
|
|
10
|
+
prior_title: "Đã đề xuất (đang chờ)"
|
|
11
|
+
cancel: "Hủy"
|
|
12
|
+
save: "Gửi đề xuất"
|
|
13
|
+
error_blank: "Vui lòng nhập một đề xuất."
|
|
14
|
+
error_save: "Không thể lưu đề xuất."
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
zh-CN:
|
|
2
|
+
i18n_feedback:
|
|
3
|
+
pill: "建议修改"
|
|
4
|
+
pill_active: "建议中 — 点击退出(Esc)"
|
|
5
|
+
title: "建议翻译修正"
|
|
6
|
+
current_text: "当前文本"
|
|
7
|
+
suggested_text: "建议文本"
|
|
8
|
+
comment: "备注"
|
|
9
|
+
comment_placeholder: "给开发者的可选备注"
|
|
10
|
+
prior_title: "已提交建议(待处理)"
|
|
11
|
+
cancel: "取消"
|
|
12
|
+
save: "发送建议"
|
|
13
|
+
error_blank: "请输入建议。"
|
|
14
|
+
error_save: "无法保存建议。"
|
|
@@ -38,7 +38,8 @@ module I18nFeedback
|
|
|
38
38
|
# from your own link instead (see #toggle_param).
|
|
39
39
|
attr_accessor :show_pill
|
|
40
40
|
|
|
41
|
-
# Text on the floating toggle pill.
|
|
41
|
+
# Text on the floating toggle pill. Leave nil to use the localized default
|
|
42
|
+
# ("Suggest edits", translated via the `i18n_feedback.pill` I18n key).
|
|
42
43
|
attr_accessor :pill_label
|
|
43
44
|
|
|
44
45
|
# The query-string parameter that turns suggest mode on/off, so a host can
|
|
@@ -56,7 +57,7 @@ module I18nFeedback
|
|
|
56
57
|
@auto_inject = true
|
|
57
58
|
@mount_path = '/i18n_feedback'
|
|
58
59
|
@show_pill = true
|
|
59
|
-
@pill_label =
|
|
60
|
+
@pill_label = nil
|
|
60
61
|
@toggle_param = 'i18n_feedback'
|
|
61
62
|
end
|
|
62
63
|
|
data/lib/i18n_feedback/widget.rb
CHANGED
|
@@ -11,6 +11,10 @@ module I18nFeedback
|
|
|
11
11
|
module Widget
|
|
12
12
|
SOURCE = File.expand_path('../../app/assets/i18n_feedback/widget.js', __dir__)
|
|
13
13
|
|
|
14
|
+
# Right-to-left scripts, so the popover renders mirrored for those locales.
|
|
15
|
+
# Matched on the language subtag, so region variants ("ar-EG") count too.
|
|
16
|
+
RTL_LANGUAGES = %w[ar arc ckb dv fa ha he ks ku ps sd ug ur yi].freeze
|
|
17
|
+
|
|
14
18
|
class << self
|
|
15
19
|
def javascript
|
|
16
20
|
@javascript ||= File.read(SOURCE)
|
|
@@ -33,7 +37,9 @@ module I18nFeedback
|
|
|
33
37
|
active: active ? true : false,
|
|
34
38
|
showPill: I18nFeedback.config.show_pill ? true : false,
|
|
35
39
|
pillLabel: I18nFeedback.config.pill_label,
|
|
36
|
-
toggleParam: I18nFeedback.config.toggle_param
|
|
40
|
+
toggleParam: I18nFeedback.config.toggle_param,
|
|
41
|
+
labels: labels,
|
|
42
|
+
rtl: rtl?(locale)
|
|
37
43
|
}
|
|
38
44
|
# Escape "</" so a value can't close the <script> block early.
|
|
39
45
|
json = config.to_json.gsub('</', '<\/')
|
|
@@ -42,6 +48,37 @@ module I18nFeedback
|
|
|
42
48
|
%(<script type="application/json" data-i18n-feedback-config>#{json}</script>) +
|
|
43
49
|
%(<script data-i18n-feedback-widget#{nonce_attr}>#{javascript}</script>)
|
|
44
50
|
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
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
|
|
59
|
+
{
|
|
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.')
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def t(key, default)
|
|
76
|
+
I18n.t(key, scope: :i18n_feedback, default: default)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def rtl?(locale)
|
|
80
|
+
RTL_LANGUAGES.include?(locale.to_s.downcase.split(/[-_]/).first)
|
|
81
|
+
end
|
|
45
82
|
end
|
|
46
83
|
end
|
|
47
84
|
end
|
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.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yaroslav Shmarov
|
|
@@ -44,6 +44,27 @@ files:
|
|
|
44
44
|
- app/helpers/i18n_feedback/tag_helper.rb
|
|
45
45
|
- app/models/i18n_feedback/application_record.rb
|
|
46
46
|
- app/models/i18n_feedback/suggestion.rb
|
|
47
|
+
- config/locales/i18n_feedback.ar.yml
|
|
48
|
+
- config/locales/i18n_feedback.bn.yml
|
|
49
|
+
- config/locales/i18n_feedback.de.yml
|
|
50
|
+
- config/locales/i18n_feedback.en.yml
|
|
51
|
+
- config/locales/i18n_feedback.es.yml
|
|
52
|
+
- config/locales/i18n_feedback.fr.yml
|
|
53
|
+
- config/locales/i18n_feedback.hi.yml
|
|
54
|
+
- config/locales/i18n_feedback.id.yml
|
|
55
|
+
- config/locales/i18n_feedback.it.yml
|
|
56
|
+
- config/locales/i18n_feedback.ja.yml
|
|
57
|
+
- config/locales/i18n_feedback.ko.yml
|
|
58
|
+
- config/locales/i18n_feedback.nl.yml
|
|
59
|
+
- config/locales/i18n_feedback.pl.yml
|
|
60
|
+
- config/locales/i18n_feedback.pt.yml
|
|
61
|
+
- config/locales/i18n_feedback.ru.yml
|
|
62
|
+
- config/locales/i18n_feedback.th.yml
|
|
63
|
+
- config/locales/i18n_feedback.tr.yml
|
|
64
|
+
- config/locales/i18n_feedback.uk.yml
|
|
65
|
+
- config/locales/i18n_feedback.ur.yml
|
|
66
|
+
- config/locales/i18n_feedback.vi.yml
|
|
67
|
+
- config/locales/i18n_feedback.zh-CN.yml
|
|
47
68
|
- config/routes.rb
|
|
48
69
|
- lib/generators/i18n_feedback/install/install_generator.rb
|
|
49
70
|
- lib/generators/i18n_feedback/install/templates/create_i18n_feedback_suggestions.rb.tt
|