Skip to content

Commit 7365339

Browse files
committed
feat: add metro transformer
1 parent 088efe5 commit 7365339

14 files changed

Lines changed: 499 additions & 31 deletions

File tree

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ module.exports = {
6262
"<rootDir>/packages/cli",
6363
"<rootDir>/packages/conf",
6464
"<rootDir>/packages/loader",
65+
"<rootDir>/packages/metro-transformer",
6566
"<rootDir>/packages/macro",
6667
"<rootDir>/packages/vite-plugin",
6768
"<rootDir>/packages/format-po",

packages/conf/src/getConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export function getConfig({
7171
)
7272

7373
// gracefully stop further executing
74-
throw new Error("No Config")
74+
throw new Error("No Lingui config found")
7575
}
7676

7777
const userConfig = result ? result.config : {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Change Log
2+
3+
All notable changes to this project will be documented in this file.
4+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5+
6+
### Features
7+
8+
- use fallback locales from cldr ([#820](https://github.com/lingui/js-lingui/issues/820)) ([2d9e124](https://github.com/lingui/js-lingui/commit/2d9e124b91f1ba7a65e9f997a3ba952679c6c23a))
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[![License][badge-license]][license]
2+
[![Version][badge-version]][package]
3+
[![Downloads][badge-downloads]][package]
4+
5+
# @lingui/metro-transformer
6+
7+
> Metro bundler transformer for LinguiJS catalogs
8+
9+
`@lingui/metro-transformer` is part of [LinguiJS][linguijs]. See the
10+
[documentation][documentation] for all information, tutorials and examples.
11+
12+
## Installation
13+
14+
```sh
15+
npm install --save-dev @lingui/metro-transformer
16+
# yarn add --dev @lingui/metro-transformer
17+
```
18+
19+
## Usage
20+
21+
See the [reference][reference] documentation.
22+
23+
## License
24+
25+
This package is licensed under [MIT][license] license.
26+
27+
[license]: https://github.com/lingui/js-lingui/blob/main/LICENSE
28+
[linguijs]: https://github.com/lingui/js-lingui
29+
[documentation]: https://lingui.dev
30+
[reference]: https://lingui.dev/ref/metro-transformer
31+
[package]: https://www.npmjs.com/package/@lingui/metro-transformer
32+
[badge-downloads]: https://img.shields.io/npm/dw/@lingui/metro-transformer.svg
33+
[badge-version]: https://img.shields.io/npm/v/@lingui/metro-transformer.svg
34+
[badge-license]: https://img.shields.io/npm/l/@lingui/metro-transformer.svg
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"name": "@lingui/metro-transformer",
3+
"version": "0.1.0",
4+
"description": "Metro bundler transformer for LinguiJS catalogs",
5+
"exports": {
6+
"./expo": {
7+
"require": "./dist/expo/index.cjs",
8+
"import": "./dist/expo/index.mjs",
9+
"types": "./dist/expo/index.d.ts"
10+
},
11+
"./react-native": {
12+
"require": "./dist/react-native/index.cjs",
13+
"import": "./dist/react-native/index.mjs",
14+
"types": "./dist/react-native/index.d.ts"
15+
}
16+
},
17+
"sideEffects": false,
18+
"author": {
19+
"name": "Vojtech Novak",
20+
"email": "vonovak@gmail.com"
21+
},
22+
"license": "MIT",
23+
"keywords": [
24+
"metro",
25+
"react native",
26+
"metro bundler",
27+
"i18n",
28+
"internationalization",
29+
"i10n",
30+
"localization",
31+
"i9n",
32+
"translation",
33+
"multilingual"
34+
],
35+
"scripts": {
36+
"build": "rimraf ./dist && unbuild",
37+
"stub": "unbuild --stub"
38+
},
39+
"repository": {
40+
"type": "git",
41+
"url": "https://github.com/lingui/js-lingui.git"
42+
},
43+
"bugs": {
44+
"url": "https://github.com/lingui/js-lingui/issues"
45+
},
46+
"engines": {
47+
"node": ">=18.0.0"
48+
},
49+
"files": [
50+
"LICENSE",
51+
"README.md",
52+
"dist/"
53+
],
54+
"dependencies": {
55+
"@babel/runtime": "^7.20.13",
56+
"@lingui/cli": "4.11.2",
57+
"@lingui/conf": "4.11.2"
58+
},
59+
"devDependencies": {
60+
"@lingui/format-json": "4.11.2",
61+
"rimraf": "^6.0.1",
62+
"unbuild": "2.0.0"
63+
},
64+
"peerDependencies": {
65+
"metro": "*"
66+
}
67+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { createLinguiMetroTransformer } from "../metroTransformer"
2+
3+
const expoTransformer = require("@expo/metro-config/babel-transformer")
4+
5+
export const transform = createLinguiMetroTransformer(expoTransformer)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { getConfig } from "@lingui/conf"
2+
import {
3+
createCompiledCatalog,
4+
getCatalogForFile,
5+
getCatalogs,
6+
} from "@lingui/cli/api"
7+
import type { BabelTransformer, BabelTransformerArgs } from "./types"
8+
9+
export const createLinguiMetroTransformer = (
10+
upstreamTransformer: BabelTransformer
11+
): BabelTransformer["transform"] => {
12+
return async function linguiMetroTransformer(params) {
13+
if (!params.filename.endsWith(".po")) {
14+
return upstreamTransformer.transform(params)
15+
}
16+
const jsSource = await transformFile(params)
17+
return upstreamTransformer.transform({
18+
...params,
19+
src: jsSource,
20+
})
21+
}
22+
}
23+
24+
export async function transformFile(
25+
params: Pick<BabelTransformerArgs, "filename">
26+
) {
27+
const config = getConfig()
28+
29+
const catalogRelativePath = params.filename
30+
31+
const fileCatalog = getCatalogForFile(
32+
catalogRelativePath,
33+
await getCatalogs(config)
34+
)
35+
36+
if (!fileCatalog) {
37+
throw new Error(
38+
`Requested resource ${catalogRelativePath} is not matched to any of your catalogs paths specified in "lingui.config".
39+
40+
Your catalogs:
41+
${config.catalogs.map((c) => c.path).join("\n")}
42+
43+
Working dir is:
44+
${process.cwd()}
45+
46+
Please check that \`catalogs.path\` is filled properly and restart the Metro server.\n`
47+
)
48+
}
49+
50+
const { locale, catalog } = fileCatalog
51+
52+
const messages = await catalog.getTranslations(locale, {
53+
fallbackLocales: config.fallbackLocales,
54+
sourceLocale: config.sourceLocale,
55+
})
56+
57+
const strict = process.env.NODE_ENV !== "production"
58+
59+
return createCompiledCatalog(locale, messages, {
60+
strict,
61+
namespace: "es",
62+
pseudoLocale: config.pseudoLocale,
63+
})
64+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { createLinguiMetroTransformer } from "../metroTransformer"
2+
3+
const reactNativeTransformer = (() => {
4+
try {
5+
return require("@react-native/metro-babel-transformer")
6+
} catch (error) {
7+
return require("metro-react-native-babel-transformer")
8+
}
9+
})()
10+
11+
export const transform = createLinguiMetroTransformer(reactNativeTransformer)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// taken and edited from https://github.com/facebook/metro/blob/main/packages/metro-babel-transformer/types/index.d.ts
2+
3+
export type BabelTransformerArgs = {
4+
readonly filename: string
5+
readonly options: unknown // a more precise type would be BabelTransformerOptions but we don't care about its shape
6+
readonly plugins?: unknown
7+
readonly src: string
8+
}
9+
10+
export type BabelTransformer = {
11+
transform: (args: BabelTransformerArgs) => Promise<{
12+
ast: unknown
13+
metadata: unknown
14+
}>
15+
getCacheKey?: () => string
16+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module.exports = {
2+
locales: ["en", "cs"],
3+
sourceLocale: "en",
4+
catalogs: [
5+
{
6+
path: "locales/{locale}/messages",
7+
include: ["src"],
8+
},
9+
],
10+
fallbackLocales: {
11+
cs: "en",
12+
},
13+
format: "po",
14+
}

0 commit comments

Comments
 (0)