Skip to content

Add support for simplified Chinese#1415

Merged
matthew-white merged 1 commit intomasterfrom
add-zh
Nov 13, 2025
Merged

Add support for simplified Chinese#1415
matthew-white merged 1 commit intomasterfrom
add-zh

Conversation

@matthew-white
Copy link
Member

This PR specifies the options/code needed to support simplified Chinese (zh). It doesn't pull the actual translations: those will come in a follow-up PR.

The codebase already includes support for traditional Chinese (zh-Hant). Note that zh is a language subtag, while Hant is a script subtag. We could have used the tag zh-Hans for simplified Chinese (with a script subtag of Hans), but we're just using zh instead. Simplified Chinese was added to Transifex as zh, not zh-Hans, and it's important that the codebase match Transifex. It was added to Transifex as zh because that's what was used for Collect.

CONTRIBUTING.md has a section on Adding a New Locale. To add support for simplified Chinese, I followed the steps there. To double-check, I searched the codebase for zh to see what was needed for traditional Chinese.

Most of the changes are routine/expected, but I did have to make a change to userLocale(), which isn't typical. Without the change, a user with a browser preference for simplified Chinese would have defaulted to traditional Chinese instead. userLocale() is the function that decides the user's locale based on their browser preferences (navigator.languages). Before, it used to be that each locale corresponded to a unique language. Now there are two locales that correspond to the same language (zh), but with different scripts (traditional vs. simplified). The logic of userLocale() had to change to account for that fact.

Prior art for comparison:

  • Add Portuguese #1130
    • 2nd and 4th commits
  • Add support for traditional Chinese #1006
    • Much more had to change in this PR. It's probably not worth digging too deeply into the PR.
      • zh-Hant was the first locale with a script subtag.
      • zh-Hant was the second locale after ja where there's typically no space character between sentences.
      • There are some CSS details that are the same for zh-Hant and ja (and now zh). For example, italics don't work super well, so bold is used instead.
    • One thing to note is that the CSS selector :lang(zh) matches both zh-Hant and zh. I confirmed that locally. So nothing there should need to change.

What has been done to verify that this works as intended?

I tried it out locally after pulling the actual translations. I saw that zh looked different from zh-Hant.

I also confirmed specifically that the date range picker showed Chinese characters and that zh looked different from zh-Hant (e.g., 周日 for Sunday instead of 週日).

For the changes to userLocale(), I verified those via unit tests.

How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?

The risk of regression for existing languages should be low. Probably the main risk is from userLocale(), but I feel like there's good test coverage of that.

We sometimes ask the QA team to verify new languages. I don't feel like it's super necessary in this case, especially since the codebase already has zh-Hant.

Before submitting this PR, please make sure you have:

  • run npm run test and npm run lint and confirmed all checks still pass OR confirm CircleCI build passes
  • verified that any code or assets from external sources are properly credited in comments or that everything is internally sourced

Comment on lines +26 to +33
// Set it up so that we can match either on language or on language + script.
// Region is ignored.
const byTag = new Map();
for (const locale of locales.keys()) {
const { language, script } = new Intl.Locale(locale);
if (!byTag.has(language)) byTag.set(language, locale);
if (script != null) byTag.set(`${language}-${script}`, locale);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I thought about making byTag a nested structure (first level language / second level script), but this ended up seeming a little simpler to me.

@matthew-white matthew-white merged commit 36e80fb into master Nov 13, 2025
7 checks passed
@matthew-white matthew-white deleted the add-zh branch November 13, 2025 06:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants