Importing TOML in React Native
This is a no bullshit quick note that I also can use in the future.
I love to use TOML in i18next because I also comment the translations to give them context. The problem is, there’s no standard way to simply import TOML files in a React Native project.
Metro is the bundler for React Native projects. In our case, it has a very useful feature: Transforming source codes.
Transforming is basically taking in a source code that is not native to JS (like TOML, YAML etc.), and converting it into native JS type. Of course, this is oversimplified.

So, when you do import enTranslation from “@/assets/translations/en.toml”, Metro will parse TOML and convert it into native JS.
We also need a parser for TOML, and I think smol-toml is the most maintained one at the time I am writing this.
So, let’s first create metro.transformer.js and add this code:
// import transformer
const upstreamTransformer = require("@expo/metro-config/babel-transformer");
// import parser
const { parse } = require("smol-toml");
module.exports = {
// export custom transform function
transform: (config) => {
// spread config, we need individual vars
const { src, filename, options } = config;
// if file is toml
if (filename.endsWith(".toml")) {
try {
// parse it
const parsedData = parse(src);
// act like it's a JS module and export the data
const code = `module.exports = ${JSON.stringify(parsedData, null, 2)};`;
// transform the result
return upstreamTransformer.transform({
src: code,
filename,
options,
});
} catch (error) {
// if there's error, do not compile
throw new Error(
`Error parsing TOML file ${filename}: ${error.message}`
);
}
}
// Use default transformer for other files
return upstreamTransformer.transform(config);
},
};
This is not where it ends, though. We also need to add it to metro.config.js.
const { getDefaultConfig } = require("expo/metro-config");
// get default config
const config = getDefaultConfig(__dirname);
// introduce transformer into default config
config.transformer = {
...config.transformer,
// define transformer path here
babelTransformerPath: require.resolve("./metro.transformer.js"),
};
// introduce resolver, without this, import will not recognize toml imports
config.resolver = {
...config.resolver,
sourceExts: [...config.resolver.sourceExts, "toml"],
};
module.exports = config;
After this, you can safely import TOML files:
import enTranslations from "@/assets/translations/en.toml";
Of course, you will see some problems about Typescript being unable to define types. Create toml.d.ts at root of your project and define type:
declare module "*.toml" {
const value: Record<string, unknown>;
export default value;
}
And add it to your tsconfig.json.
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"paths": {
"@/*": ["./src/*"]
}
},
"include": [
"**/*.ts",
"**/*.tsx",
".expo/types/**/*.ts",
"expo-env.d.ts",
"nativewind-env.d.ts",
"toml.d.ts", // add type definition file here
]
}

