From 80b3404a5956a2bb539818242f6671cda0a35e5c Mon Sep 17 00:00:00 2001
From: Sean Madsen <sean@seanmadsen.com>
Date: Tue, 7 Nov 2017 17:16:07 -0500
Subject: [PATCH] Improve language and markdown

---
 docs/standards/php.md          |   6 +-
 docs/translation/database.md   | 135 ++++++++++++++++++++++-----------
 docs/translation/extensions.md |  14 ++--
 docs/translation/index.md      |  58 +++++++-------
 4 files changed, 132 insertions(+), 81 deletions(-)

diff --git a/docs/standards/php.md b/docs/standards/php.md
index 08d33390..b4dbb077 100644
--- a/docs/standards/php.md
+++ b/docs/standards/php.md
@@ -101,15 +101,15 @@ Changing these can be quite difficult and can break interfaces consumed by downs
 
 ## Localization
 
-Any string that will be displayed to the user should be wrapped in ts() to translate the string:
+Any string that will be displayed to the user should be wrapped in `ts()` to translate the string:
 
-```
+```php
 $string = ts("Hello, world!");
 ```
 
 Translation strings can also include placeholders for variables:
 
-```
+```php
 $string = ts("Membership for %1 has been updated. The membership End Date is %2.", array(
   1 => $userDisplayName,
   2 => $endDate,
diff --git a/docs/translation/database.md b/docs/translation/database.md
index 67e3f1e5..0b8b7194 100644
--- a/docs/translation/database.md
+++ b/docs/translation/database.md
@@ -7,15 +7,23 @@ We try to reduce the number of strings that will be practically never seen by ad
 For example, in `CRM_Upgrade_Incremental_php_FourSeven`, `addTask()` task names such as "Upgrade DB to ..." should be translated:
 
 ```php
-$this->addTask(ts('Upgrade DB to %1: SQL', array(1 => '4.3.5')), 'task_4_3_x_runSql', $rev);
+$this->addTask(
+  ts('Upgrade DB to %1: SQL', array(1 => '4.3.5')),
+  'task_4_3_x_runSql',
+  $rev
+);
 ```
 
-Very specific one-time tasks should not be translated (wrapped in "ts"). Administrators are very unlikely to see such strings. If they do, they will probably need the original English string in order to get support on the forums. They are also strings that are very hard to translate because of lack of context.
+Very specific one-time tasks should not be translated (wrapped in `ts`). Administrators are very unlikely to see such strings. If they do, they will probably need the original English string in order to get support on the forums. They are also strings that are very hard to translate because of lack of context.
 
 For example, do not translate:
 
 ```php
-$this->addTask('Update financial_account_id in financial_trxn table', 'updateFinancialTrxnData', $rev);
+$this->addTask(
+  'Update financial_account_id in financial_trxn table',
+  'updateFinancialTrxnData',
+  $rev
+);
 ```
 
 ## Localized fields
@@ -33,15 +41,15 @@ However, since localizable fields add a certain technical complexity, the follow
 
 While there are many cities where street names can officially be in multiple languages (or have official transliterations), users usually enter their address only in one language. It is rarely required to store the address translation (one exception: event locations, which is currently a known limitation).
 
-Similarly, the first and last name of an individual may be written in different alphabets (ex: Latin and Cyrillic), but this is not a frequent use-case worth the complexity. Adminstrators can workaround this by creating custom fields.
+Similarly, the first and last name of an individual may be written in different alphabets (ex: Latin and Cyrillic), but this is not a frequent use-case worth the complexity. Administrators can workaround this by creating custom fields.
 
-In order to define a field as localizable, the XML schema files must have the following tag:
+In order to define a field as localizable, the [XML schema definition](/framework/database/schema-definition.md) for that field must have the following tag:
 
 ```
 <localizable>true</localizable>
 ```
 
-If a new field was not initially tagged as localizable, the upgrade must explicitely convert the field. See the section below on localised fields schema changes.
+If a new field was not initially tagged as localizable, the upgrade must explicitly convert the field. See the section below on localised fields schema changes.
 
 ## SQL upgrades
 
@@ -52,62 +60,99 @@ SQL upgrades must account for two use-cases:
 
 There are two variables exposed to the sql templates when upgrading: `$multilingual` makes it possible to test if the database is multi-lingual, while `$locales` lists the enabled languages. For example:
 
-```
+```smarty
 {if $multilingual}
   {foreach from=$locales item=locale}
-    UPDATE civicrm_option_group SET label_{$locale} = description_{$locale} WHERE label_{$locale} IS NULL;
+    UPDATE civicrm_option_group
+    SET label_{$locale} = description_{$locale}
+    WHERE label_{$locale} IS NULL;
   {/foreach}
 {else}
-  UPDATE civicrm_option_group SET `label` = `description` WHERE `label` IS NULL;
+  UPDATE civicrm_option_group
+  SET `label` = `description`
+  WHERE `label` IS NULL;
 {/if}
 ```
 
-However the `{localize}` helper for SQL upgrades (e.g. statements in `CRM/Upgrade/Incremental/sql/*.mysql.tpl` files)  allows you do the same thing without explicitly looping on locales. This UPDATE statement handles both multi-lingual and non-multi-lingual cases.
+However the `{localize}` helper for SQL upgrades (e.g. statements in `CRM/Upgrade/Incremental/sql/*.mysql.tpl` files)  allows you do the same thing without explicitly looping on locales. This `UPDATE` statement handles both multi-lingual and non-multi-lingual cases.
 
-```
-UPDATE `civicrm_premiums` SET {localize field="premiums_nothankyou_label"}premiums_nothankyou_label = '{ts escape="sql"}No thank-you{/ts}'{/localize};
+```smarty
+UPDATE `civicrm_premiums`
+SET
+  {localize field="premiums_nothankyou_label"}
+    premiums_nothankyou_label = '{ts escape="sql"}No thank-you{/ts}'
+  {/localize};
 ```
 
 On a multi-lingual site with English and French enabled, this would evaluate to:
 
-```
-UPDATE `civicrm_premiums` SET premiums_nothankyou_label_en_US = 'No thank-you', premiums_nothankyou_label_fr_FR = 'Non merci';
-```
-
-The `{ts}` tag translates the string based on the default language that is set WHEN THE UPGRADE IS BEING RUN. In the above example if the upgrade was run while the default language was French, that column would be set to "Merci non". It would be good to fix this so that the values for each enabled language are translated when a translated string is available.
-
-For an INSERT example, the following query:
-
-```
-INSERT INTO civicrm_option_value
-   (option_group_id, {localize field='label'}label{/localize}, value, name,  filter,  weight, is_active )
-VALUES
-   (@option_group_id_ere, {localize}'{ts escape="sql"}Participant Role{/ts}'{/localize}, 1, 'participant_role', 0,  1, 1 );
-```
-
-On a multi-lingual site with English and French enabled, would evaluate to:
-
-```
-INSERT INTO civicrm_option_value
-   (option_group_id, label_en_US, label_fr_FR, value, name,  filter,  weight, is_active )
-VALUES
-   (@option_group_id_ere, 'Participant Role', 'Rôle du participant', 1, 'participant_role', 0,  1, 1 );
+```sql
+UPDATE `civicrm_premiums`
+SET
+  premiums_nothankyou_label_en_US = 'No thank-you',
+  premiums_nothankyou_label_fr_FR = 'Non merci';
+```
+
+The `{ts}` tag translates the string based on the default language that is set _when the upgrade is being run_. In the above example if the upgrade was run while the default language was French, that column would be set to "Merci non". It would be good to fix this so that the values for each enabled language are translated when a translated string is available.
+
+For an `INSERT` example, the following query:
+
+```smarty
+INSERT INTO civicrm_option_value (
+  option_group_id,
+  {localize field='label'}label{/localize},
+  value,
+  name,
+  filter,
+  weight,
+  is_active )
+VALUES (
+  @option_group_id_ere,
+  {localize}'{ts escape="sql"}Participant Role{/ts}'{/localize},
+  1,
+  'participant_role',
+  0,
+  1,
+  1 );
+```
+
+On a multi-lingual site with English and French enabled, the above would evaluate to:
+
+```sql
+INSERT INTO civicrm_option_value (
+  option_group_id,
+  label_en_US,
+  label_fr_FR,
+  value,
+  name,
+  filter,
+  weight,
+  is_active )
+VALUES (
+  @option_group_id_ere,
+  'Participant Role',
+  'Rôle du participant',
+  1,
+  'participant_role',
+  0,
+  1,
+  1 );
 ```
 
 ## Localised fields schema changes
 
 Two use-cases:
 
-1- An existing field in CiviCRM was not tagged in the xml schema as `<localizable>` (ex: the `title` in `civicrm_survey`, before CiviCRM 4.5). After adding the `<localize>` tag in the XML file, you must also add an upgrade snippet for exsting databases. Example, from sql/4.1.0.mysql.tpl:
+1. An existing field in CiviCRM was not tagged in the [XML schema](/framework/database/schema-definition.md) as `<localizable>` (ex: the `title` in `civicrm_survey`, before CiviCRM 4.5). After adding the `<localize>` tag in the XML file, you must also add an upgrade snippet for existing databases. Example, from `sql/4.1.0.mysql.tpl`:
 
-```
-{if $multilingual}
-  {foreach from=$locales item=locale}
-      ALTER TABLE civicrm_pcp_block ADD link_text_{$locale} varchar(255);
-      UPDATE civicrm_pcp_block SET link_text_{$locale} = link_text;
-  {/foreach}
-  ALTER TABLE civicrm_pcp_block DROP link_text;
-{/if}
-```
+    ```smarty
+    {if $multilingual}
+      {foreach from=$locales item=locale}
+          ALTER TABLE civicrm_pcp_block ADD link_text_{$locale} varchar(255);
+          UPDATE civicrm_pcp_block SET link_text_{$locale} = link_text;
+      {/foreach}
+      ALTER TABLE civicrm_pcp_block DROP link_text;
+    {/if}
+    ```
 
-2- A localized field was removed or added, the schema during the upgrade does odd things to figure out which fields are mutli-lingual. Rebuilding the multi-lingual schema will check in CRM/Core/I18n/SchemaStructure.php for the fields used by the database views. If the schema is changed, copy the SchemaStructure.php from the master branch to, for example, SchemaStructure_4_5_alpha1.php. The 4.5 alpha1 will then read this file when rebuilding the schema, see CRM/Core/I18n/Schema.php for more information (getLatestSchema). i.e. during an upgrade, we may be upgrading from 4.0 to 4.5, and when rebuilding the views at each stage, we need to load the correct schema version. Since we do not have a schema file for each minor version, CiviCRM will attempt to load the most relevant schema version to the version of the upgrade step being run.
+2. If a localized field was removed or added, the schema does odd things during the upgrade to figure out which fields are mutli-lingual. Rebuilding the multi-lingual schema will check in `CRM/Core/I18n/SchemaStructure.php` for the fields used by the database views. If the schema is changed, copy the `SchemaStructure.php` from the master branch to, for example, `SchemaStructure_4_5_alpha1.php`. The 4.5 alpha1 will then read this file when rebuilding the schema, see `CRM/Core/I18n/Schema.php` for more information (`getLatestSchema`). i.e. during an upgrade, we may be upgrading from 4.0 to 4.5, and when rebuilding the views at each stage, we need to load the correct schema version. Since we do not have a schema file for each minor version, CiviCRM will attempt to load the most relevant schema version to the version of the upgrade step being run.
diff --git a/docs/translation/extensions.md b/docs/translation/extensions.md
index 0d84e817..5e330199 100644
--- a/docs/translation/extensions.md
+++ b/docs/translation/extensions.md
@@ -1,20 +1,20 @@
 # Extensions Translation
 
-For developing a CiviCRM extension in a way that can be translated, all the best practices described in the Internationalisation for Developers page apply. This page describes special considerations that need to be taken in count for achieving this.
+For developing a CiviCRM extension in a way that can be translated, all the best practices described in the [Internationalisation for Developers](/translation/index.md) page apply. This page describes special considerations that need to be taken into account for extensions.
 
 ## For translators: Translating strings on Transifex
 
-There is a separate project on Transifex to translate extensions. Each extension has its own "resource". Therefore, when a translator joins a translation team, he/she can translate all extensions. We didn't see a need to separate each extension in a separate project, because each extension should have only one translation (.po) file.
+There is a separate project on Transifex to translate extensions. Each extension has its own "resource". Therefore, when a translator joins a translation team, they can translate all extensions. We didn't see a need to separate each extension in a separate project, because each extension should have only one translation (`.po`) file.
 
-See: https://www.transifex.com/projects/p/civicrm_extensions/
+See: <https://www.transifex.com/projects/p/civicrm_extensions/>
 
 ## For administrators: Download translation files for extensions
 
 The easiest way to download translations for extensions is to use the [l10nupdate](https://github.com/cividesk/com.cividesk.l10n.update/) extension.
 
-## For developers: Correct usage of the ts() function
+## For developers: Correct usage of the `ts()` function
 
-In PHP, Smarty, and JS code, the convention is to perform translations using the `ts()` helper function. This is the same as in core code – with the additional requirement that one must specify the "domain" so that the translation engine can use the correct dictionary (.mo file) at run-time.
+In PHP, Smarty, and JS code, the convention is to perform translations using the `ts()` helper function. This is the same as in core code &mdash; with the additional requirement that one must specify the "domain" so that the translation engine can use the correct dictionary (`.mo` file) at run-time.
 
 PHP:
 
@@ -27,7 +27,7 @@ $string = ts('Hello, %1', array(
  
 Smarty templates:
 
-```
+```smarty
 {crmScope extensionKey='org.example.myextension'}
   <p>{ts 1=$display_name}Hello, %1{/ts}</p>
 {/crmScope}
@@ -51,6 +51,6 @@ $scope.ts = CRM.ts('org.example.myextension');
 
 Angular HTML templates:
 
-```
+```html
 <p>{{ts('Hello, %1', {1: display_name})}}</p>
 ```
diff --git a/docs/translation/index.md b/docs/translation/index.md
index e3280cb3..19649a61 100644
--- a/docs/translation/index.md
+++ b/docs/translation/index.md
@@ -2,11 +2,11 @@
 
 When writing new application code, developers should organize their code in a way which is amenable to internationalization, so that it may be localized to various languages and regions of the world.
 
-If you are an extension developer, there is additional documentation in the [Extension translation](/translation/extensions.md] page.
+If you are an extension developer, there is additional documentation in the [Extension translation](/translation/extensions.md) page.
 
 ## PHP
 
-The strings hard-coded into PHP should be wrapped in ts() function calls. Here are a few examples:
+The strings hard-coded into PHP should be wrapped in `ts()` function calls. Here are a few examples:
 
 ```php
 $string = ts('Hello, World!');
@@ -74,7 +74,7 @@ else {
 
 ## Javascript
 
-When translating strings in an extension, ts scope needs to be declared. The CRM.ts function takes scope as an argument and returns a function that always applies that scope to ts calls:
+When translating strings in an extension, ts scope needs to be declared. The `CRM.ts` function takes scope as an argument and returns a function that always applies that scope to ts calls:
 
 ```js
 // This closure gets a local copy of jQuery, Lo-dash, and ts
@@ -83,37 +83,43 @@ When translating strings in an extension, ts scope needs to be declared. The CRM
 })(CRM.$, CRM._, CRM.ts('foo.bar.myextension'));
 ```
 
-Note that `CRM.ts` is not the same as the global `ts` function. `CRM.ts` is a function that returns a function (javascript is wacky like that). Since your closure gives the local `ts` the same name as the global `ts`, it will be used instead.
+!!! note
+    `CRM.ts` is not the same as the global `ts` function. `CRM.ts` is a function that returns a function (javascript is wacky like that). Since your closure gives the local `ts` the same name as the global `ts`, it will be used instead.
 
-Important: Your local version of `ts` could be named anything, but strings in your javascript file cannot be accurately parsed unless you name it ts.
+!!! important
+    Your local version of `ts` could be named anything, but strings in your javascript file cannot be accurately parsed unless you name it `ts`.
 
 ## Smarty templates
 
-The strings hard-coded into templates should be wrapped in `{ts}...{/ts}` tags. For example:
+* The strings hard-coded into templates should be wrapped in `{ts}...{/ts}` tags. For example:
 
-```
-{ts}Full or partial name (last name, or first name, or organization name).{/ts}
-```
+    ```smarty
+    {ts}Full or partial name (last name, or first name, or organization name).{/ts}
+    ```
 
-If you need to pass a variable to the localisable string, you should use the following pattern:
+* If you need to pass a variable to the localizable string, you should use the following pattern:
 
-```
-<div class="status">{ts 1=$delName}Are you sure you want to delete <b>%1</b> Tag?{/ts}</div>
-```
+    ```smarty
+    <div class="status">
+      {ts 1=$delName}Are you sure you want to delete <b>%1</b> Tag?{/ts}
+    </div>
+    ```
 
-When possible, avoid HTML formatting and newlines inside `{ts}...{/ts}` tags. For example:
+* When possible, avoid HTML formatting and newlines inside `{ts}...{/ts}` tags. 
 
-```
-<p>{ts}Hello, world!{/ts}</p>
-```
-
-and not:
+    * Good
 
-```
-{ts}<p>This is a bad example.</p>{/ts}
-```
+        ```smarty
+        <p>{ts}Hello, world!{/ts}</p>
+        ```
+    
+    * Bad
+    
+        ```
+        {ts}<p>Hello, world!</p>{/ts}
+        ```
 
-## Why not use the Drupal locale module?
+## Rationale for using Gettext
 
 In most projects, strings are typically translated by either:
 
@@ -127,6 +133,6 @@ In order to be support Joomla!, WordPress, Backdrop and eventually other content
 
 Here are the guides to other popular projects:
 
-* Drupal: https://www.drupal.org/node/322729
-* Joomla!: https://docs.joomla.org/Specification_of_language_files
-* WordPress: https://codex.wordpress.org/I18n_for_WordPress_Developers
+* Drupal: <https://www.drupal.org/node/322729>
+* Joomla!: <https://docs.joomla.org/Specification_of_language_files>
+* WordPress: <https://codex.wordpress.org/I18n_for_WordPress_Developers>
-- 
GitLab