Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds clarifications to README for new fbtee users #20

Merged
merged 2 commits into from
Jan 8, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 112 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ This is a fork of Facebook's original `fbt` library, which has been archived. Th
**fbtee** requires at least Node 22, and React 19 if you are using React.

```bash
npm install fbtee @nkzw/babel-preset-fbtee
npm install fbtee
```

In addition to `fbtee`, you need to install the Babel preset and React plugin for Vite:

```bash
npm install -D @nkzw/babel-preset-fbtee @vitejs/plugin-react
```

In your `vite.config.ts`:
Expand All @@ -38,25 +44,31 @@ export default {
};
```

**fbtee** uses three scripts to manage translations. These scripts help automate the process of collecting, creating, and compiling translations. It is recommended to add them to your `package.json`:
**fbtee** uses three scripts to manage translations. These scripts help automate the process of collecting, creating, and compiling translations. Dependending on your setup you might adjust want to adjust them, which we'll cover below. It is recommended to add them to your `package.json`:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion:

... These scripts help automate the process of collecting, creating, and compiling translations, which we'll cover below. Dependending on...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, my meaning of cover below isn't matching on how you read that. So I might need to improve that text. I didn't want to say that we cover the collection, creating and compiling below, but the adjustment of the setup / commands. Never the less there's an issue with two times basically the same thing in there.

Copy link
Collaborator

@kayhadrin kayhadrin Jan 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean now, but I was mainly trying to fix the phrasing of this sentence:

Dependending on your setup you might adjust want to adjust them, which we'll cover below.

I also noticed this mispeled word... "Dependending" 😅


```json
{
"scripts": {
"fbtee:collect": "fbtee collect --manifest < .src_manifest.json > .source_strings.json",
"fbtee:manifest": "fbtee manifest --src src",
"fbtee:collect": "fbtee collect --manifest < .src_manifest.json > .source_strings.json",
kayhadrin marked this conversation as resolved.
Show resolved Hide resolved
"fbtee:translate": "fbtee translate --translations translations/*.json --jenkins > src/translations.json"
}
}
```

Run these commands to set up the initial translation files:
Let's go through these commands ones by one:

- `fbtee manifest --src src` searches through files in the `src` directory and generates a manifest file (`.src_manifest.json`) that lists all the files containing `<fbt>` tags. In addition it creates `.enum_manifest.json` which lists all the files containing `<fbt:enum>` tags. These files will be put into `.gitignore` as they are auto-generated and should not be checked into version control. You can adjust the `--src` parameter to point to your source directory. If your source directory is for example the root use `--src .` or if it's an app folder use `--src app`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

These files will be put into .gitignore as they are auto-generated and should not be checked into version control.

After:

As most transient files, these files should not be checked into your version control system (See .gitignore).

From my POV, the fbtee doc is intended for developers who want to use it in their own projects; so when I read "These files will be put into .gitignore", it seems to imply some kind of automation that we actually don't do at all.

- `fbtee collect --manifest < .src_manifest.json > .source_strings.json` reads the manifest file and extracts all the strings marked for translation into a `.source_strings.json` file. This file should be uploaded to your translation provider as the source for your translations. The file itself will also be put into `.gitignore`. As you might be able to see in theory both the output file name of the manifest command, as well as input and ouput of the collect command are configurable. Yet we recommend to stick with the default values.
Copy link
Collaborator

@kayhadrin kayhadrin Jan 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quote:

The file itself will also be put into .gitignore.

Ditto from above comment.

As you might be able to see in theory both the output file name of the manifest command, as well as input and ouput of the collect command are configurable. Yet we recommend to stick with the default values.

This seems self-explanatory and I think this sentence could be removed for conciseness.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I generally agree, but since many configurations can be ‘copied and pasted’, I wanted to point out a sort of ‘beware, you may need to change this’.

- `fbtee translate --translations translations/*.json --jenkins > src/translations.json` reads all the translations in the `translations/` directory and compiles them into a single `src/translations.json` file. This file is used by **fbtee** to display translated content in your app. The `--translations` parameter specifies the path to the translation files. The `--jenkins` flag is used to define the utilized [hash function](https://en.wikipedia.org/wiki/Jenkins_hash_function). You can adjust the `--translations` parameter to point to your translation directory. If your translations are within your app directory in a folder called `i18n`, for example, you'd use `--translations app/i18n/*.json`. The output is the translation file used by **fbtee**. This file is going to be referred to in your applications entry point, therefor it needs to be generated as part of the build, but should not be part of your version control. Also here you should adjust the output file name to your needs. For example if we're going with an app folder structure we could use `> app/translations.json`. As this command requires the translations to be present in the `translations/` directory to create a valid json to be used, you first need to create such files based on the `.source_strings.json` received as part of the collect command.
Copy link
Collaborator

@kayhadrin kayhadrin Jan 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Suggesting some rewording to simplify the definition of the role of translations.json
  2. In my opinion, I don't think we should discourage users not to version their translation files. Of course, they can ignore that if they already have other ways to version + archive their translation builds.
  3. I think we can assume that users would already know how to customize file paths for their own projects.

Before

The output is the translation file used by fbtee. This file is going to be referred to in your applications entry point, therefor it needs to be generated as part of the build, but should not be part of your version control. Also here you should adjust the output file name to your needs. For example if we're going with an app folder structure we could use > app/translations.json.

After:

The script will store translations for all the provided locales into a single file src/translations.json destined to be used by fbtee on the clientside. This file contents will later be provided to the fbtee library during the client-side setup phase (See setupFbtee), therefore it needs to be generated & bundled as part of your website build.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On 1) With regards to the proposed after: Given this formulation one could raise the question on what's then used on server side, given that the meaning of client and server in this context, and the context of the framework I'm working in might not be identical.

  1. Maybe whoever wrote the original ReadMe could chime in given it was already marked as to be put into .gitignore. In general I assume it's a duplication, if the translate command would be part of the build. If it's not, then I agree.

  2. As commented above a lot of instructions that atleast I'm used to can be simply copied. It shouldn't harm to put attention that this is not the case, but that already here some assumptions are being made (e.g. your code being in a src repository, some other files being in root). Yet up to you all.


So in a first step - given you've added the commands to your package.json script section - run these commands to set up the initial files:

```bash
npm run fbtee:manifest && npm run fbtee:collect && npm run fbtee:translate
npm run fbtee:manifest && npm run fbtee:collect
```

The files generated by these commands are auto-generated and should not be checked into version control. Add the following entries to your `.gitignore`:
The files generated by these - as previously said - should not be checked into version control. Add the following entries to your `.gitignore`:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before

The files generated by these - as previously said - should not be checked into version control. Add the following entries to your .gitignore:

After

The files generated by these commands - as previously said - should not be checked into version control. Add the following entries to your .gitignore:


```
.src_manifest.json
Expand All @@ -65,6 +77,8 @@ The files generated by these commands are auto-generated and should not be check
src/translations.json
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally, for best practice, I'd recommend storing the translations file in the repo alongside the source code because website owners should always be able figure out what exact translations were being used on the website at any point in time.
Typical scenario for legal investigations: "How were the site's T&Cs in Spanish last year when we were promoting this product?"
Of course, YMMV depending on how developers build their websites.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this comment slip to another point? If I'm not mistaken that line was already in there. Yet if I understood the setup that was aimed for correctly, then this wouldn't be required as in theory it's anyways always build from the individual translation files that are checked in?

```

Be sure to adjust the paths to your needs if you're not using the default values.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

> [!NOTE] 
> Be sure to adjust the paths to your needs if you're not using the default values.


Next, set up **fbtee** in your app's initialization code (e.g., `src/index.tsx`):

```tsx
Expand All @@ -82,13 +96,19 @@ setupFbtee({
});
```

Finally, if you are using React and TypeScript in your project, you need to add TypeScript types for **fbtee** to enable proper type checking in JSX. You can do this by referencing the `ReactTypes.d.ts` file in your main `index.tsx` file or a global type declaration file (e.g., `types.d.ts`):
> [!NOTE]
> At this point you've not yet generated the translation file. Therefore you'll see an error for it no tbeing able to find the module `./translations.json`. This is expected and will be resolved once you've generated the translation file. Simply running the command at this point wouldn't remedy it, as the empty json file wouldn't adhere to the expected type and would also throw an error.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We wouldn't need to write this warning if we moved the fbtee clienside setup instructions later, after explaining how to assemble translation files,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct. However, in my view, it might make sense to organise the entire ReadMe slightly differently. It might make sense to start with the explanation of usage within the codebase, as the commands themselves are only really ‘usable’ once some translations are in the codebase.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor typos if you're keeping this text:

- ... Therefore you'll see an error for it no tbeing able to find the module `./translations.json`. 
+ ... Therefore, you'll see an error for it not being able to find the module `./translations.json`. 


> [!WARNING]
> To be described: How to handle e.g. React Router with "framework mode" with a client and server entry. How to define the language based on e.g. the users browser settings and ensure that there are no hydration errors or the like. Currently the sample is a hardcoded locale and gender.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This WARNING note would be more relevant as a new TODO item to add to #11 instead. We can do that later outside of this PR I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Do you add it to the issue, I'll remove it here?


Next up, if you are using React and TypeScript in your project, you need to add TypeScript types for **fbtee** to enable proper type checking in JSX. You can do this by referencing the `ReactTypes.d.ts` file in your main `index.tsx` file or a global type declaration file (e.g., `types.d.ts`):

```tsx
/// <reference types="fbtee/ReactTypes.d.ts" />
```

_You’re now ready to go!_
_You’re now ready to define your first translatable element!_

## Usage

Expand Down Expand Up @@ -141,16 +161,97 @@ _Note: `<fbt>` is auto-imported for you by the `@nkzw/babel-preset-fbtee` plugin
After marking your strings for translation with `<fbt>`, run the following commands to extract, and compile translations:

```bash
npm run fbtee:collect
npm run fbtee:manifest && npm run fbtee:collect
```

You can now upload the `.source_strings.json` file to your translation provider. One sample for such a translation provider is [Crowdin](https://crowdin.com/).

As a sample the `.source_strings.json` could look like this:

```json
{
"childParentMappings": {},
"phrases": [
{
"hashToLeaf": {
"MB6OYuvCF1VzjOmqinI42g==": {
"desc": "What's next question",
"text": "What's next?"
}
},
"col_beg": 12,
"col_end": 68,
"filepath": "app/welcome/welcome.tsx",
"line_beg": 43,
"line_end": 43,
"project": "",
"jsfbt": {
"m": [],
"t": {
"desc": "What's next question",
"text": "What's next?"
}
}
}
]
}
```

You can now upload the `.source_strings.json` file to your translation provider. Once you have the translated strings stored in a `translations/` folder as JSON files, you can run the following command to generate the translations file:
With the translated filed being for english US (see fbtee setup above) (e.g. `translations/en_US.json`):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before: english US
After:  English US


```json
{
"fb-locale": "en_US",
"translations": {
"MB6OYuvCF1VzjOmqinI42g==": {
"tokens": [],
"types": [],
"translations": [
{
"translation": "What's next?",
"variations": []
}
]
}
}
}
```

For another locale, such as german it could be another file such as `translations/de_DE.json`:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before: For another locale, such as german it could be...
After:  For another locale, such as German, it could be...


```json
{
"fb-locale": "de_DE",
"translations": {
"MB6OYuvCF1VzjOmqinI42g==": {
"tokens": [],
"types": [],
"translations": [
{
"translation": "Was kommt jetzt?",
"variations": []
}
]
}
}
}
```

Once you have the translated strings stored in a `translations/` folder as JSON files, you can run the following command to generate the translations file:

```bash
npm run fbtee:translate
```

After generating the translations file, your app is ready to display translated content in other languages.
This will generate the `translation.json` file referred to in the setup done before. This file might look like this:

```json
{"de_DE":{"2HVYhv":"Was kommt jetzt?"},"en_US":{"2HVYhv":"What's next?"}}
```

After generating the translations file, your app is ready to display translated content in other languages. The error you had until now in the `setupFbtee` with regards to the imported translations file should be resolved now.
kayhadrin marked this conversation as resolved.
Show resolved Hide resolved

Keep in mind that the `translations.json` file needs to be created during your build process in order for **fbtee** to work correctly. You can add the `fbtee:translate` command to your build script.

## ESLint Plugin

Expand Down