Skip to content

Commit

Permalink
feat(vite): support different extensions for catalogs. Improve coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
timofei-iatsenko committed Mar 16, 2023
1 parent 4f1d30e commit bd58939
Show file tree
Hide file tree
Showing 17 changed files with 339 additions and 232 deletions.
6 changes: 5 additions & 1 deletion packages/vite-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# @lingui/vite-plugin

> Vite plugin which compiles on the fly the .po files for auto-refreshing. In summary, `lingui compile` command isn't required when using this plugin
> Vite plugin which compiles on the fly lingui catalogs. In summary, `lingui compile` command isn't required when using this plugin
`@lingui/vite-plugin` is part of [LinguiJS][linguijs]. See the [documentation][documentation] for all information, tutorials and examples.

Expand All @@ -31,7 +31,11 @@ const config: UserConfig = {
### Then in Vite-processed code:

```ts
// *.po files assigned to this loader by default
const { messages } = await import(`./locales/${language}.po`);

// for other extension you have to use `?lingui` suffix
const { messages } = await import(`./locales/${language}.json?lingui`);
```
> See Vite's official documentation for more info about Vite dynamic imports
> https://vitejs.dev/guide/features.html#dynamic-import
Expand Down
2 changes: 1 addition & 1 deletion packages/vite-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@
"@lingui/conf": "4.0.0-next.1"
},
"devDependencies": {
"vite": "3.2.4"
"vite": "4.1.4"
}
}
16 changes: 15 additions & 1 deletion packages/vite-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import path from "path"
import type { Plugin } from "vite"

const fileRegex = /\.(po)$/
const fileRegex = /(\.po|\?lingui)$/

type LinguiConfigOpts = {
cwd?: string
Expand All @@ -29,13 +29,27 @@ export function lingui(linguiConfig: LinguiConfigOpts = {}): Plugin {

async transform(src, id) {
if (fileRegex.test(id)) {
id = id.split("?")[0]

const catalogRelativePath = path.relative(config.rootDir, id)

const fileCatalog = getCatalogForFile(
catalogRelativePath,
getCatalogs(config)
)

if (!fileCatalog) {
throw new Error(
`Requested resource ${catalogRelativePath} is not matched to any of your catalogs paths specified in "lingui.config".
Resource: ${id}
Your catalogs:
${config.catalogs.map((c) => c.path).join("\n")}
Please check that catalogs.path is filled properly.\n`
)
}

const { locale, catalog } = fileCatalog

const messages = await catalog.getTranslations(locale, {
Expand Down
21 changes: 19 additions & 2 deletions packages/vite-plugin/test/__snapshots__/index.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,24 @@

exports[`vite-plugin should return compiled catalog 1`] = `
{
code: /*eslint-disable*/export const messages=JSON.parse("{\\"mY42CM\\":\\"Hello World\\",\\"mVmaLu\\":[\\"My name is \\",[\\"name\\"]]}");,
map: null,
mVmaLu: [
My name is ,
[
name,
],
],
mY42CM: Hello World,
}
`;

exports[`vite-plugin should return compiled catalog json 1`] = `
{
key: Message,
key2: [
Hello ,
[
name,
],
],
}
`;
21 changes: 21 additions & 0 deletions packages/vite-plugin/test/default-vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { UserConfig } from "vite"
import { lingui } from "../src/index"
import path from "path"

export function createDefaultViteConfig(dirname: string): UserConfig {
return {
build: {
lib: {
entry: path.resolve(dirname, "entrypoint.js"),
fileName: "bundle",
formats: ["cjs"],
},
},

plugins: [
lingui({
cwd: dirname,
}),
],
}
}
55 changes: 46 additions & 9 deletions packages/vite-plugin/test/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,52 @@
import path from "path"
import { lingui } from "../src"
import { exec as _exec } from "child_process"
import { mkdtempSync } from "fs"
import os from "os"

describe("vite-plugin", () => {
it("should return compiled catalog", async () => {
const p = lingui({
configPath: path.resolve(__dirname, ".linguirc"),
})
const result = await (p.transform as any)(
"",
path.join(__dirname, "locale", "en", "messages.po")
)
expect(result).toMatchSnapshot()
const mod = await runVite(`po-format/vite.config.ts`)
expect((await mod.load()).messages).toMatchSnapshot()
})

it("should return compiled catalog json", async () => {
const mod = await runVite(`json-format/vite.config.ts`)

expect((await mod.load()).messages).toMatchSnapshot()
})
})

async function runVite(configPath: string) {
const outDir = mkdtempSync(
path.join(os.tmpdir(), `lingui-test-${process.pid}`)
)
const command =
path.resolve(__dirname, `../node_modules/.bin/vite`) +
` build -c ` +
path.resolve(__dirname, configPath) +
` --emptyOutDir --outDir ${outDir}`
await exec(command)

return await import(path.resolve(outDir, "bundle.js"))
}

function exec(cmd: string) {
const _options = {
env: process.env,
}
return new Promise((resolve, reject) => {
_exec(cmd, _options, (error, stdout, stderr) => {
stdout = stdout.trim()
stderr = stderr.trim()

if (error === null) {
resolve({ stdout, stderr })
} else {
reject({ error, stdout, stderr })
console.error(stdout)
console.error(stderr)
process.exit(1)
}
})
})
}
7 changes: 7 additions & 0 deletions packages/vite-plugin/test/json-format/.linguirc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"locales": ["en"],
"catalogs": [{
"path": "<rootDir>/locale/{locale}"
}],
"format": "minimal"
}
3 changes: 3 additions & 0 deletions packages/vite-plugin/test/json-format/entrypoint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export async function load() {
return await import("./locale/en.json?lingui")
}
4 changes: 4 additions & 0 deletions packages/vite-plugin/test/json-format/locale/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"key": "Message",
"key2": "Hello {name}"
}
3 changes: 3 additions & 0 deletions packages/vite-plugin/test/json-format/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createDefaultViteConfig } from "../default-vite.config"

export default createDefaultViteConfig(__dirname)
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions packages/vite-plugin/test/po-format/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createDefaultViteConfig } from "../default-vite.config"

export default createDefaultViteConfig(__dirname)
10 changes: 9 additions & 1 deletion website/docs/ref/vite-plugin.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Vite Plugin

`@lingui/vite-plugin` is a Vite plugin, which compiles `.po` catalogs on the fly and provides additional required configuration for Vite.
`@lingui/vite-plugin` is a Vite plugin, which compiles Lingui catalogs on the fly and provides additional required configuration for Vite.

:::note
Refer to [Setup with Vite](/docs/tutorials/setup-vite.md) for a full installation guide.
Expand Down Expand Up @@ -38,6 +38,14 @@ export async function dynamicActivate(locale: string) {
}
```

:::note
If you use format which has different extension then `*.po` you need to specify `?lingui` suffix

```ts
const { messages } = await import(`./locales/${language}.json?lingui`);
```
:::

See the [guide about dynamic loading catalogs](/docs/guides/dynamic-loading-catalogs.md) for more info.

See [Vite's official documentation](https://vitejs.dev/guide/features.html#dynamic-import) for more info about Vite dynamic imports.
Expand Down
Loading

0 comments on commit bd58939

Please sign in to comment.