Skip to content

Commit 342fd04

Browse files
[Tooling] Add Localization sync job (#770)
* Use latest release-toolkit Gem * Add Fluent / PO localization lanes * Update source PO file (en-US.pot) to be synced to GlotPress * Update generated Fluent files based on latest GlotPress translations * Update release-toolkit * Fix Rubocop violations * Run bundle update * Create temporary dir for downloading PO files and use open-uri for downloading * Update code to use `fluent-tools` Gem * Update generated source PO file * Update generated Fluent files based on latest GlotPress translations * Add job and script to sync localization files * Update lanes to not push automatically * Update sync script to only push at the end * Add localization README file * Reorder helper lane * Validate file_path at the beginning of the `generate_fluent_file_from_po` lane * Update code to exit early in `download_translations` when there are no downloaded files * Add all locales supported by the iOS and Android apps h/t to @crazytonyli for highlighting that the supported locales should be a combination of the locales supported in the iOS and Android apps #765 (comment) * Add generated Fluent files with the updated list of supported locales * Update fluent-tools to 0.2.0 and re-generate localization files with the latest version * Update to 0.3.0 release * Update PO file with latest fluent-tools * Add IMAGE to nightly localization sync job * Add ci-toolkit plugin to localization sync job * Make sure to checkout branch (given we're pushing later) * Update source PO file (en-US.pot) to be synced to GlotPress --------- Co-authored-by: Automattic Release Bot <[email protected]>
1 parent 44cfe64 commit 342fd04

File tree

4 files changed

+109
-14
lines changed

4 files changed

+109
-14
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash -euo pipefail
2+
3+
echo "--- :git: Checking out the current branch"
4+
BRANCH="${BUILDKITE_BRANCH:-trunk}"
5+
git checkout "${BRANCH}"
6+
git pull origin "${BRANCH}"
7+
8+
echo '--- :robot_face: Use bot for Git operations'
9+
source use-bot-for-git
10+
11+
echo "--- :rubygems: Setting up Gems"
12+
install_gems
13+
14+
echo "--- :globe_with_meridians: :arrow_up: Generate the source language PO file for GlotPress based on `wp_localization/localization/en-US/main.ftl`"
15+
bundle exec fastlane generate_source_po_file commit_changes:true
16+
17+
echo "--- :globe_with_meridians: :arrow_down: Download and update translations from GlotPress and update the local Fluent files"
18+
bundle exec fastlane download_translations commit_changes:true
19+
20+
git push origin

.buildkite/nightly.yml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,25 @@ steps:
33
command: |
44
echo "--- :rust: Testing"
55
make test-rust-integration-wordpress-org-api
6+
notify:
7+
- slack:
8+
channels:
9+
- "#wordpress-rs"
10+
message: "Nightly build failed."
11+
if: build.state == "failed"
612
env:
713
TEST_ALL_PLUGINS: true
814

9-
notify:
10-
- slack:
11-
channels:
12-
- "#wordpress-rs"
13-
message: "Nightly build."
14-
if: build.state == "failed"
15+
- label: ":globe_with_meridians: :arrow_up: :arrow_down: Sync localization"
16+
command: .buildkite/commands/sync-localization.sh
17+
plugins: [$CI_TOOLKIT]
18+
notify:
19+
- slack:
20+
channels:
21+
- "#wordpress-rs"
22+
message: "Localization sync failed."
23+
if: build.state == "failed"
24+
env:
25+
IMAGE_ID: $IMAGE_ID
26+
agents:
27+
queue: mac

fastlane/Fastfile

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,9 @@ end
178178
#
179179
# The resulting PO file is saved as the source file (.pot) for translations and is synced to GlotPress.
180180
#
181-
# @param commit_and_push_changes [Boolean] Whether to commit and push the generated PO file (default: false)
181+
# @param commit_changes [Boolean] Whether to commit the generated PO file (default: false)
182182
#
183-
lane :generate_source_po_file do |commit_and_push_changes: false|
183+
lane :generate_source_po_file do |commit_changes: false|
184184
UI.header('🔄 Converting English Fluent file to PO format')
185185

186186
FileUtils.mkdir_p(File.dirname(LOCALIZATION_PO_SOURCE_FILE))
@@ -201,7 +201,7 @@ lane :generate_source_po_file do |commit_and_push_changes: false|
201201
UI.error("❌ Failed to convert English Fluent file: #{e.message}")
202202
end
203203

204-
if commit_and_push_changes
204+
if commit_changes
205205
commit_changed_files(
206206
files: LOCALIZATION_PO_SOURCE_FILE,
207207
message: 'Update source PO file (en-US.pot) to be synced to GlotPress'
@@ -212,11 +212,11 @@ end
212212
# Downloads the latest translations from GlotPress and updates Fluent files
213213
#
214214
# This lane fetches translated PO files from GlotPress for all supported locales,
215-
# converts them back to Fluent format, and optionally commits and pushes the changes.
215+
# converts them back to Fluent format, and optionally commits the changes.
216216
#
217-
# @param commit_and_push_changes [Boolean] Whether to commit and push the updated Fluent files (default: false)
217+
# @param commit_changes [Boolean] Whether to commit the updated Fluent files (default: false)
218218
#
219-
lane :download_translations do |commit_and_push_changes: false|
219+
lane :download_translations do |commit_changes: false|
220220
UI.header('🌐 Downloading translations from GlotPress')
221221

222222
Dir.mktmpdir do |temp_download_dir|
@@ -239,7 +239,7 @@ lane :download_translations do |commit_and_push_changes: false|
239239

240240
UI.success("✅ Updated Fluent files: #{updated_fluent_files.length} locales")
241241

242-
if commit_and_push_changes && updated_fluent_files.any?
242+
if commit_changes && updated_fluent_files.any?
243243
commit_changed_files(
244244
files: updated_fluent_files,
245245
message: 'Update generated Fluent files based on latest GlotPress translations'
@@ -344,7 +344,7 @@ def remove_lane_context_values(names)
344344
names.each { |name| lane_context.delete(name) }
345345
end
346346

347-
def commit_changed_files(files:, message:, push: true)
347+
def commit_changed_files(files:, message:, push: false)
348348
git_add(path: files)
349349
result = git_commit(
350350
path: files,

wp_localization/README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Localization
2+
3+
This directory contains the localization files for `wordpress-rs`, enabling a translation workflow between Fluent localization files (`.ftl`) and GlotPress.
4+
5+
We use GlotPress as a platform/service to have translators translate our strings from English to other languages.
6+
But GlotPress does not support Rust's Fluent `.ftl` format as an input/output file format.
7+
8+
To circumvent that, during the localization automation process, we convert the `localization/en-US/main.ftl` file to the PO format in `glopress/en-US.pot` so that a cron job can then later pick up that `.pot` file and upload it to GlotPress and send it to translators.
9+
This transformation is handled by `bundle exec fastlane generate_source_po_file`.
10+
11+
Later we then download the translations from GlotPress (which are exported in the `.po` format), then regenerate the `localization/*/main.ftl` files for each language based on those downloaded translated `.po` files.
12+
This is handled by `bundle exec fastlane download_translations`
13+
14+
_Note that we have to commit the `glotpress/en-US.pot` file here because that file is picked up by a cron job in our systems on a regular basis (as opposed to the `.pot` being sent via API on demand) given how those imports are integrated in our systems._
15+
16+
## Workflow for Developers
17+
18+
### Automated Daily Sync
19+
20+
The localization process runs automatically every night via a Buildkite pipeline (`.buildkite/nightly.yml`). This automated job:
21+
22+
1. **Generates the source en-US PO file** from `localization/en-US/main.ftl` and commits it to `glotpress/en-US.pot`
23+
2. **Downloads latest translations** from GlotPress for all supported locales as PO files
24+
3. **Converts downloaded PO files to Fluent format** and updates the corresponding `localization/*/main.ftl` files
25+
4. **Commits the updated translation files** to the repository
26+
27+
This means that translation updates happen automatically without developer intervention.
28+
29+
### Adding New Localization Strings
30+
31+
1. **Add strings to the source file**: Edit `wp_localization/localization/en-US/main.ftl` to add or update localization strings.
32+
33+
2. **The automated nightly job will handle the rest**: The next nightly run will automatically:
34+
- Convert your changes to PO format (`glotpress/en-US.pot`)
35+
- Commit the updated source file
36+
- Upload to GlotPress via the wpcom cron job
37+
38+
### Manual Operations (Optional)
39+
40+
If you need to run the localization sync manually instead of waiting for the nightly job:
41+
42+
**Generate source PO file:**
43+
```bash
44+
bundle exec fastlane generate_source_po_file
45+
```
46+
47+
**Download GlotPress translations and generate local Fluent translation files:**
48+
```bash
49+
bundle exec fastlane download_translations
50+
```
51+
52+
### Helper Lanes
53+
54+
- **`download_po_files_from_glotpress`**: Downloads PO files for all supported locales
55+
- **`generate_fluent_file_from_po`**: Converts individual PO files back to Fluent format
56+
57+
## References
58+
59+
- **Fluent format**: Uses [Project Fluent](https://projectfluent.org/) for localization files
60+
- **PO format**: Standard [gettext](https://www.gnu.org/software/gettext/manual/gettext.html) format used by GlotPress
61+
- **Conversion tool**: Uses the [fluent-tools](https://github.com/Automattic/fluent-rust-tools) Ruby gem for format conversion
62+
- **GlotPress integration**: Downloads translations from `https://translate.wordpress.com/projects/mobile/wordpress-rs`

0 commit comments

Comments
 (0)