fbtee - React Internationalization Framework
fbtee (Far Better Translations, Extended Edition) is a robust internationalization framework for JavaScript and React applications, currently stable at version 1.7.3. It differentiates itself by building upon Facebook's battle-tested `fbt` library, which has served billions of users in production environments for over a decade. The framework emphasizes an intuitive developer experience through inline translations embedded directly in code, eliminating the need for translation keys or wrapper functions. It uses a compiler-based approach to extract translatable strings and optimizes runtime performance by compiling translations into an Intermediate Representation. fbtee supports dynamic content, pluralization, lists, and provides straightforward integration with modern build tools like Vite and Next.js, often with pre-configured templates available for quick setup. It maintains an active development cycle with regular releases, enhancing features and streamlining the i18n workflow.
Common errors
-
Invariant Violation: The Babel plugin 'fbt' must be configured.
cause The `@nkzw/babel-preset-fbtee` is not correctly installed or configured in the build pipeline, preventing the Babel plugin from running.fixInstall `@nkzw/babel-preset-fbtee` via npm/yarn and add it to your Babel presets in `vite.config.ts`, `babel.config.js`, or similar configuration file. -
ReferenceError: fbt is not defined
cause The `fbt` JSX components are not being transformed by the Babel plugin at build time, leading to a runtime error.fixEnsure your Babel configuration correctly applies `@nkzw/babel-preset-fbtee` to the files containing `fbt` components, and that your build process is using this Babel configuration. -
Error: Missing source_strings.json
cause The `fbtee translate` command was executed before the `source_strings.json` file was generated by the `fbtee collect` command, or the file is not in the expected path.fixRun `npm run collect` (or `fbtee collect`) to generate the `source_strings.json` file before attempting to run the translation compilation step. -
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
cause This generic React error can occur if `fbt` or `FbtParam` are not correctly imported or if an older React version (e.g., pre-19) is used where `fbtee` expects modern features.fixVerify `fbt` and `FbtParam` are correctly imported as named exports from 'fbtee'. Also, ensure your `react` and `react-dom` packages are at version 19 or higher as required by `fbtee`.
Warnings
- breaking As of v1.5.0, explicit String() casting for `fbs()` calls is no longer required as they are automatically converted to strings. Continuing to use `String()` might be redundant or cause warnings.
- gotcha fbtee requires Node.js version 22 or higher and React version 19 or higher. Using older versions will lead to compatibility issues and runtime errors.
- gotcha Correct Babel configuration with `@nkzw/babel-preset-fbtee` is critical. Without it, `fbtee` cannot extract strings or compile translations, leading to untranslated content or build failures.
- gotcha The `fbtee` workflow relies on two essential CLI commands: `fbtee collect` to extract source strings and `fbtee translate` to compile translated files. Failing to run these commands will result in missing or untranslated content in your application.
- gotcha Implicit React Fragments (`<>`) are supported within `<fbt:param>` elements since v0.1.0. If you are on an older version or experience issues, ensure your fragments are correctly formed.
Install
-
npm install fbtee -
yarn add fbtee -
pnpm add fbtee
Imports
- fbt
const fbt = require('fbtee');import { fbt } from 'fbtee'; - FbtParam
import FbtParam from 'fbtee';
import { FbtParam } from 'fbtee'; - LocaleContext
import LocaleContext from 'fbtee';
import { LocaleContext } from 'fbtee'; - fbs
import fbs from 'fbtee';
import { fbs } from 'fbtee';
Quickstart
/*
package.json (excerpt for context):
{
"name": "fbtee-quickstart",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"collect": "fbtee collect",
"translate": "fbtee translate"
},
"dependencies": {
"fbtee": "^1.7.3",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@nkzw/babel-preset-fbtee": "^1.7.3",
"@vitejs/plugin-react": "^4.2.1",
"typescript": "^5.2.2",
"vite": "^5.2.0"
}
}
*/
// vite.config.ts
import fbteePreset from '@nkzw/babel-preset-fbtee';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
react({
babel: {
presets: [fbteePreset]
}
})
]
});
// src/App.tsx
import { fbt, FbtParam } from 'fbtee';
import React from 'react';
const Name = ({ name }: { name: string }) => (
<FbtParam name="name">{name}</FbtParam>
);
const App = () => {
const userName = 'Alice';
const itemCount = 5;
return (
<div style={{ fontFamily: 'sans-serif', padding: '20px' }}>
<h1>
<fbt desc="Welcome title">
Welcome to <FbtParam name="app">fbtee Demo</FbtParam>!
</fbt>
</h1>
<p>
<fbt desc="Greeting message">
Hello, <Name name={userName} />! You have{' '}
<FbtParam name="count" number={itemCount}>
{itemCount}
</FbtParam>{' '}
new items in your cart.
</fbt>
</p>
<p>
<fbt desc="Simple goodbye message">Goodbye!</fbt>
</p>
<button onClick={() => alert('Locale switching not implemented in this snippet.')}>
Switch Locale (conceptual)
</button>
<p>
<em>Remember to run `npm run collect` and `npm run translate`!</em>
</p>
</div>
);
};
export default App;