Skip to content

Latest commit

 

History

History
139 lines (91 loc) · 5.64 KB

I18n.md

File metadata and controls

139 lines (91 loc) · 5.64 KB

Multi-language Support (MLS)

OpenSRP Web supports multi-language using react.i18next. This document is divided into 2 sections

  1. Usage - contains instructions on how people can configure MLS when using packages.
  2. Contributors - Targets developers with the intent of either adding packages that should support MlS or maintaining packages that already support MLS

Usage

Install the i18n and pkg-config packages.

yarn add @opensrp/i18n @opensrp/pkg-config

Pass the required configs to pkg-config at the earliest point possible in your code. This should be before you import any other @opensrp packages

// dispatch-configs.ts
import { setAllConfigs } from '@opensrp/pkg-config';

setAllConfigs({
  languageCode: 'en',
  projectCode: 'core',
});
// index.js
import './dispatch-configs';
import

Configuration

Opensrp-web packages uses 2 configuration options to fully configure MLS i.e. languageCode and projectCode. These 2 are the subtags that we use to form a languageTag which is formatted as <languageCode>-<projectCode>. They are supplied once during build, via the envs REACT_APP_LANGUAGE_CODE and REACT_APP_PROJECT_CODE.

N/B The language should be internally available in the package of interest. If you are not sure of this check the Adding a new language section

consider where you have a certain string e.g. Plans that should translate to Plans for a certain clinet instance but display as Missions in another instance of the same app. In other words how can we support different translation values for the same language

This is where the projectCode comes in, helps further define what set of translations for a certain language should be used

Contributors/Maintainers

This section targets developers interested in enhancing, supporting or maintaining MLS-enabled packages.

MLS architecture

The @opensrp/i18n package includes the translation resources as static strings, it also exposes an i18n instance that is preloaded with the string resources and a context provider that provisions the i18n instance to your render tree. The i18n package relies on @opensrp/pkg-config to get the initial configured language.

Adding translatable strings

To Update the translateable strings:

Check that the strings are wrapped by a the i18next translator function t. Run the string extraction command.

./scripts/i18nExtraction.js extract <package-folder-names...> -l <locales...>

e.g

# in the repo root directory
./scripts/i18nExtraction.js extract app react-utils -l en sw

This should parse the code, get all translatable strings and updated the respective json locale files in packages/i18n. From here, you can use your favourite translation tools to get the translations as json files, add them to the right folders in packages/i18n, and then shoot us a PR.

Adding a Localized package

To add a package with localization support, you only need 2 things.

  1. the new package should have a peerDependency on the @opensrp/i18n package
  2. Add a src/mls.ts file with the below content.
import { useTranslation as useOrigTranslation, UseTranslationOptions } from '@opensrp/i18n';

export const namespace = '<package-folder-name>';

export const useTranslation = (ns?: string, options?: UseTranslationOptions) => {
  return useOrigTranslation(ns ? ns : namespace, options);
};

This hook abstraction helps add the namespace scope to the @opensrp/i18n.useTranslation , the alternative would require you to pass the namespace to every useTranslation call in a package.

Adding a new language

Add it to @openspr/pkg-config for proper typing.

export const supportedLanguageCodes = ['en', 'sw', 'fr', 'ar', 'th', 'vi'] as const;
export const supportedProjectCode = ['eusm', 'core'] as const;

Then run the extraction command while necessary locale or/and the projectCode options.

# in the repo root directory
./scripts/i18nExtraction.js extract  -l <new-locale> -p <projectCode>

This should update the locales files in packages/i18n. Create a pr.

De-duping translations using namespaces.

Consider a case where you have component A that has translatable strings. You would then like to use this component in 2 different cases within the same app where in each case the strings should be translated differently.

One way to handle this situation is to extract the labels into props. One can then provide 2 HOC wrapper components each supplying its own set of translation for the labels.

Whilst this is easy enough it does not scale well for huge components that make use of several util functions that also have their own translatable strings.

An alternative way and how we do it, is to allow passing a namespace string prop to the component. This props instructs the component on where to look up translations per component instance. Here is an example in code

export function Component({ i18nNamespace }: { i18nNamespace: string }) {
  const { t } = useTranslation(i18nNamespace);
}

//<Component i18nNamespace="fhir-inventory"> - reads locales from the fhir-inventory namespace
//<Component i18nNamespace="fhir-locations"> - reads locales from the fhir-locations namespace

To generate strings to a custom namespace, one can use the --output-namespace flag e.g

# in the repo root directory
./scripts/i18nExtraction.js extract fhir-location-management -l en --output-namespace fhir-service-points

This would extract strings in the fhir-location-management package to a custom namespace fhir-service-points that can then be used as a namespace prop.