-
Notifications
You must be signed in to change notification settings - Fork 22
Add internationalization (i18n) support with react-i18next #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, I would prefer a library that sticks on ICU MessageFormat since the Intl.MessageFormat
proposal will eventually be a part of the ES spec. What do @syimyuzya @untunt @ayaka14732 think?
Additionally, before we can move on, we will need to decide on whether:
- to remove the English translations temporarily and merge anyway; or
- to merge into an alternative branch,
nk2028:i18n
since English users will see messages in two languages at the same time as not all messages are translated.
escapeValue: false, // not needed for react as it escapes by default | ||
}, | ||
backend: { | ||
loadPath: "/tshet-uinh-autoderiver/locales/{{lng}}/translation.json", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will need to follow assetLocation
in vite.config.ts
since we also have vite.cos.config.ts
for production
src/Components/App.tsx
Outdated
document.documentElement.lang = i18n.language; | ||
i18n.on("languageChanged", lng => { | ||
document.documentElement.lang = lng; | ||
}); | ||
|
||
document.title = t("tshetUinhAutoderiver"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be put into i18n.ts
since nothing is related to the App
component.
document.documentElement.lang = i18n.language; | |
i18n.on("languageChanged", lng => { | |
document.documentElement.lang = lng; | |
}); | |
document.title = t("tshetUinhAutoderiver"); | |
document.documentElement.lang = i18n.language; | |
document.title = i18n.t("tshetUinhAutoderiver"); | |
i18n.on("languageChanged", lng => { | |
document.documentElement.lang = lng; | |
document.title = i18n.t("tshetUinhAutoderiver"); | |
}); |
src/Components/Main.tsx
Outdated
}, []); | ||
const onHideTooltip = useCallback(() => setCopyTooltipText("複製到剪貼簿"), []); | ||
const onHideTooltip = useCallback(() => setCopyTooltipText(t("copyToClipboard")), []); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t
will be a dependency in these cases
src/options.tsx
Outdated
@@ -204,13 +205,16 @@ export const evaluateOption: Record<Option, Handler> = { | |||
return result.length ? ( | |||
<> | |||
<Title> | |||
找到 {result.length} 個相異項目。 | |||
{i18n.t("schemaCompareDifferent", { count: result.length })} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is tricky, we will need a functional component like
function Translation({ message, ...options }) {
const { t } = useTranslation();
return t(message, options);
}
to get the messages sync with the language chosen (I am new to the i18next library and I haven’t think of how to type the component correctly yet, but I believe this should be what react-i18next
provide. I wonder if there are alternative i18n libraries that provide such components.)
That’s not really an issue. i18next is a widely used and well-supported library. ICU MessageFormat doesn’t seem particularly relevant in this context, since we’re only using formatting for one of the strings, while the rest are just straightforward string replacements. |
All the strings (as far as I can test) have been translated into English. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t
should be added to React hooks’ dependency arrays. I wonder if ESLint is checking this.
I’ll come back next month to test out the PR and give a more detailed review.
<link | ||
rel="stylesheet" | ||
href="https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@400;700&family=Noto+Serif+SC:wght@400;700&family=Noto+Serif+TC:wght@400;700&family=Jomolhari&display=swap" /> | ||
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&family=Noto+Serif+KR:wght@400;700&family=Noto+Serif+SC:wght@400;700&family=Noto+Serif+TC:wght@400;700&family=Jomolhari&display=swap" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although it doesn’t make much difference, are we actually using all the weights of the font?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we are only using Regular and Bold
html:lang(zh-HK), html :lang(zh-HK) { | ||
font-family: "Source Han Serif C", "Source Han Serif K", "Noto Serif CJK KR", "Source Han Serif SC", | ||
"Noto Serif CJK SC", "Source Han Serif", "Noto Serif CJK JP", "Source Han Serif TC", "Noto Serif CJK TC", | ||
"Noto Serif KR", "Noto Serif SC", "Noto Serif TC", "Jomolhari", "HanaMin", "CharisSILW", serif; | ||
} | ||
html:lang(en-GB), html :lang(en-GB) { | ||
font-family: "Roboto", "Source Han Serif C", "Source Han Serif K", "Noto Serif CJK KR", "Source Han Serif SC", | ||
"Noto Serif CJK SC", "Source Han Serif", "Noto Serif CJK JP", "Source Han Serif TC", "Noto Serif CJK TC", | ||
"Noto Serif KR", "Noto Serif SC", "Noto Serif TC", "Jomolhari", "HanaMin", "CharisSILW", sans-serif; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer extracting the common part to a CSS variable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although it doesn't make a difference, it can be simplified to
html:lang(zh-HK), html :lang(zh-HK) { | |
font-family: "Source Han Serif C", "Source Han Serif K", "Noto Serif CJK KR", "Source Han Serif SC", | |
"Noto Serif CJK SC", "Source Han Serif", "Noto Serif CJK JP", "Source Han Serif TC", "Noto Serif CJK TC", | |
"Noto Serif KR", "Noto Serif SC", "Noto Serif TC", "Jomolhari", "HanaMin", "CharisSILW", serif; | |
} | |
html:lang(en-GB), html :lang(en-GB) { | |
font-family: "Roboto", "Source Han Serif C", "Source Han Serif K", "Noto Serif CJK KR", "Source Han Serif SC", | |
"Noto Serif CJK SC", "Source Han Serif", "Noto Serif CJK JP", "Source Han Serif TC", "Noto Serif CJK TC", | |
"Noto Serif KR", "Noto Serif SC", "Noto Serif TC", "Jomolhari", "HanaMin", "CharisSILW", sans-serif; | |
} | |
:lang(zh-HK) { | |
font-family: "Source Han Serif C", "Source Han Serif K", "Noto Serif CJK KR", "Source Han Serif SC", | |
"Noto Serif CJK SC", "Source Han Serif", "Noto Serif CJK JP", "Source Han Serif TC", "Noto Serif CJK TC", | |
"Noto Serif KR", "Noto Serif SC", "Noto Serif TC", "Jomolhari", "HanaMin", "CharisSILW", serif; | |
} | |
:lang(en-GB) { | |
font-family: "Roboto", "Source Han Serif C", "Source Han Serif K", "Noto Serif CJK KR", "Source Han Serif SC", | |
"Noto Serif CJK SC", "Source Han Serif", "Noto Serif CJK JP", "Source Han Serif TC", "Noto Serif CJK TC", | |
"Noto Serif KR", "Noto Serif SC", "Noto Serif TC", "Jomolhari", "HanaMin", "CharisSILW", sans-serif; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Random thought: have you considered en-HK
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although it doesn't make a difference, it can be simplified to ...
IIRC the priorities of html :lang(en-GB)
and :lang(en-GB)
are different. Therefore, when combining with other rules, the rendering results would be different.
I need to find an example for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Random thought: have you considered
en-HK
?
I guess en-GB
would be better for SEO purposes?
@@ -864,7 +867,9 @@ export default function SchemaEditor({ state, setState, commonOptions, evaluateH | |||
)} | |||
</Parameters> | |||
) : ( | |||
<NoParameters>此推導方案無需選項。</NoParameters> | |||
<NoParameters> | |||
<Trans t={t}>此推導方案無需選項。</Trans> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this line, but not the others, uses the <Trans>
component?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t(...)
does not work with interpolations (i.e. {{count}}
in "Found {{count}} different items."
)
import "purecss/build/pure.css"; | ||
import { useTranslation } from "react-i18next"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is weird, but you’ll need to swap the imports manually. ESLint doesn’t handle such edge cases.
@ztjhz @ayaka14732 Would you like to work on the remaining issues yourselves, or would you prefer me to take care of them? |
TODO for myself:
TODO later (probably after merging):
|
I've realised it. I don't have an idea to make it look better 😂
@graphemecluster I think you can work on it, because I don't know how to solve some of the problems, and @ztjhz may not have time to work on it. |
This PR only lays out the i18n foundation (only some text have been translated to English).
Translations are organized in JSON files located at public/locales/{{lang}}/translation.json, where {{lang}} represents the language code (e.g., en, ja, es).
To support a new language:
Usage Examples
Inside Components:
Outside Components: