Cryostat-web uses i18next as an internationalization-framework. The react-i18next package is used to integrate i18next with React. To add new user strings to the project, they must be handled in the manner below.
The current list of language locales supported in Cryostat can be found in src/i18n/config.ts
. The translations themselves can be found in locales/{LOCALE_CODE}
To add a new language, add a new entry to the i18nResources
object in src/i18n.ts
. The key should be the language locale, and the value should be the translation object containing the corresponding namespace json files in locales
.
To add a new localization key for a user-facing string in cryostat-web
, use the t
function from react-i18next
:
import { useTranslation } from 'react-i18next';
...
export const SomeFC = (props) => {
const { t } = useTranslation();
return (
<div>
{t('somekey')}
</div>
);
}
After saving the file, and running yarn localize
, this will generate a new key in the en
locale namespace json file in /locales/en/common.json
(having multiple locales will add a key to each locale json file!):
$ yarn localize # uses i18next-parser to generate based on files in src/
locales/en/common.json
{
...
"somekey": "cryostat_tmp",
...
}
The value of the key will be the string cryostat_tmp
by default (we set this in i18next-parser.config.js
). This is a placeholder value that should be replaced with the actual translation by going to the corresponding locale json file and manually replacing the value with the translation.
locales/en/common.json
{
...
"somekey": "This is a translation",
...
}
The React i18next API docs can be found here.
Currently the two namespaces are common
and public
.
If you want to add a new key to a specific namespace, you can specify the namespace as the first argument to the t
function:
<div>
{t('SOME_COMMON_KEY', { ns: 'common' })}
</div>
In cryostat-web
, we use common
for common user-facing strings that you may see all the time: e.g. Home
, Help
, Cancel
, etc.
<div>
{t('Cancel')}
</div>
locales/en/common.json
{
"CANCEL": "Cancel",
}
These keys should be capitalized, and should be unique within the namespace.
If we want to localize specific user-facing strings that are only used in a specific component, we can use the public
namespace. We don't actually need to specify the namespace in this case for the t
function, since we set this as the default namespace in src/i18n/config.ts
:
<div>
{t(`AboutDescription.VERSION`)}
</div>
locales/en/public.json
...
"AboutDescription": {
"BUGS": "Bugs",
"FILE_A_REPORT": "File a Report",
"VERSION": "some version!"
},
...
To run unit tests using Jest that use a translation, but we want to test the value, use the testT
function from src/test/Common.tsx
:
e.g.
expect(screen.getByText(testT('CRYOSTAT_TRADEMARK', { ns: 'common' }))).toBeInTheDocument();