Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ jobs:
- run: npm install --prefix assets
- run: npm --prefix assets run webpack:build
- run: mix compile --all-warnings
- name: Check localizations up-to-date
run: mix gettext.extract --check-up-to-date

elixir_unit:
name: Unit tests / Elixir / mix coveralls.html
Expand Down
55 changes: 0 additions & 55 deletions .github/workflows/translator.yml

This file was deleted.

50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,56 @@ Then, start the server with `iex -S mix phx.server`

Then, visit the site at http://localhost:4001.

## How to support translations

### Internationalizing strings in the application

User-facing interfaces in Dotcom are internationalized, supporting 6 key languages.

This is done via [the `Gettext` Elixir library](https://hex.pm/packages/gettext), which uses
[the GNU `gettext` tool](https://www.gnu.org/software/gettext) under the hood,
[managing `.po` files for message strings](https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html).

To internationalize a string in an interface, do the following:

- Wrap strings to be translated in the `gettext` function, i.e. `gettext("your string here")`.
Note that you may need to wrap the function call in `{...}` for attribute strings and
`<%= ... %>` for text on the page.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: HEEx works with {} for text on the page as well, so 👇 are equivalent.

<span><%= foo(@bar) %></span>
<span>{foo(@bar)}</span>

All that to say, you can drop the "<%= ... %> for text on the page" part of this note.


#### Rules Of Gettext

1. No newlines inside a gettext call. Newlines are a new gettext call.
2. Don't start or end with whitespace. If you break a sentence up, leave the whitespace in the HTML untranslated.
3. If you break apart a sentence across multiple gettext calls, use `pgettext` and add context including the full sentence to help translators. Grep the app for `pgettext` for examples.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the sort of thing that would apply to links... e.g. in a sentence like "transfer to the Orange Line at Downtown Crossing"?


Note that new strings will default to English language until translations are provided for them.

### Preparing for Translations

We use Smartling as our department approved vendor to complete translations - this is done through GitHub integrations.

Smartling GitHub integration tracks main to see if changes are made to the translation files in PRs developers open. If this does happen, Smartling opens up seperate PRs to introduce the translated content for all of our supported languages to merge into the PR developers open.

Here is the workflow for making updates to copy in Dotcom and completing translations:
1. Make your changes in a branch (note that content branches should NOT begin with "smartling.") Localize the content in Dotcom using `gettext` as described in the above section.
2. Run `mix localize` to update the `gettext` translation files.
* If this isn't run - we have a CI check to fail the build if the translation files are out of date, so there will be no
way to merge in changes without updated translations.
3. Put up the changes in your branch to a PR. You will notice a `Not ready for translation` label automatically gets applied to your PR. **When your PR is reviewed and approved (but before it is merged), remove the label.**
3. After some time, a Smartling machine translation PR will be opened, merging the translated content into your PR.
4. Review the Smartling PR, approve, and merge it into your PR. The translated content will now be available in your PR.
5. Get your updated feature PR merged into main.

### How to review Smartling PRs
What's good to check for in review:
* Making sure nothing is glaringly wrong or off
* Do the files have translations (as opposed to empty strings etc.)?
* Glance over the file and make sure its structure looks reasonable
* Ensuring nothing is broken feature-wise/UX-wise

What you _don't_ need to worry about:
* Reviewing the translations themselves for correctness

## Algolia

[Algolia](https://www.algolia.com) powers our search features. Sometimes after content updates or GTFS releases we will find that the search results do not contain up-to-date results. When this happens you can re-index the Algolia data by running: `mix algolia.update`.
Expand Down
2 changes: 1 addition & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ config :dotcom, :httpoison, HTTPoison

config :dotcom,
default_locale_code: "en",
locale_codes: ["en", "es", "ht", "pt", "vi", "zh"]
locale_codes: ["en", "es", "ht", "pt-BR", "vi", "zh-CN", "zh-TW", "fr-FR"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: I think by virtue of adding fr-FR, you've caused another .po file to com into existence on mix compile. Would it make sense to commit that file as well?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotta be honest - I was rushing when I typed this - it's not a .po file 🤦‍♂️ - it's a JSON file - priv/cldr/locales/fr.json.

I stand by my question/suggestion/request to commit it though!


config :dotcom, :location_service, LocationService

Expand Down
32 changes: 30 additions & 2 deletions lib/dotcom/gettext/plural.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
defmodule Dotcom.Gettext.Plural do
@moduledoc false
@moduledoc """
This module defines plural form equations for languages for PO files.

use Cldr.Gettext.Plural, cldr_backend: Dotcom.Cldr
Plural forms are documented in the gettext docs here:
https://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms

There's a list of plural forms for most languages here:
https://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html
"""
@behaviour Gettext.Plural

# Haitian Creole is not supported by default by Gettext.Plural (which uses Expo.PluralForms)
def nplurals("ht"), do: 2

# Gettext.Plural forwards xx_YY to xx for plurals, but not xx-YY, so this patches that
def nplurals(<<locale::binary-size(2)>> <> "-" <> _sublocale),
do: Gettext.Plural.nplurals(locale)

# Fall back to Gettext.Plural
defdelegate nplurals(locale), to: Gettext.Plural

# Haitian Creole is not supported by default by Gettext.Plural (which uses Expo.PluralForms)
def plural("ht", 1), do: 0
def plural("ht", _), do: 1

# Gettext.Plural forwards xx_YY to xx for plurals, but not xx-YY, so this patches that
def plural(<<locale::binary-size(2)>> <> "-" <> _sublocale, count),
do: Gettext.Plural.plural(locale, count)

# Fall back to Gettext.Plural
defdelegate plural(locale, n), to: Gettext.Plural
end
6 changes: 0 additions & 6 deletions lib/dotcom/locales.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ defmodule Dotcom.Locales do
@development_additional_locales
end

# @future_locales [
# %Locale{code: "ht", endonym: "Kreyòl Ayisyen"},
# %Locale{code: "pt", endonym: "Português"},
# %Locale{code: "vi", endonym: "Tiếng Việt"},
# %Locale{code: "zh", endonym: "中文"}
# ]
@locales [
@default_locale,
@development_locale
Expand Down
Loading
Loading