> For the complete documentation index, see [llms.txt](https://documentation.opencrvs.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.opencrvs.org/v1.3/setup/3.-installation/3.2-set-up-your-own-country-configuration/3.2.9-countryconfig-apis-explained/3.2.9.1-managing-language-content.md).

# 3.2.9.1 Managing language content

It is possible to amend all text copy in OpenCRVS and introduce as as many content translations as you like.

#### **Technical background**

The multi-lingual text content approach for OpenCRVS is developed using [FormatJS](https://formatjs.io/) . It is worthwhile reading their documentation to understand how this technically works, particularly this [page](https://formatjs.io/docs/core-concepts/basic-internationalization-principles).

FormatJS uses industry-wide i18n [JSON](https://en.wikipedia.org/wiki/JSON) standards to import text content. This JSON standard is also exported by enterprise level content management systems such as [Transifex](https://www.transifex.com/) or [Contentful](https://www.contentful.com/).

If you are not using a content management system, you edit text copy directly in these JSON files that are served to the client. Therefore, you will need a code editor like VSCode, explained in step [3.1.5 Tooling](/v1.3/setup/3.-installation/3.1-set-up-a-development-environment/3.1.5-tooling.md).

#### **Editing text content**

You can edit copy at any time, even after OpenCRVS goes live. The code to serve this JSON to the application is provided in the country configuration repo and requires no configuration in order to serve.

The content JSON looks like this:

```
{
  "data": [
    {
      "lang": "en",
      "displayName": "English",
      "messages": {
        "buttons.add": "Add",
        "buttons.apply": "Apply",
        ...
```

You can duplicate the [JSON Object ](https://www.w3schools.com/js/js_json_objects.asp)blocks in the "data" array for every language you want to support. Duplicate the entire block. In our Farajaland example you can see that we have duplicated the block for French.

* The **lang** key is an [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code
* The **displayName** is how you want this language selection to be displayed in the user language select component in a content management system.
* Inside the **messages** object are all the possible content keys that OpenCRVS uses. **You can edit the value but not the key itself. You must not remove any keys as they are ALL required.**
* The **value** uses the [unicode ICU Message Syntax](https://unicode-org.github.io/icu/userguide/format_parse/messages/) approach using braces {} and English variables to occasionally substitute dynamic text. You must read the [unicode documentation](https://unicode-org.github.io/icu/userguide/format_parse/messages/) and understand how this works if you are editing these values. Dynamic variables must remain in English.

1. Edit text for the **client** application in JSON in this file: [client.json](https://github.com/opencrvs/opencrvs-countryconfig/blob/develop/src/api/content/client/client.json). The descriptions for the use-case of each of these **client** content keys is described in this JSON [file](https://github.com/opencrvs/opencrvs-farajaland/blob/develop/src/features/languages/content/client/descriptions.json).
2. Edit text for the **login** application in JSON in this file: [login.json](https://github.com/opencrvs/opencrvs-farajaland/blob/develop/src/features/languages/content/login/login.json) . The descriptions for the use-case of each of these **login** content keys is described in this JSON [file](https://github.com/opencrvs/opencrvs-farajaland/blob/develop/src/features/languages/content/login/descriptions.json).
3. Edit **SMS notifications** JSON in this file: [notifications.json](https://github.com/opencrvs/opencrvs-farajaland/blob/develop/src/features/languages/content/notification/notification.json) . The descriptions for the use-case of each of these **SMS notifications** content keys is described in this JSON [file](https://github.com/opencrvs/opencrvs-farajaland/blob/develop/src/features/languages/content/notification/descriptions.json).

Some dynamc content is rendered using ICU Message Syntax, explained here: <https://formatjs.io/docs/core-concepts/icu-syntax>\\

For example, in cases like the below, the areas in **bold** are the areas to translate and you leave the rest of the syntax in English as it is code:

{year}-**Farajaland**-{event, select, birth{**birth**} death{**death**} other{**birth**}}-event-statistics.csv {fileSize}\
This is the most complex example:

{event, select, declaration {{eventType, select, birth {**birth**} death {**death**} other{**birth**}} **declaration has been sent for review.**} registration {{eventType, select, birth {**birth**} death {**death**} other{**birth**}} **has been registered.**} duplication {{eventType, select, birth {**birth**} death {**death**} other{**birth**}} **has been registered.**} rejection {{eventType, select, birth {**birth**} death {**death**} other{**birth**}} **declaration has been rejected.**} certificate {{eventType, select, birth {**birth**} death {**death**} other{**birth**}} **certificate has been completed.**} offline {{eventType, select, birth {**birth**} death {**death**} other{**birth**}} **declaration will be sent when you reconnect.**} other {{eventType, select, birth {**birth**} death {**death**} other{birth}}}

After editing the content, if the JSON is not valid, it will not load properly in the client. You can use an online validator like [this one](https://jsonlint.com/) to check that your JSON is valid. VSCode also warns you by highlighting any errors.

#### **Setting up a content management system**

It requires professional expertise in NodeJS if you want to set up a content management system other than Contentful.

You can see the functions that decide to serve either the static JSON text files or JSON from Contentful [here](https://github.com/opencrvs/opencrvs-farajaland/blob/21bebbe0e05bc7d926e57c2009f5792618045e8a/src/features/languages/service/service.ts#L80). If you want to use a different system, you can code whatever integration you like in the **getLanguages** function provided it returns language JSON to the clients in the same format as the static JSON files.

Update this environment [variable](https://github.com/opencrvs/opencrvs-farajaland/blob/21bebbe0e05bc7d926e57c2009f5792618045e8a/src/constants.ts#L81) to enable a content management system appropriately.

If you are using Contentful we automatically export JSON files ready for Contentful import if you wish to use it.

To perform an initial import to Contentful:

1. First create a space in Contentful and add your locales for your translations. Copy your **space-id** from Contentful settings.
2. Download and install the [Contentful cli](https://github.com/contentful/contentful-cli)
3. Run the following command to export your space as you will need ids for your locales: `contentful space export --space-id=<your-space-id>`
4. Open the exported file and copy the required ids to this [file](https://github.com/opencrvs/opencrvs-farajaland/blob/master/src/features/languages/scripts/constants.ts)
5. You can run the following command to generate a **contentful-import.json** file: `yarn contentful:prepare:import`
6. Run the Contentful import script: `contentful space import --content-file src/features/languages/generated/contentful-import.json --space-id=<your-space-id>`
7. Get your API key from Contentful settings and add it to an environment variable .env file, or paste [here](https://github.com/opencrvs/opencrvs-farajaland/blob/21bebbe0e05bc7d926e57c2009f5792618045e8a/src/constants.ts#L76) for use in development. DO NOT SUBMIT API KEYS TO A PUBLIC REPO!


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://documentation.opencrvs.org/v1.3/setup/3.-installation/3.2-set-up-your-own-country-configuration/3.2.9-countryconfig-apis-explained/3.2.9.1-managing-language-content.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
