Translation issueshttps://lab.civicrm.org/dev/translation/-/issues2024-03-25T18:55:32Zhttps://lab.civicrm.org/dev/translation/-/issues/85Some strings in core afforms do not translate2024-03-25T18:55:32ZbgmSome strings in core afforms do not translateFor example:
- Enable CiviCampaign
- Go to the CiviCampaign dashboard
![image](/uploads/49a1d30b027b36f57971cbc4fb9d48ff/image.png)
For the tabs, the strings are correctly wrapped with `ts`, and I double-checked that the strings are t...For example:
- Enable CiviCampaign
- Go to the CiviCampaign dashboard
![image](/uploads/49a1d30b027b36f57971cbc4fb9d48ff/image.png)
For the tabs, the strings are correctly wrapped with `ts`, and I double-checked that the strings are translated in my translation file.
For the placeholders on the filter fields, the strings are not correctly wrapped in `ts`, but even if I do wrap them, and I make sure to add the strings to my translation files, they do not translate.
cc @colemanwhttps://lab.civicrm.org/dev/translation/-/issues/84`testLocalizedData()` failing after recent strings update2024-03-13T12:59:26Ztotten`testLocalizedData()` failing after recent strings updateIn CI, the test `testLocalizedData()` has started failing consistently. I've done some hunting and may have an explanation (*but don't know the next step*).
__The Test__: `testLocalizedData()` generates the SQL data-set in two locales. ...In CI, the test `testLocalizedData()` has started failing consistently. I've done some hunting and may have an explanation (*but don't know the next step*).
__The Test__: `testLocalizedData()` generates the SQL data-set in two locales. It spot-checks the data for a common string that should usually be translated. Specifically, `New Organization` is a link in the default menu. It's translated as `Neue Organisation` (`de_DE`) or `Nouvelle organisation` (`fr_FR`).
__Compare__: The test passes on my laptop but not in CI. My laptop has older translation data than the server.
You can manually inspect by running a small script and grepping the output (`cv scr printsql.php | grep Neue`):
```php
function _getSqlLive($locale) {
$schema = new \CRM_Core_CodeGen_Schema(\Civi\Test::codeGen());
$files = $schema->generateLocaleDataSql($locale);
foreach ($files as $file => $content) {
if (preg_match(';^civicrm_data\.;', $file)) {
return $content;
}
}
throw new \Exception("Failed to generate $locale");
}
echo _getSqlLive('de_DE');
```
Both outputs include some translated strings, but the newer doesn't have as many:
```diff
---Local machine, old data
+++Server machine, new data
("Individual,Contact",NULL,"4","0","1","new_individual","Neue Person"),
-("Organization,Contact",NULL,"5","0","1","new_organization","Neue Organisation"),
-("Household,Contact",NULL,"6","0","1","new_household","Neuer Haushalt"),
+("Organization,Contact",NULL,"5","0","1","new_organization","New Organization"),
+("Household,Contact",NULL,"6","0","1","new_household","New Household"),
```
If I inspect the data (`msgunfmt civicrm.mo -o civicrm.po`), I find these in the old data-set:
```
msgid "New Individual"
msgstr "Neue Person"
msgid "New Organization"
msgstr "Neue Organisation"
msgctxt "menu"
msgid "New Individual"
msgstr "Neue Person"
msgctxt "menu"
msgid "New Organization"
msgstr "Neue Organisation"
```
And these in the new data-set:
```
msgid "New Individual"
msgstr "Neue Person"
msgctxt "menu"
msgid "New Individual"
msgstr "Neue Person"
msgctxt "menu"
msgid "New Organization"
msgstr "Neue Organisation"
```
So it's missing `New Organization` in the default context. Additionally, the phrases `Phone Call` and `Meeting` appear in the old data-set but not the new data-set. I see similar omissions in `fr_FR`.
I assume that the SQL translation is evaluating everything in the default context. (It doesn't seem to use the `menu` translations). I don't know if that's good or bad. But regardless, it's probably bad that `Phone Call` and `Meeting` are missing.
In the CI logs for `testTranslatedData()`, the failure starts on roughly Feb 4. (Some places seem to start Feb 5 -- l10n data is cached for a bit.) I'm guessing this is related the new strings released around Feb 4 (https://chat.civicrm.org/civicrm/pl/jyqia56a47dp5dnrouiabnmnuw).
(ping @bgm)https://lab.civicrm.org/dev/translation/-/issues/83No translation for "sections" in "New <contact>"2023-08-30T12:57:17Zthoni56No translation for "sections" in "New <contact>"When creating a new person/household/organisation there are foldable sections for details, address, communication preferences etc.
When the site has a non-English localization (at least a Swedish one) they are not translated.
![Skärmav...When creating a new person/household/organisation there are foldable sections for details, address, communication preferences etc.
When the site has a non-English localization (at least a Swedish one) they are not translated.
![Skärmavbild_2023-08-11_kl._13.38.33](/uploads/effa60ca9aa352a2d735ddfe89bb8d79/Skärmavbild_2023-08-11_kl._13.38.33.png)
I'm contributing to the Swedish translation so I know that the strings are translated in Transifex ;-). I have `uplang` installed and it seems to update other translations (although I would love a way to explicitly trigger the download, see https://lab.civicrm.org/extensions/uplang/-/issues/2).https://lab.civicrm.org/dev/translation/-/issues/81eWAYRecurring/ewayrecurring - Tricky to checkout git repo2022-11-30T08:36:05ZtotteneWAYRecurring/ewayrecurring - Tricky to checkout git repoThere appear to be two l10n data folders for "ewayrecurring", but they have different capitalization:
https://github.com/civicrm/civicrm-l10n-extensions/tree/master/po/eWAYRecurring
https://github.com/civicrm/civicrm-l10n-extensions/tre...There appear to be two l10n data folders for "ewayrecurring", but they have different capitalization:
https://github.com/civicrm/civicrm-l10n-extensions/tree/master/po/eWAYRecurring
https://github.com/civicrm/civicrm-l10n-extensions/tree/master/po/ewayrecurring
If you checkout on a case-insensitive filesystem, then you get weird messages.
Here's what I see with initial checkout:
```
[bknix-min:~/bknix/build/universe/ext/civicrm-l10n-extensions] git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: po/eWAYRecurring/bg_BG/eWAYRecurring.po
modified: po/eWAYRecurring/ca_ES/eWAYRecurring.po
modified: po/eWAYRecurring/cs_CZ/eWAYRecurring.po
modified: po/eWAYRecurring/cy_GB/eWAYRecurring.po
modified: po/eWAYRecurring/de_DE/eWAYRecurring.po
modified: po/eWAYRecurring/en_GB/eWAYRecurring.po
modified: po/eWAYRecurring/es_ES/eWAYRecurring.po
modified: po/eWAYRecurring/fr_CA/eWAYRecurring.po
```
The two names `po/eWAYRecurring/bg_BG/eWAYRecurring.po` and `po/ewayrecurring/bg_BG/ewayrecurring.po` point to the same object in the filesystem, but they have different content, so one or the other gets locally modified.
Because the repo is in this funny state, it's hard to stay up-to-date (`git pull` doesn't run cleanly).https://lab.civicrm.org/dev/translation/-/issues/79Error in link on upgrade page after update database ready2022-11-30T18:23:15ZHanVError in link on upgrade page after update database readyI have today upgraded to version 5.55.2, on the screen after the database upgrade is an error in the link in the message:
Your Date Format settings have been automatically updated. (CRM/Upgrade/Incremental/php/FiveFiftyThree.php)
In the...I have today upgraded to version 5.55.2, on the screen after the database upgrade is an error in the link in the message:
Your Date Format settings have been automatically updated. (CRM/Upgrade/Incremental/php/FiveFiftyThree.php)
In the open tag it must be: href='%1'
I found the place with transifex.https://lab.civicrm.org/dev/translation/-/issues/75Translatable fields within Extension table2022-04-21T20:39:46ZseamusleeTranslatable fields within Extension tableAt present the CiviCRM i18n widget code and also the i10n schema code depend on the functions in the schema structure file returning an array of fields or html widgets. The Schema Structure file does not contain any information about tab...At present the CiviCRM i18n widget code and also the i10n schema code depend on the functions in the schema structure file returning an array of fields or html widgets. The Schema Structure file does not contain any information about tables other than core tables so for example in the JMA Grant Applications extension if we wanted to make the title or the introductory text field translatable we would have to hack the schema structure file.
I would like to propose that we create 3 new Events or similar to handle altering the fields, indices and widgets functions in the schema structure file.https://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/67Canonize API for storing translated data2021-08-12T19:25:30ZtottenCanonize API for storing translated data# Goal
Enable richer user experiences which incorporate data-translation. Specifically, provide a CRUD API for administrative applications that need to read/write alternate versions of a string in the database.
# Background
* This is ...# Goal
Enable richer user experiences which incorporate data-translation. Specifically, provide a CRUD API for administrative applications that need to read/write alternate versions of a string in the database.
# Background
* This is most immediately motivated by https://lab.civicrm.org/dev/mail/-/issues/83, which aims to improve the process+experience of drafting+testing workflow templates. For this case, the string that is being edited (ie `civicrm_msg_template.msg_html`) is a relatively rich piece of content (with HTML tags, tokens, Smarty expressions - which in turn may vary based on the context for which the template will be used). The richness of the text implies that one should have more features available (token-pickers, syntax-highlighting, ad nauseum). Editing a translation of this content in a generic textbox (as with multilingual UI, Transifex UI, or POEdit) would be difficult and error-prone.
* This is intended as a step in support of https://lab.civicrm.org/community/feature-request/-/issues/26, which is a broad effort (initiated by @ayduns @BjoernE) to re-conceive how the multilingual subsystem works. TLDR: Current multilingual requires significant MySQL schema manipulation. This works for 1-3 languages but does not scale to 10 languages. Resolving it requires changes in the storage/lifecycle of translated data.
* Inspired by this discussion, Eileen wrote a proof-of-concept extension https://github.com/eileenmcnaughton/civi-data-translate. The scope of `civi-data-translate` mostly matches the scope of this filing, but not quite perfectly. It matches insofar as it introduces an APIv4 interface and a MySQL table for strings. It diverges insofar as it specifically touches on `MessageTemplate`. (The work for `MessageTemplate` is left as a separate matter.) Its biggest obstacle is dependency-hell: it requires a skilled administrator to maintain a deployment, which disincentivizes development and usage.
# Approaches
Working within the limits of available code and capacity, it appears feasible to adapt `civi-data-translate` to this purpose. Either:
1. Move its APIv4 interface and data-storage to core-proper, or...
2. Move its APIv4 interface and data-storage to core-extension.
# Comments
* Having an API to edit the strings would be meaningless if we did not have a data-store.
* There is a performance question about using MySQL for a string table. (Most FOSS applications use `gettext` MO files which are optimized for fast lookup of static strings. This is how Civi handles translation of its numerous app-strings.) In prior discussions with @BjoernE @ayduns etal, we identified this balance:
* There is a difference between *administration* (browsing/editing strings) and *runtime lookup* (substituting 1000 strings during a page-load).
* For administration, there is no question about whether the performance of a MySQL string-table would be acceptable. It would be. In fact, many different tools/workflows/stores can be acceptable.
* The performance question is relevant to *runtime lookup of heavily used strings*. The performance question is not necessarily closed, and it depends on other variables (*the #data-strings, the use-case, the hardware, etc*).
* If one does need to optimize lookup, the best known approach is to compile to gettext. To wit: Read strings from whatever source is handy, aggregate them, and [write them](https://github.com/pear/File_Gettext/blob/master/File/Gettext/MO.php) to a cache folder in `*.mo` format. (You can see [de.systopia.l10nmo](https://github.com/systopia/de.systopia.l10nmo) as a foray into this approach of blending/merging string sources.)
* I was worried about proposing this - specifically, worried that it might conflict with a more optimized dataflow. However, on reflection, I think it is complementary progress. Suppose you wanted to patch `l10nmo` to include a feed of strings provided by web-based administrators. If each web UI stored strings differently, then you'd probably give up. But if they use the same (shared/documented) string API, then it's easier to pull from there.
* (*I mention this as a hypothetical. In practice, some things like dev/mail#83 can be achieved without this level of optimization. The upshot is that we can bite off a chunk of work here on the API/storage side and make some incremental progress.*)https://lab.civicrm.org/dev/translation/-/issues/63Italian translation of Household Member relationship doesn't specify which si...2021-01-29T10:58:50ZDaveDItalian translation of Household Member relationship doesn't specify which side the relationship is onIn english it's "Household Member of" to mean the individual is a member of a household (A to B), and "Household Member is" to mean the household has the individual as a member (B to A).
In italian it's "Membro del nucleo familiare" on ...In english it's "Household Member of" to mean the individual is a member of a household (A to B), and "Household Member is" to mean the household has the individual as a member (B to A).
In italian it's "Membro del nucleo familiare" on both sides, so it's not clear which way is which.
https://lab.civicrm.org/dev/translation/-/blob/14722d7fbae68eaea4214aa0f6966d635c1f4d91/po/it_IT/common-base.po#L25802-25808
Came up while looking at other stuff. I don't know what the right translation should be.https://lab.civicrm.org/dev/translation/-/issues/62Updated State list for Taiwan2021-01-15T15:42:56ZsudomanUpdated State list for TaiwanOne of our site users would like to recommend updating the "State list" of "Country: Taiwan". Below is the recommended list from the Office of the President (<https://english.president.gov.tw/Page/106>). Our user says that it's ok to put...One of our site users would like to recommend updating the "State list" of "Country: Taiwan". Below is the recommended list from the Office of the President (<https://english.president.gov.tw/Page/106>). Our user says that it's ok to put the list under "State", even though they actually only call them city or county.
```
Taipei City
New Taipei City
Keelung City
Taoyuan City
Hsinchu City
Hsinchu County
Miaoli County
Taichung City
Changhua County
Nantou County
Yunlin County
Chiayi City
Chiayi County
Tainan City
Kaohsiung City
Pingtung County
Yilan County
Hualien County
Taitung County
Penghu County
Kinmen County
Lienchiang County
```
Thanks : )https://lab.civicrm.org/dev/translation/-/issues/61docURL and ts, or how ConfigTaskList.tpl has odd translation strings2021-05-10T20:51:53ZbgmdocURL and ts, or how ConfigTaskList.tpl has odd translation stringsWhen running the string extraction, these strings end up in the .pot files:
```
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid "$componentTitles.CiviContribute"
msgstr ""
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid ...When running the string extraction, these strings end up in the .pot files:
```
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid "$componentTitles.CiviContribute"
msgstr ""
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid "$componentTitles.CiviPledge"
msgstr ""
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid "$componentTitles.CiviEvent"
msgstr ""
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid "$componentTitles.CiviMember"
msgstr ""
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid "$componentTitles.CiviMail"
msgstr ""
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid "$componentTitles.CiviCampaign"
msgstr ""
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid "$componentTitles.CiviCase"
msgstr ""
#: templates/CRM/Admin/Page/ConfigTaskList.tpl
msgid "$componentTitles.CiviGrant"
msgstr ""
```
To test:
```
civistrings templates/CRM/Admin/Page/ConfigTaskList.tpl
```
Is it because of an incorrect use of `ts`, or is it because civistrings should ignore crmURL?
Code:
```
<tr class="even">
<td class="tasklist nowrap" style="width: 10%;">{docURL page="user/contributions/what-is-civicontribute" text=$componentTitles.CiviContribute}</td>
<td>{ts}Online fundraising and donor management, as well as offline contribution processing and tracking.{/ts}</td>
</tr>
```
Example of docURL strings that should be extracted:
```
templates/CRM/Contribute/Form/ContributionPage/Custom.hlp:{capture assign=docLinkCustom}{docURL page="user/organising-your-data/custom-fields" text="custom fields"}{/capture}
templates/CRM/Contribute/Form/ContributionPage/Custom.hlp:{capture assign=docLinkProfile}{docURL page="user/organising-your-data/profiles" text="profiles"}{/capture}
templates/CRM/Case/Page/ConfigureError.tpl:{capture assign=docLink}{docURL page="user/case-management/set-up" text="CiviCase Setup documentation"}{/capture}
templates/CRM/Contact/Form/OnBehalfOf.tpl: {ts}Latitude and longitude may be automatically populated by enabling a Mapping Provider.{/ts} {docURL page="user/initial-set-up/installation-and-basic-set-up" text="(Refer to the Mapping and Geocoding section in the Installation and Basic Setup Chapter)"}</span>
```
I feel like we should instead use 'ts' in the docURL call, instead of assuming it. There are 22 instances where it would need fixing.
```
grep -r docURL templates/ | grep text | grep -v componentTitle
```
@totten @seamuslee Any thoughts?https://lab.civicrm.org/dev/translation/-/issues/59Broken link and mistranslation in Italian for ACL roles page2021-03-19T15:14:05ZDaveDBroken link and mistranslation in Italian for ACL roles pageIt's just a help text link, but maybe 2 problems:
1. The use of `{docURL}` requires text you pass in to be translated already.
1. Somebody probably noticed it wasn't working and tried to adjust by putting the link into transifex, but it...It's just a help text link, but maybe 2 problems:
1. The use of `{docURL}` requires text you pass in to be translated already.
1. Somebody probably noticed it wasn't working and tried to adjust by putting the link into transifex, but it leads to a broken link: https://lab.civicrm.org/dev/translation/-/blob/9d4c4d9db3535f3816969b541c9bbe00345569a4/po/it_IT/common-base.po#L18128
This is the code:
https://github.com/civicrm/civicrm-core/blob/d1eed91c218f4c285a535275e36732f68463824b/templates/CRM/ACL/Header.tpl#L10-L14
```smarty
{capture assign=docLink}{docURL page='user/initial-set-up/permissions-and-access-control/' text='Access Control Documentation'}{/capture}
<div class="help">
<p>{ts 1=$docLink}ACLs allow you to control access to CiviCRM data. An ACL consists of an <strong>Operation</strong> (e.g. 'View' or 'Edit'), a <strong>set of data</strong> that the operation can be performed on (e.g. a group of contacts), and a <strong>Role</strong> that has permission to do this operation. Refer to the %1 for more info.{/ts}</p>
</div>
```https://lab.civicrm.org/dev/translation/-/issues/57Mixed up translation for a few case role-related strings in nl_BE2020-10-23T15:08:34ZDaveDMixed up translation for a few case role-related strings in nl_BEThere are a couple lines in the nl_BE po file that are a bit mixed up. This came up before and it got fixed for nl_NL but didn't get updated for nl_BE. I think this needs to be updated in transifex.
https://lab.civicrm.org/dev/translati...There are a couple lines in the nl_BE po file that are a bit mixed up. This came up before and it got fixed for nl_NL but didn't get updated for nl_BE. I think this needs to be updated in transifex.
https://lab.civicrm.org/dev/translation/-/blob/41c36bc0532e3dd5e96e3481d6212f0c36e84686/po/nl_BE/case.po#L787-797
The nl_NL ones are correct so the corresponding lines above just need to match these:
https://lab.civicrm.org/dev/translation/-/blob/41c36bc0532e3dd5e96e3481d6212f0c36e84686/po/nl_NL/case.po#L771-781https://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/50Locale-aware recaptcha2020-12-14T04:07:55Zmattwiremjw@mjwconsult.co.ukLocale-aware recaptchaThe library in use by CiviCRM is a *very* old version and is not locale-aware. See https://civicrm.stackexchange.com/questions/11533/recaptcha-update-language/37503 for more info.
We should update the library and make recaptcha in CiviC...The library in use by CiviCRM is a *very* old version and is not locale-aware. See https://civicrm.stackexchange.com/questions/11533/recaptcha-update-language/37503 for more info.
We should update the library and make recaptcha in CiviCRM respect the locale of the form.https://lab.civicrm.org/dev/translation/-/issues/49Multi-record Custom Data Money Field is not formatted2020-06-12T14:24:00ZbgmMulti-record Custom Data Money Field is not formattedSteps to re-create:
* Create a new Custom Field Group, for Contacts, with multi-record enabled.
* Add a money field (text) in that group.
Then go to a contact record, and create a record with a money amount.
Result:
![civicrm-custom-...Steps to re-create:
* Create a new Custom Field Group, for Contacts, with multi-record enabled.
* Add a money field (text) in that group.
Then go to a contact record, and create a record with a money amount.
Result:
![civicrm-custom-value-formatting](/uploads/6f44d0c3eecfbf7ce0471ed87b2eb49b/civicrm-custom-value-formatting.png)
Expected result: $123.44
When we view the record, it displays correctly:
![Capture_d_écran_de_2020-06-10_12-52-10](/uploads/6cefeae38392e7681effe4c298064db9/Capture_d_écran_de_2020-06-10_12-52-10.png)
I narrowed it down to `CRM_Profile_Page_MultipleRecordFieldsListing::browse()`, but it feels like a mine field.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/44When you have multiple available languages using the language switcher on an ...2020-04-14T14:46:25ZDaveDWhen you have multiple available languages using the language switcher on an angular page gives page not foundI thought I'd seen this reported already but can't find it. Maybe I was thinking of https://lab.civicrm.org/dev/translation/-/issues/23 which is maybe related but seems a bit different. The issue here is the resulting url.
1. On the loc...I thought I'd seen this reported already but can't find it. Maybe I was thinking of https://lab.civicrm.org/dev/translation/-/issues/23 which is maybe related but seems a bit different. The issue here is the resulting url.
1. On the localization page add another language in the "Available languages" field.
1. Visit an angular page like Admin - CiviCase - Case Types.
1. Using the language switcher (on drupal 7 it's in the left sidebar), change the language.
1. It will change the language, but you get a page that just says "Unknown path".https://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.