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/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ Some older files use the block format (`/*++ Copyright (c) Microsoft. All rights
- Use `EMIT_USER_WARNING(Localization::MessageXxx(...))` for non-fatal config warnings
- All new user-facing strings must have entries in `localization/strings/en-US/Resources.resw`
- In Resources.resw comments, use `{Locked="..."}` to prevent translation of `.wslconfig` property key names
- Localized files are generated by a third-party loc team and regenerated downstream, so translation edits in a GitHub PR cannot be merged (they would be overwritten). This covers the per-locale `localization/strings/<locale>/Resources.resw` UI strings and the per-locale `intune/<locale>/WSL.adml` policy templates (anything other than the `en-US` sources and the neutral `intune/WSL.admx`). Filing a GitHub issue is the correct path for contributors; see `CONTRIBUTING.md`.
- Community localization reports come in as **both GitHub issues and pull requests** - when triaging, look for both and file a tracking Bug for each. These are tracked via Bugs in the GCS Azure DevOps project, not merged directly. See `.github/copilot/localization-bugs.md` for the project coordinates, required fields, and `az boards` workflow.

### Telemetry and Logging

Expand Down
215 changes: 215 additions & 0 deletions .github/copilot/localization-bugs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
## Creating Localization Tracking Bugs (GCS Azure DevOps)

Community members report localization problems in two ways: by filing a GitHub **issue** about a bad
translation, or by opening a **pull request** that edits a localized file (the per-locale UI strings in
`localization/strings/<locale>/Resources.resw`, or the per-locale Intune/group-policy templates in
`intune/<locale>/WSL.adml`), or that adds a brand-new locale file. Both are valid signals and you should
look for **both** when triaging.

Either way, the fix is handled by the Microsoft Global Collaboration Service (GCS) localization pipeline,
**not** merged directly from GitHub: every non-`en-US` localized file is generated by the GCS team and
regenerated downstream, so any translation edit merged here would be overwritten. (PRs that touch
localized files should be declined with a pointer to `CONTRIBUTING.md`; only the `en-US` sources and the
language-neutral `intune/WSL.admx` live in this repo.) To route a report for review, file a tracking
**Bug** in the GCS Azure DevOps project for each issue or PR.

> **GCS requirement — be specific: list the exact resource IDs to fix.** The loc team will **not**
> triage abstract reports. A bug that only names the file, language, and a few quoted strings gets
> rejected (moved to the **More Info** state) because the team does not have capacity to parse a vague
> report into the concrete strings that need work — that translation has to be done up front by the
> filer. Every bug must therefore carry an explicit list of the **resource IDs** (the `name` attribute
> of the `<data name="...">` elements in `localization/strings/<locale>/Resources.resw`) that need
> fixing. The gold-standard level of detail is **Bug 1223866** (`.../GlobalCollaborationService/Global%20Collaboration%20Service%20Project/_workitems/edit/1223866`):
> for each resource ID it gives the current (bad) value and the proposed value, e.g.
>
> ```xml
> <data name="MessageDistroAlreadySet" xml:space="preserve">
> <value>Der Verteilungsname wurde bereits festgelegt.</value> <!-- current -->
> <value>Der Distributionsname wurde bereits festgelegt.</value> <!-- proposed -->
> </data>
> ```

### Deriving the resource-ID list

How you obtain the IDs depends on the report type:

- **PR editing an existing locale file** — the changed resource IDs are exactly the `<data name>`
blocks whose `<value>` differs between the repo's current file and the PR head. Load both and diff
by name. The PR "Files changed" view already shows current→proposed for each, so post the **compact
ID list plus a link to the PR diff** rather than re-inlining every value (a 160-row inline table is
unwieldy; the PR diff is the source of truth for the old/new text).

```powershell
# changed resource IDs between two Resources.resw files (master vs PR head)
function Get-ChangedIds($baseResw, $headResw) {
function Load($p) { $x = [xml](Get-Content $p -Raw); $h = @{}; foreach ($d in $x.root.data) { $h[$d.name] = $d.value }; $h }
$b = Load $baseResw; $h = Load $headResw
$h.Keys | Where-Object { $b[$_] -ne $h[$_] }
}
```

- **Issue citing line numbers** (e.g. `Resources.resw#L185`) — fetch the file **at the exact commit
the issue links to**, then walk upward from each cited line to the nearest `data name="..."` to get
the enclosing resource ID. Line numbers drift between commits, so always pin to the linked SHA.

- **Issue quoting bad strings** — grep the locale `Resources.resw` for each quoted value to find the
`<data name>` that contains it. One displayed term often maps to several IDs (`.Header`,
`.Description`, `...TextBox.AutomationProperties.Name`/`.HelpText`, shell-nav `.Content`), so list
them all.

- **PR adding a brand-new locale** — this is a net-new whole-file contribution, **not** a correction
list, so there is nothing pre-existing to "fix". Give the team the actionable file-level items
instead: (1) hard parity failures vs `en-US` that block `tools/devops/validate-localization.py` —
placeholder/insert-count mismatches and missing `{Locked="..."}` tokens, listed by resource ID;
(2) the coverage gap (which `en-US` IDs are missing, and how many of N total); (3) any strings
present in the file but absent from `en-US` (obsolete — drop them); and (4) that a new locale needs
build registration, not just a file drop.

### Coordinates

| | |
|---|---|
| Org | `https://dev.azure.com/GlobalCollaborationService` |
| Project | `Global Collaboration Service Project` |
| Process | `GCS_Agile` |
| Work item type | `Bug` |
| Web "create from template" link | `https://dev.azure.com/GlobalCollaborationService/Global%20Collaboration%20Service%20Project/_workitems/create/Bug?templateId=b97df4d3-4106-4099-a3a9-1782b5891bec` |

### Required fields (and known-good values for a community loc PR)

The Bug type has several required custom picklist fields. Values that work for "community translation PR
needs review":

| Field (reference name) | Value |
|---|---|
| `System.Title` | `WSL: Review community <locale> localization report (GitHub #<issue or PR>)` |
| `System.Description` / `Microsoft.VSTS.TCM.ReproSteps` | GitHub link + scope + action (see below) |
| `Custom.IssueType` | `Incorrect Translation` |
| `Custom.ProductArea` | `Software` |
| `Custom.How_Found` | `Community` |
| `Custom.Severity_Impact` | `S3 - Medium` (field default) |
| `Microsoft.VSTS.Common.ValueArea` | `Business` (field default) |
| `Custom.HaveyouattachedEnglishandlocalizedscreenshots` | `No` (allowed: `Yes`/`No`; no default — must be set) |
| `Custom.Language` | picklist — see mapping below (the WSL locale code is **not** accepted) |

Other required custom flags (`Custom.BugBlocked`, `Custom.XLanguage`,
`Custom.OverrideMaxStringsThreshold`, `Custom.SkipSourceAudioFilesValidation`,
`Custom.DidCopilotrespondinthesamelanguage`, `Custom.Copilotattachallfiles`) default to `0` and
auto-fill; leave them unset.

### `Custom.Language` mapping (picklist values, not locale codes)

`Custom.Language` is a 148-value picklist keyed by display name. Map the WSL `Resources.resw` locale
folder to the picklist value:

| WSL locale | `Custom.Language` value |
|---|---|
| `es-ES` | `Spanish (Spain, International Sort)` |
| `zh-CN` | `Chinese (Simplified) - PRC` |
| `el-GR` | `Greek (Greece)` |
| `tr-TR` | `Turkish (Turkey)` |

For other locales, list the allowed values and match by display name:

```powershell
$org="https://dev.azure.com/GlobalCollaborationService"
$projEnc="Global%20Collaboration%20Service%20Project"
$res="499b84ac-1321-427f-aa17-267ca6975798" # Azure DevOps AAD resource id
az rest --method get --resource $res `
--uri "$org/$projEnc/_apis/wit/workitemtypes/Bug/fields/Custom.Language?`$expand=all" `
--headers "Accept=application/json;api-version=7.1-preview.3" |
ConvertFrom-Json | Select-Object -ExpandProperty allowedValues
```

### Suggested description body

```
Community localization report on GitHub microsoft/WSL needs review by the loc pipeline.

GitHub: https://github.com/microsoft/WSL/<issues or pull>/<number>
Language: <locale>
Type: <issue reporting a bad translation | PR editing the localized file>
Scope: localized file (localization/strings/<locale>/Resources.resw or intune/<locale>/WSL.adml).
For a PR: <edits to existing | brand-new>, +A/-B, 1 file. For an issue: the specific string(s) reported.
Resource IDs to fix: <explicit list of <data name> keys - see the dedicated comment with the full
list, or paste it here>. This is required; see "Deriving the resource-ID list" above.
Action: validate placeholder/locked-token parity vs en-US (tools/devops/validate-localization.py),
then incorporate or advise. New locales additionally need build registration, not just a file drop.
Note: do not merge the GitHub PR - localized files are regenerated by GCS and edits here are overwritten.
```

The resource-ID list is the part GCS actually needs. If it is long, post it as a work-item **comment**
(ADO comments accept HTML and can be edited in place via `PATCH .../comments/<id>`) and reference that
comment from the description.

### Creating via CLI (`az boards`)

Requires the `azure-devops` az extension and an identity with **create/edit work item** permission in
the project (see caveat below).

```powershell
$org="https://dev.azure.com/GlobalCollaborationService"
$proj="Global Collaboration Service Project"
$area="Global Collaboration Service Project\Global\Windows" # working area path, see Permissions gotcha
$desc="Community es-ES localization PR. PR: https://github.com/microsoft/WSL/pull/14109 ..."
az boards work-item create --org $org --project $proj --type "Bug" `
--title "WSL: Review community es-ES localization PR (GitHub #14109)" `
--area "$area" --description $desc `
--fields "System.Description=$desc" `
"Microsoft.VSTS.TCM.ReproSteps=$desc" `
"Custom.Language=Spanish (Spain, International Sort)" `
"Custom.IssueType=Incorrect Translation" `
"Custom.ProductArea=Software" `
"Custom.How_Found=Community" `
"Custom.Severity_Impact=S3 - Medium" `
"Microsoft.VSTS.Common.ValueArea=Business" `
"Custom.HaveyouattachedEnglishandlocalizedscreenshots=No"
```

### Gotchas

- **`az.cmd` eats `&` in URLs.** When using `az rest`, never put `&` (multiple query params) in
`--uri` on Windows — cmd truncates the URL there. Pass `api-version` via the **Accept header**
instead: `--headers "Accept=application/json;api-version=7.1"`, keeping at most one `?param` in the URI.
- **Permissions are area-path-scoped, and the path matters.** Creating work items requires explicit rights on
the *specific area path*, not the project as a whole. The correct, durable path for WSL localization bugs is
`Global Collaboration Service Project\Global\Windows` (confirmed against existing manually-filed WSL loc
bugs). Always set `System.AreaPath` (or `--area`) to that path. A `@ntdev.microsoft.com` identity is denied
at the project root and most other paths (`TF237111: ... does not have permissions to save work items under
the specified area path`). Do NOT file under `...\C and AI\Unspecified`: an identity may briefly appear to
have access there, but bugs filed there get cleaned up and the access is not stable. To probe a path without
creating anything, POST with `?validateOnly=true`. If your identity lacks rights everywhere, create the bug
through the web template link above.
- **`System.Description` is required, separately from repro steps.** The Bug type rejects a create with
`TF401320: Rule Error for field Description ... Required, InvalidEmpty` unless `System.Description` is set.
Set both `System.Description` and `Microsoft.VSTS.TCM.ReproSteps` (the same body is fine). When POSTing a
JSON-patch document via `az rest`, use newline-to-`<br>` so the HTML-rendered fields keep their line breaks.
- **Picklist discovery.** Field allowed-values often don't expand through the plain field endpoint; use
`?$expand=all` on `.../workitemtypes/Bug/fields/<ref>` as shown above.
- **"Not found" can mean "no access," not "doesn't exist."** WIQL and `GET .../workitems/<id>` honor ACLs:
a `CreatedBy=@me` query returning zero rows, or `TF401232: Work item <id> does not exist, or you do not
have permissions to read it`, often just means your identity can't read that area path. Don't assume the
bug was deleted. A gap in sequential work-item IDs is a tell that items were created but are now invisible
to you (e.g. filed under a path whose access got revoked, then reaped) - which is exactly why you should
stick to the durable `Global\Windows` path above.
- **Read the bug back after creating it.** Immediately `GET` each new work item id (or open the URL) to
confirm it's actually persisted and readable under your identity. A create that "succeeds" against a flaky
area path can vanish later; a read-back catches that while you can still re-file.
- **Non-ASCII gets mangled, and `az` errors poison `ConvertFrom-Json`.** Locale content (Turkish, Greek, CJK)
comes back cp1252-garbled unless you set `[Console]::OutputEncoding=[System.Text.Encoding]::UTF8` first.
Also, `az` prints errors to the stream, so piping straight into `ConvertFrom-Json` throws on any failure;
capture with `Out-String` and parse, or check `$LASTEXITCODE`. Pass JSON-patch bodies via `--body "@file"`
(content type `application/json-patch+json`) rather than inline to dodge quoting hell.
- **Don't inline huge diffs into a comment.** For a PR that touches many strings, post the resource-ID
list and link the PR "Files changed" page for the current→proposed values; a 100+ row HTML table
makes the bug unreadable and can bump against comment-size limits. ADO comments can be edited in
place (`PATCH .../comments/<id>?api-version=7.1-preview.4`), so trim/replace rather than re-posting.

### After creating

Cross-link the systems: paste the ADO Bug ID into the GitHub PR (and vice-versa) so reviewers can find both.
Then read each new bug back (see gotcha above) to confirm it persisted under `Global\Windows`.

If GCS moves a bug to **More Info**, it almost always means the resource-ID detail is missing or too
abstract: supply the explicit `<data name>` list (see "Deriving the resource-ID list"), then move the
bug back to **Active** and reassign it to the requesting GCS reviewer.
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ You can file issues for WSL at the WSL repository, or linked repositories. Befor
2. If your issue is related to a Linux GUI app, please file it at [microsoft/wslg](https://github.com/microsoft/wslg/issues)
3. Otherwise, if you have a technical issue related to WSL in general, such as start up issues, etc., please file it at [microsoft/wsl](https://github.com/microsoft/WSL/issues)

### Localization and translation issues

If you spot a bad, missing, or incorrect translation in WSL's UI, **please file an issue** describing the problem (which language, what string, and what it should say) rather than opening a pull request.

WSL's localized files are generated by a separate localization team and are regenerated downstream, so any translation edits made in a pull request here would be overwritten and cannot be merged. This covers the per-locale UI strings (`localization/strings/<locale>/Resources.resw`) and the per-locale Intune/group-policy templates (`intune/<locale>/WSL.adml`). Filing an issue lets us route the fix to the team that owns those translations. The `en-US` source files (`localization/strings/en-US/Resources.resw`, `intune/en-US/WSL.adml`, and the language-neutral `intune/WSL.admx`) are the exception, since those originate in this repository.

Please provide as much information as possible when reporting a bug or filing an issue on the Windows Subsystem for Linux, and be sure to include logs as necessary!

Please see the [notes for collecting WSL logs](#notes-for-collecting-wsl-logs) section below for more info on filing issues.
Expand Down