Translation Middleware for Express APIs and MongoDB
In this post, I am going to talk about how to automatically perform translation on API responses using swagger metadata config, in an express middleware.
The config-based approach has the below benefits:
- Removes duplicate code being added for each route/handler
- Takes a config-based approach to define the translation, which can make this nearly 100% error-free.
- Development speed — Adding translation to the APIs is a breeze
Database
For the database, a simple schema can be to create another translations
collection that records the translations e.g.
// translations collection schema
{
table: string, // for e.g. crops
column_id: string, // this is the crop_id
column_id_value: int, // value for crop_id
column_to_translate: string, // this can be crop_name
en: string,
hi: string,
...
}
// query to lookup
db.translations.find({
table: 'crops',
column_id: 'crop_id',
column_id_value: 1,
column_to_translate: 'crop_name'
},
{
en: 1,
hi: 1,
_id: 0
})
One can add a compound index on the (table, column_id, column_id_value, column_to_translate)
to optimize the read.
Since we always query by the 4 keys, we can also create a translationKey
that merges these values and then index on this key instead.
For e.g., we could instead store <prefix>_crop_id_1_crop_name
as the value for the translationKey
and avoid passing in the value separately.
API Layer
In order to configure a translation middleware for your express APIs, you would need:
- Swagger based routes
- json-path library to traverse the JSON tree
- mung for transforming express response
Steps
- Define
translationConfig.yaml
2. Include it in the main swaggger.yaml
3. Define the middleware translation.js
There are a few things going on in the above function:
- We go through all the translation configs defined in
translationConfig.yaml
- Create the unique translation keys for each field using its corresponding
translateFn
- Perform a one-time DB lookup for the keys in the collection named
Translations
- Query the body for the
fieldPaths
we need to replace - Find out the corresponding key nodes for these
fieldPaths
- Substitute the value from the translation map (for the required lang) in the node value
Also, here is the simplified version of translationUtil.js
Thanks for reading!