This PR introduces the ability to switch languages, as well as translations for most of the, if not the entire, application.
General Notes
all translations are provided in a way that conveys the same meaning as their English counterparts and are not meant to be word-for-word translations for most parts. In fact, I would heavily discourage against word-for-word translations.
With that said, translations can be adjusted accordingly. I don't hold special feelings for my own translations. Some of them were provided just to have something, so not every translation is bound to be perfect.
there are many places where the UI looks weird due to the Bulgarian translations being longer than the English ones. Those have not been fixed in this PR, as I'd rather document them all first and tackle them in a separate PR (or multiple PRs)
for stuff like the FAQ and the changelog, where the content is rendered dynamically from constants, the constants that are used for rendering now point to translation keys, which hold the actual content.
Translation files
Translation files are stored in src/translation/{language} as .json files, where {language} is any of our supported languages. The files are split as follows:
common.json - translations for components that appear throughout the app, like the navigation menu, or translations used in multiple places across the app.
toast.json - translation keys for the toast mesasges. Note: the reason they are no longer grouped as "success" and "error" was because I was trying something with TypeScript typing and initially removed them to make it easier, but it ultimately failed and never bothered to restore it.
Note: the previous errorToast utility function has been removed and replaced with a hook, this is so that it can use the useTranslation hook.
validationErrorMessages - translation keys for validation error messages, self-explanatory
all other .json files represent a group of pages. For example, the about.json file holds the translation keys for all About pages. Each subpage is represented by a top-level JSON key. In some cases, those files may also have a common key, which holds translations used across the page group, but not used outside of the page group itself
Note: occassionally, stuff like table headers, which happen to be the same across multiple pages, are still translated within their page files and are not extracted in common.json, this is mostly because I'd rather avoid accidental side effects if we decide we want to change the specific translation and do not intend to do it globally.
Change language menu
As mentioned in #115, the menu's implementation is temporary for now. For new users, the menu will detect the browser language and select the translation (and therefore corresponding option) automatically. After that, the menu will appropriately save the user's preference (if they decide to change it)
Although I mentioned that the mobile variant will implement the menu with a native select, it turns out that there are several limitations to the component such as that my mobile wireframe will prove impossible to implement, so the mobile variant for now is also a standard dropdown menu
Other notes
I have added a placeholder Suspense element, as it is needed for the translations to load correctly. It goes without saying that we willl want to create something more than a mere heading to improve the UX while the user is waiting for the app to load (we can also consider lazy loading some of the modules and components), but this is obviously out of scope for this PR.
for the changelog translations, while you could theoritically represent the entire archive as a JSON array, I have still left the version and date as a JavaScript object, this is mostly because I'd rather have a single source of truth for those (and the date has to be formatted as something that can be parsed as a date, so having a single source of truth for it reduces the chance of errors)
I appreciate the hard work and initiative. Looks really good! I spot a few typos here and there but they will be fixed another time when we do a deeper UI review.
Closes #115
This PR introduces the ability to switch languages, as well as translations for most of the, if not the entire, application.
General Notes
Translation files Translation files are stored in
src/translation/{language}
as.json
files, where{language}
is any of our supported languages. The files are split as follows:common.json
- translations for components that appear throughout the app, like the navigation menu, or translations used in multiple places across the app.toast.json
- translation keys for the toast mesasges. Note: the reason they are no longer grouped as "success" and "error" was because I was trying something with TypeScript typing and initially removed them to make it easier, but it ultimately failed and never bothered to restore it.errorToast
utility function has been removed and replaced with a hook, this is so that it can use theuseTranslation
hook.validationErrorMessages
- translation keys for validation error messages, self-explanatory.json
files represent a group of pages. For example, theabout.json
file holds the translation keys for all About pages. Each subpage is represented by a top-level JSON key. In some cases, those files may also have acommon
key, which holds translations used across the page group, but not used outside of the page group itselfNote: occassionally, stuff like table headers, which happen to be the same across multiple pages, are still translated within their page files and are not extracted in
common.json
, this is mostly because I'd rather avoid accidental side effects if we decide we want to change the specific translation and do not intend to do it globally.Change language menu As mentioned in #115, the menu's implementation is temporary for now. For new users, the menu will detect the browser language and select the translation (and therefore corresponding option) automatically. After that, the menu will appropriately save the user's preference (if they decide to change it)
Although I mentioned that the mobile variant will implement the menu with a native select, it turns out that there are several limitations to the component such as that my mobile wireframe will prove impossible to implement, so the mobile variant for now is also a standard dropdown menu
Other notes
Suspense
element, as it is needed for the translations to load correctly. It goes without saying that we willl want to create something more than a mere heading to improve the UX while the user is waiting for the app to load (we can also consider lazy loading some of the modules and components), but this is obviously out of scope for this PR.Let me know if I missed any translation