Translation issueshttps://lab.civicrm.org/dev/translation/-/issues2022-01-27T13:24:34Zhttps://lab.civicrm.org/dev/translation/-/issues/74ts() - Allow symbolic placeholders2022-01-27T13:24:34Ztottents() - Allow symbolic placeholdersOverview
---------
When writing translatable strings, placeholders must be numeric.
This leads to some quirky strings - eg if you're outputting a title and subtitle ("Some Chapter: Some Section"), the only way to encode that is `ts('%1...Overview
---------
When writing translatable strings, placeholders must be numeric.
This leads to some quirky strings - eg if you're outputting a title and subtitle ("Some Chapter: Some Section"), the only way to encode that is `ts('%1: %2')`. This string should be translatable because the layout is language dependent (eg LTR/RTL; eg punctuation-preferences), but the exported string will become meaningless when presented in Transifex (or similar). And it may be confused with other/similar strings.
Current behavior
-----------------
The function `ts(string $str, array $params)` accepts the following `$params`:
* Functional params (`count`, `plural`, `context`, `domain`, `escape`, `skip_translation`)
* Substitution params (numeric keys; `0`, `1`, `2`, ...)
As in:
```php
echo ts('Hello, %1!', [
1 => $name,
]);
echo '<li>' . ts('%1: %2', [
1 => $title,
2 => $subtitle,
]) . '</li>';
echo ts('The directory %1 is not writable. Please check your file permissions.', [
'plural' => 'The following directories are not writable: %1. Please check your file permissions.',
'count' => count($notWritableDirs),
1 => implode(', ', $notWritableDirs),
]),
```
```smarty
{ts 1=Bob}Hello %1!{/ts}
<li>{ts 1="Title" 2="Subtitle"}%1: %2{/ts}</li>
```
~~Proposed behavior (draft 1; symbol-prefix)~~
-----------------
Any `$params` which begin with a symbol (`%`, `_`, `{`, `@`, etc) will be used for variable substitution.
The earlier examples remain valid. Additionally, these examples are also valid:
```php
echo ts('Hello, %name!', [
'%name' => $name,
]);
echo '<li>' . ts('%title: %subtitle', [
'%title' => $title,
'%subtitle' => $subtitle],
) . '</li>';
echo ts('The directory %dir is not writable. Please check your file permissions.', [
'plural' => 'The following directories are not writable: %dir. Please check your file permissions.',
'count' => count($notWritableDirs),
'%dir' => implode(', ', $notWritableDirs),
]),
```
```smarty
{ts _NAME_=Bob}Hello _NAME_!{/ts}
<li>{ts _title_="Foo" _subtitle_="Bar"}_title_: _subtitle_{/ts}</li>
```
Proposed behavior (draft 2; capitalization-based)
-----------------
Any `$params` which begin with a capital letter (`[A-Z]`) will be used for variable substitution.
```php
echo ts('Hello, %NAME!', [
'NAME' => $name,
]);
echo '<li>' . ts('%TITLE: %SUBTITLE', [
'TITLE' => $title,
'SUBTITLE' => $subtitle],
) . '</li>';
echo ts('The directory %DIR is not writable. Please check your file permissions.', [
'plural' => 'The following directories are not writable: %DIR. Please check your file permissions.',
'count' => count($notWritableDirs),
'DIR' => implode(', ', $notWritableDirs),
]),
```
```smarty
{ts NAME=Bob}Hello %NAME!{/ts}
<li>{ts TITLE="Foo" SUBTITLE="Bar"}%TITLE: %SUBTITLE{/ts}</li>
```
Comments
---------
Either draft (using symbol-prefix or using uppercase) should avoid conflicts with existing strings+params. (Existing params do not begin with symbols and they are not uppercase.)
A couple factors in choosing a symbol:
* Using `%` is most consistent with current `ts()` style.
* `ts()` is used in multiple programming languages. Each has different compatibility/constraints.
* Pure PHP and pure JS are fairly flexible (`%FOO`, `{{FOO}}`, `_FOO_`, etc)
* Smarty-HTML (`{ts KEY=VALUE}...{/ts}`) is pretty limited. The bottleneck is how it parses the `KEY`.
* Angular-HTML (`{{ts('...')}}`) is in the middle. It's OK for `{{ts('%FOO')}}`, `{{ts('_FOO_')}}`, but I wouldn't count on `{{ts('{{FOO}}')}}`.
* If you want one symbol that works everywhere, `_` is probably it.
* Being flexible about symbol may be good for compatibility in the most contexts.
I suppose that the uppercase approach constrains style a bit, but maybe that's a good thing - ie you get more consistency in how `ts()` looks across environments.
Questions
---------
Are there any constraints in other layers -- eg Transifex, civistrings -- which would prevent this?
As far as I know, the only constraints which require using numeric-keys are baked into `ts()` itself.https://lab.civicrm.org/dev/translation/-/issues/53Frequency units frequently fail to be translated properly2023-11-23T07:20:57ZStéphane Lussierstephane@symbiotic.coopFrequency units frequently fail to be translated properlyOn numerous occasions, the internal value of frequency units (eg: year, month) are sent for display to a template without being translated first.
One such issue may be found in [CRM/Contribute/Form/Contribution/Main.php](https://lab.ci...On numerous occasions, the internal value of frequency units (eg: year, month) are sent for display to a template without being translated first.
One such issue may be found in [CRM/Contribute/Form/Contribution/Main.php](https://lab.civicrm.org/dev/core/-/blob/master/CRM/Contribute/Form/Contribution/Main.php#L550). In this case, a simple fix would usually suffice:
```patch
--- a/civicrm/CRM/Contribute/Form/Contribution/Main.php
+++ b/civicrm/CRM/Contribute/Form/Contribution/Main.php
@@ -548,7 +548,7 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu
if (!empty($form->_values['is_recur_interval']) || $className == 'CRM_Contribute_Form_Contribution') {
$unit .= "(s)";
}
- $form->assign('frequency_unit', $unit);
+ $form->assign('frequency_unit', ts($unit));
}
else {
$form->assign('one_frequency_unit', FALSE);
```
However, this patch in incomplete. There are multiple cases where a similar fix would need to be applied.
It's also not uncommon to find singular/plural tests in existing templates. The following example comes from [templates/CRM/Contribute/Form/Contribution/ThankYou.tpl](https://lab.civicrm.org/dev/core/-/blob/master/templates/CRM/Contribute/Form/Contribution/ThankYou.tpl#L123):
```smarty
{if $frequency_interval > 1}
<strong>{ts 1=$frequency_interval 2=$frequency_unit}This membership will be renewed automatically every %1 %2(s).{/ts}</strong>
{else}
<strong>{ts 1=$frequency_unit}This membership will be renewed automatically every %1.{/ts}</strong>
{/if}
```
This solution looks a bit strange to me... It assumes that adding an `(s)` to an internal keyword will make it plural. That may work in most situations, but it would prevent the already translated keyword to be altered upon the phrase translation.
Shouldn't the keyword be fully translated _and_ pluralized (if necessary) _before_ being sent to the translation string?
Could the `ts` function take care of translating and pluralizing substrings?
I don't mean to make a huge issue out of a small one, but I wonder: Is there a pattern that we can agree on for these sorts of situations?https://lab.civicrm.org/dev/translation/-/issues/47Investigate javascript currency library2023-06-02T19:33:39ZeileenInvestigate javascript currency libraryI think that we should use an approach for money fields similar to date fields where formatting is at the js layer and the values are always submitted in unrounded US decimal format - ie. always submitted like 4,000.0123 (or preferably 4...I think that we should use an approach for money fields similar to date fields where formatting is at the js layer and the values are always submitted in unrounded US decimal format - ie. always submitted like 4,000.0123 (or preferably 4000.123) and the php can expect just to 'use what it gets'
There are a number of possible js libraries. https://bashooka.com/coding/javascript-libraries-for-formatting-number-currency-time-date/
I feel like the requirements are
1) Format currencies appropriately. If I have a page that accepts donations in EUR it should display as 2.534.234,00 €
2) Format currencies by locale if known. If I 'know' - probably from a drupal url or similar that my page is for French Euro users then I want 2 534 234,00 €
3) Use the site numeric separator on backend screens. If I'm used to using a US decimal format I want all donations displayed with the same 'meaning' of the decimal
4) Format on input.
5) Package is appropriately licenced
The first 3 seem comfortably addressed by https://osrec.github.io/currencyFormatter.js/ which also offers the very nice
```
<div class='money' data-ccy='EUR'> 1234564.58 </div>
<div class='money' data-ccy='GBP'> 8798583.85 </div>
<div class='money' data-ccy='CHF'> 0.9754 </div>
```
syntax - which we could extend for scenarios 2 & 3 if necessary. Is MIT license OK?
The package seems pretty static - and they have not merged a PR to add Romanian which might be not great. I'm just looking at a couple of others as well
I REALLY like the jquery syntax above :-)
See https://lab.civicrm.org/dev/translation/-/issues/47 for same topic but php layer
Also Format on input - http://autonumeric.org/ looks promising - also MIT
Dinero doesn't really seem to do much formatting https://dinerojs.com/module-dinero
http://numbrojs.com/format.html also offers pretty reasonable formatting. I like the 'unformat' function but I wonder if it would work for Euro currencies
Note the screenshot demonstrates where full locale-based formatting would make no sense. The rows all need to use the decimal point the same way
![Screen_Shot_2020-05-18_at_4.35.13_PM](/uploads/58e7cfce6e88ccae2e19ba1b711d9dc4/Screen_Shot_2020-05-18_at_4.35.13_PM.png)
https://lab.civicrm.org/dev/translation/-/issues/46Proposal - languages from urls2020-05-26T20:15:41ZeileenProposal - languages from urlsI want to propose an addition to our basic edit forms
1) in CRM_Core_Form -add a property language and in generic preProcess look for this property in the url & set it on the form
2) in any APIv4 calls at the form layer use this value t...I want to propose an addition to our basic edit forms
1) in CRM_Core_Form -add a property language and in generic preProcess look for this property in the url & set it on the form
2) in any APIv4 calls at the form layer use this value to setLanguage, if exists, on the api call (this is mostly a principle of intent at this stage)
What does this achieve? Basically it allows me to take action in an extension. Currently the MessageTemplate form uses apiv4 to retrieve and save message templates. I can listen to these calls in civi_data_translate_civicrm_apiWrappers and intervene - retrieving the values relevant to the specific language, if appropriate. This is a pretty tough intervention to do without any core support, and fairly simple with a small change to core + an agreement as to how we prefer to use the api going forwards
https://github.com/eileenmcnaughton/civi-data-translate/blob/master/civi_data_translate.php#L187
Next steps - I would look to convert the EntityFormTrait to use apiv4 to create a generic template / model for how this should be done. (I would need to set api version as a parameter on the form as I realise extensions may use this trait for entities with no v4 api as yet.)
@bgm @colemanw @seamuslee @tottenhttps://lab.civicrm.org/dev/translation/-/issues/42Document guidelines for situations where trivial technical changes do more ha...2020-04-02T13:28:24ZDaveDDocument guidelines for situations where trivial technical changes do more harm than goodMoved to gitlab from https://github.com/civicrm/civicrm-dev-docs/pull/754
The [end-to-end process](https://lab.civicrm.org/dev/translation/-/wikis/Pushing-new-strings-to-transifex) from the time you make a change in the code to when the...Moved to gitlab from https://github.com/civicrm/civicrm-dev-docs/pull/754
The [end-to-end process](https://lab.civicrm.org/dev/translation/-/wikis/Pushing-new-strings-to-transifex) from the time you make a change in the code to when the translation of it ends up in the tarball of a release is lengthy, depends on human translators' time, and currently includes a [manual tedious step](https://lab.civicrm.org/infra/ops/-/issues/931) for administrators (which means it doesn't even get to transifex to be made available to translators for a few months). In the meantime the string you just changed has now potentially become untranslated immediately in all languages in both master and likely still untranslated when it becomes a release candidate. And possibly for several releases/months after.
So if the wording is not preventing users from completing tasks and the technical functionality is working, then is having it be EXACTLY right worth invalidating an existing translation and generating another end-to-end cycle of the translation process *if that is the only change being made*. It seems like it is possible to write out some guidelines and examples.
The PR proposed these as a starting point:
#### Don't change
```smarty
{ts 1="https://www.example.org"}This is a block of text where the wording is fine and the link works but the <a href="%1" target="_blank">link attributes</a> should be a parameter to the ts. But it's not preventing anyone completing their work tasks and isn't confusing to users.{/ts}
```
#### Do change
* If it would normally break translation but the new string is already used somewhere else, and so it's already translated.
* Spelling mistakes. While not preventing a user from completing a task, the positives outweigh the negatives, and this is visible to the user, as compared to the above "don't change" example where the user doesn't see a problem.https://lab.civicrm.org/dev/translation/-/issues/41Invoice for recurring contribution should be sent in the preferred language o...2022-11-25T16:01:21ZbgmInvoice for recurring contribution should be sent in the preferred language of the contactThe contact record has a "preferred language" field, which can be automatically set when people fill in Contribution or Event forms.
That field can be used in certain circumstances, such as in Mailings and in Scheduled Reminders.
Howev...The contact record has a "preferred language" field, which can be automatically set when people fill in Contribution or Event forms.
That field can be used in certain circumstances, such as in Mailings and in Scheduled Reminders.
However, it is not used in the following circumstances:
* In Administration > CiviContribute > Component settings, enable "tax and invoicing", and enable PDF invoices.
* In Administration > Localization > Languages, enable multilingual, and enable a second locale.
* Setup a form that supports recurring contributions, enable email receipts
* As an anonymous user, donate on that form in the second language (not the default global language), selecting a recurring (ex: daily) donation.
Double-check that the contact record that was created has the second-language. Change if it necessary (I forget where the setting is, for defining the pref. language).
Then, as time passes, notice that the recurring email receipts are in the default site language. This is because the cron or IPNs will usually run in the default site language.
`CRM_Core_BAO_ActionSchedule::setCommunicationLanguage()` would be a good implementation reference. We should probably move it to `CRM_Core_I18n` for clarity.https://lab.civicrm.org/dev/translation/-/issues/25Unselecting from 'Available languages' doesn't drop respective locale views f...2021-08-12T19:25:28ZMonish DebUnselecting from 'Available languages' doesn't drop respective locale views from DBSteps to replicate the issue:
1. Add more than one language from 'Add Language' list say English and French(Canada)
2. Then change civi instance to multilingual
3. DB creates views with locale suffix en_US and fr_CA
4. Now unselect Frenc...Steps to replicate the issue:
1. Add more than one language from 'Add Language' list say English and French(Canada)
2. Then change civi instance to multilingual
3. DB creates views with locale suffix en_US and fr_CA
4. Now unselect French(Canada) and save
Bug: This doesn't drop the fr_CA views from DB as it is not required.https://lab.civicrm.org/dev/translation/-/issues/24On New Event, allow translations to be entered before first save2019-03-08T17:14:15ZJoeMurrayOn New Event, allow translations to be entered before first saveCurrently, on multilingual sites, it is only possible to enter text for the current language on the first form presented for Events > New Event (civicrm/event/add?reset=1&action=add). After that form is saved, translations can be entered...Currently, on multilingual sites, it is only possible to enter text for the current language on the first form presented for Events > New Event (civicrm/event/add?reset=1&action=add). After that form is saved, translations can be entered for any translatable field on any tab.
Proposed enhancement: allow translations to be entered for the text fields on the first form as well, prior to first save.
This enhancement idea is currently unfunded.https://lab.civicrm.org/dev/translation/-/issues/23Angular asset cache and multi-lingual2024-01-29T10:06:18ZbgmAngular asset cache and multi-lingualAngular extensions, such as CiviMail (classic) or Mosaico, will not always be displayed in the correct language when the Angular asset cache is enabled/auto (Admin > System Settings > Debugging). Tested on Drupal 7 (in case that makes a ...Angular extensions, such as CiviMail (classic) or Mosaico, will not always be displayed in the correct language when the Angular asset cache is enabled/auto (Admin > System Settings > Debugging). Tested on Drupal 7 (in case that makes a different with the "auto" setting of that cache).
How to reproduce on dmaster:
* Make sure you have the civicrm-l10n.tar.gz translation files (it's the case on dmaster.demo.civicrm.org)
* Go to Administer > Localisation, and enable another language, such as French (you don't need to enable multi-lingual).
* Use the CiviCRM Language Switch to set the language to French
* Go to Mailing > New Mailing (classic or mosaico, same bug)
* Now go back to the dashboard, set the language to English
* Go to Mailing > New Mailing, and notice that the UI is still in French.https://lab.civicrm.org/dev/translation/-/issues/17RTL issue: form label should be at right, and their input fields, at the left.2018-10-22T18:50:53ZcalbasiRTL issue: form label should be at right, and their input fields, at the left.I'm not sure if I should create this issue here or at civicrm core repository. Doing here, as first step to make a Merge Request at Github repository.
I'm attaching an screenshot of the wrong output. It's wrong, at least, in Arabic, but...I'm not sure if I should create this issue here or at civicrm core repository. Doing here, as first step to make a Merge Request at Github repository.
I'm attaching an screenshot of the wrong output. It's wrong, at least, in Arabic, but I suppose it's wrong for all other RTL languages. It's, too, a basic feature, because forms are used everywhere...
This issue happens at custom profile but also at system/default profiles.![Captura_2018-09-13_17-20-29](/uploads/3bdba1980909fd4fb5a0ea96979bd24d/Captura_2018-09-13_17-20-29.png)
![Captura_2018-09-13_17-17-19](/uploads/e6b36a362c68005b37c0a74e0d106194/Captura_2018-09-13_17-17-19.png)