Skip to content

Commit 50c35dc

Browse files
mrunkelkarser
andauthored
Add ability to set the language of the ReCaptcha widget (#56)
* Detect locale and pass it to google * Update documentation, and try a whole different approach. * Remove unused import * Adjust composer to allow builds to work. * Adjust composer correctly to allow builds to work. * fix tests Co-authored-by: Marc Runkel <[email protected]> Co-authored-by: karser <[email protected]>
1 parent ee81cac commit 50c35dc

File tree

4 files changed

+13
-6
lines changed

4 files changed

+13
-6
lines changed

Form/Recaptcha3Type.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public function buildView(FormView $view, FormInterface $form, array $options):
3333
$view->vars['enabled'] = $this->enabled;
3434
$view->vars['action_name'] = $options['action_name'];
3535
$view->vars['script_nonce_csp'] = $options['script_nonce_csp'] ?? '';
36+
$view->vars['locale'] = $options['locale'] ?? 'en';
3637
}
3738

3839
public function getParent(): string
@@ -52,6 +53,7 @@ public function configureOptions(OptionsResolver $resolver): void
5253
'site_key' => null,
5354
'host' => null,
5455
'action_name' => 'homepage',
56+
'locale' => 'en',
5557
'script_nonce_csp' => '',
5658
]);
5759
}

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,15 @@ class TaskType extends AbstractType
9292
'constraints' => new Recaptcha3(),
9393
'action_name' => 'homepage',
9494
'script_nonce_csp' => $nonceCSP,
95+
'locale' => 'de',
9596
]);
9697
}
9798
}
9899
```
99100
Notes:
100101
- The `action_name` parameter is [reCAPTCHA v3 action](https://developers.google.com/recaptcha/docs/v3#actions) which identifies the submission of this particular form in the Google reCAPTCHA dashboard, and confirming it is as expected in the backend is a recommended extra security step.
101102
- The `script_nonce_csp` parameter is optional. You must use the same nonce as in your Content-Security Policy header.
103+
- The `locale` parameter is optional. It defaults to English and controls the language on the reCaptcha widget.
102104

103105
### How to use reCAPTCHA globally (meaning even in China):
104106

@@ -113,7 +115,10 @@ karser_recaptcha3:
113115
114116
### How can I set the captcha language for different locales?
115117
116-
You should install the [Symfony Translation component](https://symfony.com/doc/current/translation.html).
118+
You can control the language in the small widget displayed by setting the locale in the options above.
119+
120+
To change the error messages, you should install the [Symfony Translation component](https://symfony.com/doc/current/translation.html).
121+
117122
Then replace the validation text with the translation keys for the message and messageMissingValue options:
118123
```php
119124
$builder->add('captcha', Recaptcha3Type::class, [

Resources/views/Form/karser_recaptcha3_widget.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
setTimeout(recaptchaCallback_{{ validJsId }}, 100000);
1414
};
1515
</script>
16-
<script type="text/javascript" src="https://{{ form.vars.host }}/recaptcha/api.js?render={{ form.vars.site_key }}&onload=recaptchaCallback_{{ validJsId }}" async defer{% if form.vars.script_nonce_csp is defined %} nonce="{{ form.vars.script_nonce_csp }}"{% endif %}></script>
16+
<script type="text/javascript" src="https://{{ form.vars.host }}/recaptcha/api.js?render={{ form.vars.site_key }}&hl={{ form.vars.locale }}&onload=recaptchaCallback_{{ validJsId }}" async defer{% if form.vars.script_nonce_csp is defined %} nonce="{{ form.vars.script_nonce_csp }}"{% endif %}></script>
1717
{%- endif %}
1818
{% endapply %}
1919
{% endblock %}

Tests/FunctionalTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function testFormJavascriptPresent_ifEnabled()
3838

3939
//THEN
4040
self::assertStringContainsString('<input type="hidden" id="form_captcha" name="form[captcha]" />', $view);
41-
self::assertStringContainsString('<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=key&onload=recaptchaCallback_form_captcha" async defer nonce=""></script>', $view);
41+
self::assertStringContainsString('<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=key&hl=en&onload=recaptchaCallback_form_captcha" async defer nonce=""></script>', $view);
4242
self::assertStringContainsString('var recaptchaCallback_form_captcha', $view);
4343
self::assertStringContainsString("document.getElementById('form_captcha').value = token;", $view);
4444
}
@@ -55,7 +55,7 @@ public function testHyphenConvertedToUnderscore()
5555

5656
//THEN
5757
self::assertStringContainsString('<input type="hidden" id="form_capt-cha" name="form[capt-cha]" />', $view);
58-
self::assertStringContainsString('<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=key&onload=recaptchaCallback_form_capt_cha" async defer nonce=""></script>', $view);
58+
self::assertStringContainsString('<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=key&hl=en&onload=recaptchaCallback_form_capt_cha" async defer nonce=""></script>', $view);
5959
self::assertStringContainsString('var recaptchaCallback_form_capt_cha', $view);
6060
self::assertStringContainsString("document.getElementById('form_capt-cha').value = token;", $view);
6161
}
@@ -194,7 +194,7 @@ public function testFormJavascriptNoncePresent_ifSet()
194194
//THEN
195195
self::assertStringContainsString('<input type="hidden" id="form_captcha" name="form[captcha]" />', $view);
196196
self::assertStringContainsString('<script type="text/javascript" nonce="csp_nonce">', $view);
197-
self::assertStringContainsString('<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=key&onload=recaptchaCallback_form_captcha" async defer nonce="csp_nonce"></script>', $view);
197+
self::assertStringContainsString('<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=key&hl=en&onload=recaptchaCallback_form_captcha" async defer nonce="csp_nonce"></script>', $view);
198198
self::assertStringContainsString('var recaptchaCallback_form_captcha', $view);
199199
self::assertStringContainsString("document.getElementById('form_captcha').value = token;", $view);
200200
}
@@ -210,7 +210,7 @@ public function testFormJavascriptAltHostIsPreserved_ifSet()
210210
$view = $template->render(['form' => $form->createView()]);
211211

212212
//THEN
213-
self::assertStringContainsString('<script type="text/javascript" src="https://www.recaptcha.net/recaptcha/api.js?render=key&onload=recaptchaCallback_form_captcha" async defer nonce=""></script>', $view);
213+
self::assertStringContainsString('<script type="text/javascript" src="https://www.recaptcha.net/recaptcha/api.js?render=key&hl=en&onload=recaptchaCallback_form_captcha" async defer nonce=""></script>', $view);
214214
}
215215

216216
private function assertFormHasCaptchaError(FormInterface $form, string $expectedMessage)

0 commit comments

Comments
 (0)