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

feat(vite-plugin): support different extensions for catalogs. Improve coverage #1526

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
13 changes: 8 additions & 5 deletions .github/workflows/main-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ jobs:
- name: Install dependencies if needed
run: yarn install --network-timeout 1000000

- name: Build packages
run: yarn release:build

- name: Unit Testing
run: yarn test:ci

Expand All @@ -54,18 +57,18 @@ jobs:
- name: Install dependencies if needed
run: yarn install

- name: Unit Testing
run: yarn test:ci:coverage
- name: Check Prettier Formatting
run: yarn prettier:check

- name: Linting & Types
run: yarn lint:all

- name: Check Prettier Formatting
run: yarn prettier:check

- name: Build packages
run: yarn release:build

- name: Unit Testing
run: yarn test:ci:coverage

- name: Test Public Typings
run: yarn test:tsd

Expand Down
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
7 changes: 0 additions & 7 deletions packages/vite-plugin/test/.linguirc

This file was deleted.

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,
}),
],
}
}
67 changes: 57 additions & 10 deletions packages/vite-plugin/test/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,62 @@
import path from "path"
import { lingui } from "../src"
import { exec as _exec } from "child_process"
import { mkdtempSync } from "fs"
import os from "os"

const skipOnWindows = os.platform() === "win32" ? it.skip : it

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()
skipOnWindows("should return compiled catalog", async () => {
const mod = await runVite(`po-format/vite.config.ts`)
expect((await mod.load()).messages).toMatchSnapshot()
})

skipOnWindows("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) {
// we could not use Vite directly using nodejs api because Vite is native ESM module
// and Jest should be reconfigured completely to be able to require such modules
const packageJsonPath = require.resolve("vite/package.json")
const packageJson = require("vite/package.json")
const viteExecutable = path.resolve(
path.dirname(packageJsonPath),
packageJson.bin.vite
)

const outDir = mkdtempSync(
path.join(os.tmpdir(), `lingui-test-${process.pid}`)
)
const command =
viteExecutable +
` 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)
}
})
})
}
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)
5 changes: 0 additions & 5 deletions packages/vite-plugin/test/locale/en/messages.po

This file was deleted.

7 changes: 7 additions & 0 deletions packages/vite-plugin/test/po-format/.linguirc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"locales": ["en"],
"catalogs": [{
"path": "<rootDir>/locale/{locale}"
}],
"format": "po"
}
3 changes: 3 additions & 0 deletions packages/vite-plugin/test/po-format/entrypoint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export async function load() {
return import("./locale/en.po")
}
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