Skip to content

Commit

Permalink
Add scripts to build localization on local machine (#2701)
Browse files Browse the repository at this point in the history
* Add scripts to build localization on local machine

* Remove unneeded parameters from LocProject

* Ignore files generated by local localization build

* Add copy translations script to Dist pipeline

* Remove destination JSON path parameter

* Change scripts to use new translation function

* Add json files when script is run locally

* Change name for download artifacts pipeline

* Add npm commands to run localization scripts

* Add README with localization setup instructions

* Rename destRESJSON, fix script, and other PR fixes

* Silence New-Item and add clean resources task

* Use powershell and modify clean script on desktop

* Replace cross-env-shell for npm loc:restore script
  • Loading branch information
skapur12 committed Apr 11, 2023
1 parent e3b6cfa commit 635d441
Show file tree
Hide file tree
Showing 24 changed files with 295 additions and 81 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@
/desktop/release/
coverage/
env/
Localize/packages/
Localize/out/
/desktop/resources/i18n/*
/packages/common/resources/i18n/*
/packages/playground/resources/i18n/*
/packages/react/resources/i18n/*
/packages/service/resources/i18n/*
/util/bux/resources/i18n/json
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ docs
.vscode

package-lock.json

Localize/out/
Localize/packages/
/**/resources/
8 changes: 8 additions & 0 deletions .vsts/common/download-i18n-artifacts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
steps:
- task: DownloadBuildArtifacts@0
displayName: 'Download Localization Build Artifacts'
inputs:
buildType: 'current'
downloadType: 'single'
artifactName: 'drop'
downloadPath: '$(Agent.BuildDirectory)'
2 changes: 1 addition & 1 deletion .vsts/common/publish-artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ parameters:

steps:
- task: PublishBuildArtifacts@1
displayName: Publish artifacts
displayName: Publish application artifacts
inputs:
pathtoPublish: ./desktop/release
artifactName: ${{ parameters.folder }}
Expand Down
6 changes: 6 additions & 0 deletions .vsts/darwin/distribution.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
steps:
- template: ../common/set-dist-vars.yml
- template: ./darwin-dependencies.yml
- template: ../common/download-i18n-artifacts.yml

- script: |
pwsh -File "$(System.DefaultWorkingDirectory)/Localize/copy-translations.ps1" -artifactsPath "$(Agent.BuildDirectory)/drop/loc"
displayName: 'Run copy-translations.ps1 with artifacts path (macOS)'
- script: |
set -e
. "$(Agent.WorkFolder)/.venv/batchexplorer/bin/activate"
Expand Down
9 changes: 0 additions & 9 deletions .vsts/distribution.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,8 @@ stages:
dependsOn: Localization
condition: succeeded('Localization')
jobs:
- job: DownloadArtifacts
pool:
name: Azure-Pipelines-EO-Batch-Explorer
steps:
- download: current
artifact: drop

- job: Linux
dependsOn: DownloadArtifacts
pool:
name: Azure-Pipelines-EO-Batch-Explorer
demands:
Expand All @@ -42,7 +35,6 @@ stages:
- template: ./linux/distribution.yml

- job: MacOS
dependsOn: DownloadArtifacts
pool:
vmImage: macOS-11
demands: xcode
Expand All @@ -53,7 +45,6 @@ stages:
- template: ./darwin/distribution.yml

- job: Windows
dependsOn: DownloadArtifacts
pool:
name: Azure-Pipelines-EO-Batch-Explorer
demands:
Expand Down
6 changes: 6 additions & 0 deletions .vsts/linux/distribution.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
steps:
- template: ../common/set-dist-vars.yml
- template: ./linux-dependencies.yml
- template: ../common/download-i18n-artifacts.yml

- script: |
pwsh -File "$(System.DefaultWorkingDirectory)/Localize/copy-translations.ps1" -artifactsPath "$(Agent.BuildDirectory)/drop/loc"
displayName: 'Run copy-translations.ps1 with artifacts path (Linux)'
- script: |
set -e
. "$(Agent.WorkFolder)/.venv/batchexplorer/bin/activate"
Expand Down
5 changes: 5 additions & 0 deletions .vsts/win/distribution.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ steps:
- template: ../common/set-dist-vars.yml
- template: ./credscan.yml
- template: ./win-dependencies.yml
- template: ../common/download-i18n-artifacts.yml

- powershell: |
$(System.DefaultWorkingDirectory)/Localize/copy-translations.ps1 -artifactsPath "$(Agent.BuildDirectory)/drop/loc"
displayName: 'Run copy-translations.ps1 with artifacts path (Windows)'
- powershell: |
$version = npm run -s ts scripts/package/get-version
Expand Down
20 changes: 5 additions & 15 deletions Localize/LocProject.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,19 @@
"LanguageSet": "Azure_LanguagesExt",
"LocItems": [
{
"SourceFile": "packages\\common\\i18n\\resources.resjson",
"CopyOption": "LangIDOnName",
"OutputPath": "packages\\common\\i18n"
"SourceFile": "packages\\common\\i18n\\resources.resjson"
},
{
"SourceFile": "packages\\playground\\i18n\\resources.resjson",
"CopyOption": "LangIDOnName",
"OutputPath": "packages\\playground\\i18n"
"SourceFile": "packages\\playground\\i18n\\resources.resjson"
},
{
"SourceFile": "packages\\react\\i18n\\resources.resjson",
"CopyOption": "LangIDOnName",
"OutputPath": "packages\\react\\i18n"
"SourceFile": "packages\\react\\i18n\\resources.resjson"
},
{
"SourceFile": "packages\\service\\i18n\\resources.resjson",
"CopyOption": "LangIDOnName",
"OutputPath": "packages\\service\\i18n"
"SourceFile": "packages\\service\\i18n\\resources.resjson"
},
{
"SourceFile": "desktop\\i18n\\resources.resjson",
"CopyOption": "LangIDOnName",
"OutputPath": "desktop\\i18n"
"SourceFile": "desktop\\i18n\\resources.resjson"
}
]
}
Expand Down
42 changes: 42 additions & 0 deletions Localize/build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# build.ps1
$RepoRoot = (Resolve-Path "$PSScriptRoot\..").Path
$LocProject = Join-Path $PSScriptRoot "LocProject.json"
$LocalizationXLocPkgVer = "2.0.7"

$OutDir = Join-Path $PSScriptRoot "out"
$NUGET_PACKAGES = Join-Path $PSScriptRoot "packages"
$XLocPath = Join-Path $NUGET_PACKAGES "Localization.XLoc.$LocalizationXLocPkgVer"

# Uncomment and set the following variable if needed
# $LocCustomPowerShellScript = "{path to the script to customize localized files}"

Write-Host "Running Localization..."

# Set the RepoRoot and NUGET_PACKAGES environment variables
$env:RepoRoot = $RepoRoot
$env:NUGET_PACKAGES = $NUGET_PACKAGES

# Delete and re-create the output directory if it already exists
# The following code deletes and re-creates the Localize/out directory to ensure it is empty and ready to receive the
# generated localization files. This is necessary because if the directory already exists but is empty or partially empty,
# the script will not move any files into it, and the localization files will not be generated.
if (Test-Path -Path "$OutDir") {
Remove-Item -Path "$OutDir" -Recurse -Force
}
New-Item -ItemType Directory -Path "$OutDir" > $null

& "$XLocPath\tools\netfx\Microsoft.Localization.XLoc.exe" /f "$LocProject"
$localizationExitCode = $LASTEXITCODE

# Clear the RepoRoot and NUGET_PACKAGES environment variables
Remove-Item Env:\RepoRoot
Remove-Item Env:\NUGET_PACKAGES

# Move the generated files to the desired output directory
if ($localizationExitCode -eq 0) {
Move-Item -Path "$RepoRoot\out\*" -Destination $OutDir -Force
Remove-Item -Path "$RepoRoot\out" -Recurse -Force
}

Write-Host "Localization finished with exit code '$localizationExitCode'."
Exit $localizationExitCode
105 changes: 105 additions & 0 deletions Localize/copy-translations.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
param (
[string]$artifactsPath = ""
)

$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition

# If artifacts path is empty, then this script is run locally
# But if artifactsPath is set, then the script is run on the Azure DevOps path
if ($artifactsPath -eq "") {
$sourceRoot = Join-Path $scriptDir "out/loc"
} else {
$sourceRoot = $artifactsPath
}

$packageNames = @("common", "service", "playground", "react")

# Get language directories
$languageDirs = Get-ChildItem -Path $sourceRoot -Directory

# If this script is run locally, in addition to the resjson files, it adds a json directory containing json files for local development
# If script is run on ADO, it only adds the resjson files used in production

# Strip out resjson comments and resjson-specific formatting before writing the result to json file
function Convert-ResjsonToJson {
param (
[string]$sourcePath,
[string]$targetPath
)

$content = Get-Content -Path $sourcePath -Raw

$strippedContent = $content -replace '//.*$' -replace '/\*[\s\S]*?\*/' -replace ',\s*}' -replace ',\s*]'
$parsedContent = $strippedContent | ConvertFrom-Json
$cleanContent = New-Object -TypeName PSObject

foreach ($key in $parsedContent.PSObject.Properties.Name) {
if (-not $key.StartsWith("_")) {
$cleanContent | Add-Member -MemberType NoteProperty -Name $key -Value $parsedContent.$key
}
}

$cleanedJsonContent = $cleanContent | ConvertTo-Json -Depth 100
Set-Content -Path $targetPath -Value $cleanedJsonContent
}

Write-Host "Copying translation files"

foreach ($languageDir in $languageDirs) {
$languageId = $languageDir.Name
Write-Verbose "Processing language: $languageId"

# Process package directories
foreach ($packageName in $packageNames) {
$sourcePath = Join-Path $($languageDir.FullName) "packages/$packageName/i18n/resources.resjson"
$targetDir = (Join-Path $scriptDir ".." -Resolve) | Join-Path -ChildPath "packages/$packageName/resources/i18n/resjson"
$targetPath = Join-Path $targetDir "resources.$languageId.resjson"

Write-Verbose "Checking source path: $sourcePath"
if (Test-Path $sourcePath) {
Write-Verbose "Source path exists, preparing target directory"
if (-not (Test-Path $targetDir)) {
New-Item -ItemType Directory -Force -Path $targetDir > $null
}

Write-Verbose "Copying file from $sourcePath to $targetPath"
Copy-Item -Path $sourcePath -Destination $targetPath

$jsonTargetDir = $targetDir.Replace("resjson", "json")
$jsonTargetPath = $targetPath.Replace("resjson", "json")

if (-not (Test-Path $jsonTargetDir)) {
New-Item -ItemType Directory -Force -Path $jsonTargetDir > $null
}

Write-Verbose "Converting resjson to json: $jsonTargetPath"
Convert-ResjsonToJson -sourcePath $sourcePath -targetPath $jsonTargetPath
}
}

# Handle the desktop directory exception
$desktopSource = Join-Path $($languageDir.FullName) "desktop/i18n/resources.resjson"
$desktopTargetDir = (Join-Path $scriptDir "../desktop/resources/i18n/resjson")
$desktopTarget = Join-Path $desktopTargetDir "resources.$languageId.resjson"

Write-Verbose "Checking desktop source path: $desktopSource"
if (Test-Path $desktopSource) {
Write-Verbose "Desktop source path exists, preparing target directory"
if (-not (Test-Path $desktopTargetDir)) {
New-Item -ItemType Directory -Force -Path $desktopTargetDir > $null
}

Write-Verbose "Copying file from $desktopSource to $desktopTarget"
Copy-Item -Path $desktopSource -Destination $desktopTarget

$jsonDesktopTargetDir = $desktopTargetDir.Replace("resjson", "json")
$jsonDesktopTarget = $desktopTarget.Replace("resjson", "json")

if (-not (Test-Path $jsonDesktopTargetDir)) {
New-Item -ItemType Directory -Force -Path $jsonDesktopTargetDir > $null
}

Write-Verbose "Converting desktop resjson to json: $jsonDesktopTarget"
Convert-ResjsonToJson -sourcePath $desktopSource -targetPath $jsonDesktopTarget
}
}
3 changes: 3 additions & 0 deletions Localize/restore.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
nuget install Localization.XLoc -OutputDirectory packages -Verbosity detailed -Source https://azurebatch.pkgs.visualstudio.com/_packaging/BatchExplorer/nuget/v3/index.json
nuget install LSBuild.XLoc -OutputDirectory packages -Verbosity detailed -Source https://azurebatch.pkgs.visualstudio.com/_packaging/BatchExplorer/nuget/v3/index.json
nuget install Localization.Languages -OutputDirectory packages -Verbosity detailed -Source https://azurebatch.pkgs.visualstudio.com/_packaging/BatchExplorer/nuget/v3/index.json
5 changes: 3 additions & 2 deletions desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"ts": "ts-node --project tsconfig.node.json --files",
"ts:fast": "npm run ts -T",
"start": "npm run electron:prod",
"clean": "rimraf build/* dll/* python/dist/* python/build/*",
"clean": "rimraf build/* dll/* python/dist/* python/build/* && npm run clean:resources",
"clean:resources": "bux rmrf ./resources",
"karma": "node --max_old_space_size=4096 node_modules/karma/bin/karma",
"test": "npm run test-client:coverage && npm run test-app",
"test-app": "cross-env COVERAGE=1 npm run karma -- start",
Expand All @@ -49,7 +50,7 @@
"build:package": "npm run build:prod && npm run build-python && npm run package",
"build:prod": "cross-env NODE_ENV=production npm run build",
"build:test": "npm run build && npm run test",
"build-translations": "bux build-translations --src src --destJSON build/i18n-json --destRESJSON i18n",
"build-translations": "bux build-translations --src src --dest i18n",
"watch": "npm run webpack -- --watch --progress --profile --colors --display-error-details --display-cached",
"electron": "electron build/client/main.js",
"electron:prod": "cross-env NODE_ENV=production electron build/client/main.js",
Expand Down
26 changes: 26 additions & 0 deletions docs/build-localization-locally.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Building Localization on Local Machine

## Building the English File

To build the latest English translation resjson file from the YAML files:

* Run `npm run build` to build translations for the entire repository
* Run `npm run build-translations` in any package directory (desktop, packages/*) to build translations for a specific package

The output will be in `{packageName}/i18n/resources.resjson`

## Building Translations Files for Other Languages (Windows-Only)

To build the localization translations for all languages besides English:

* Follow the steps above first
* Install the latest, recommended version of nuget.exe from <https://www.nuget.org/downloads> at C:\Users\{userName}, for instance.
* Navigate to the root of the repository
* Run `npm run loc:restore` to install all dependencies
* Run `npm run loc:build` to build the translations and move them to their correct directories
* If needed, run `npm run clean` to clear out all previously built translation files

The output will be in `{packageName}/resources/i18n`

* `{packageName}/resources/i18n/resjson` contains RESJSON translations
* `{packageName}/resources/i18n/json` contains JSON translations (RESJSON syntax and comments have been stripped out)
1 change: 1 addition & 0 deletions docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* [Store user data/Cache data](store-user-data.md)
* [Use virtual scroll](virtual-scroll.md)
* [Localize](Localization.md)
* [Build Localization on Local Machine](build-localization-locally.md)

## Repo management

Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"build:package": "lerna run workspace:build:package --stream",
"build:prod": "lerna run workspace:build:prod --stream",
"build:test": "lerna run workspace:build:test --stream",
"clean": "lerna run --parallel workspace:clean --stream",
"clean": "lerna run --parallel workspace:clean --stream && npm run loc:clean",
"gather-build-results": "bux gather-build-results",
"launch": "npm run -s launch:web",
"launch:desktop": "lerna run --parallel workspace:launch:desktop --stream",
Expand All @@ -63,6 +63,9 @@
"lint": "prettier -c . && lerna run --parallel workspace:lint --stream && npm run -s lint:markdown",
"lint:fix": "prettier -w . && lerna run --parallel workspace:lint:fix --stream && npm run -s lint:markdown",
"lint:markdown": "markdownlint-cli2 \"**/*.md\" \"#**/node_modules/**/*\" \"#SECURITY.md\"",
"loc:build": "powershell -ExecutionPolicy Bypass -File ./Localize/build.ps1 && powershell -ExecutionPolicy Bypass -File ./Localize/copy-translations.ps1",
"loc:clean": "bux rmrf ./Localize/out",
"loc:restore": "cd Localize && powershell -ExecutionPolicy Bypass -File restore.ps1",
"start": "npm run -s start:web",
"start:desktop": "lerna run --parallel workspace:start:desktop --stream",
"start:web": "lerna run --parallel workspace:start:web --stream",
Expand Down
6 changes: 4 additions & 2 deletions packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
"build": "npm run compile && npm run build-translations",
"build:clean": "run-s clean compile",
"build:test": "run-s build test",
"build-translations": "bux build-translations --src src/ui-common --destJSON build/i18n-json --destRESJSON i18n --packageName lib.common",
"build-translations": "bux build-translations --src src/ui-common --dest i18n --packageName lib.common",
"compile": "run-p compile:*",
"compile:esm": "tsc -b ./config/tsconfig.build.json",
"compile:cjs": "tsc -b ./config/tsconfig.cjs.json",
"clean": "run-p clean:*",
"clean:build": "bux rmrf ./build",
"clean:esm": "bux rmrf ./lib",
"clean:cjs": "bux rmrf ./lib-cjs",
"clean:resources": "bux rmrf ./resources",
"test": "jest",
"test:coverage": "jest --collect-coverage",
"test:all": "npm run test:coverage",
Expand Down Expand Up @@ -74,6 +75,7 @@
},
"files": [
"lib",
"lib-cjs"
"lib-cjs",
"resources"
]
}
Loading

0 comments on commit 635d441

Please sign in to comment.