Skip to content

Commit

Permalink
Add extract operation
Browse files Browse the repository at this point in the history
  • Loading branch information
fedelman authored Jun 21, 2024
1 parent e834a7b commit b91818f
Show file tree
Hide file tree
Showing 13 changed files with 315 additions and 159 deletions.
13 changes: 12 additions & 1 deletion packages/nx-phrase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,17 @@ This operation pulls (i.e. downloads) translations from phrase into the configur
| branch | In case you're working with branches in phrase. || - |
| useSourceLocaleAsFallback | Emulate phrase fallback_locale behavior via source_locale field. This only works with `react_simple_json` fileFormat || false |

#### Extract

This operation extracts translations from the source code and stores them into a json file (format `react_simple_json`).

| Name | What does it do? | Required | Default |
| --- | --- | :-: | :-: |
| output | Path relative to your project's root directory where the extracted L10N keys are written. || - |
| sourceRoot | Source root override, in case some of your sources are not located in your project's sourceRoot. || Your project's sourceRoot directory (as specified in project.json) |
| sourceGlob | Glob pattern used to search for files containing translations || `**/*.{ts,tsx}` |
| ignoreGlob | Glob pattern to ignore some files that would otherwise be included by `sourceGlob` || |

#### Push

This operation extracts translations from the source code and pushes (i.e. uploads) them to phrase.
Expand All @@ -109,7 +120,7 @@ This operation extracts translations from the source code and pushes (i.e. uploa
| sourceGlob | Glob pattern used to search for files containing translations || `**/*.{ts,tsx}` |
| ignoreGlob | Glob pattern to ignore some files that would otherwise be included by `sourceGlob` || |

#### Unused
#### Find Unused

This operation finds keys in the source code and phrase that are not in use or are missing. By configuring transfomers and filters it is also possible to compare keys that aren't a direct match. This is helpful for example when you allow your translators to create derivative translation keys that target the same translation in code.

Expand Down
7 changes: 6 additions & 1 deletion packages/nx-phrase/executors.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
"schema": "./src/executors/push/schema.json",
"description": "Translation push"
},
"unused": {
"extract": {
"implementation": "./src/executors/extract/executor",
"schema": "./src/executors/extract/schema.json",
"description": "Extract L10N keys from the source code"
},
"find-unused": {
"implementation": "./src/executors/find-unused/executor",
"schema": "./src/executors/unused/schema.json",
"description": "Find unused translations"
Expand Down
3 changes: 2 additions & 1 deletion packages/nx-phrase/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@porscheofficial/nx-phrase",
"version": "0.2.0",
"version": "0.2.1",
"repository": {
"type": "url",
"url": "https://github.com/porscheofficial/nx-plugins",
Expand All @@ -12,6 +12,7 @@
"executors": "./executors.json",
"peerDependencies": {
"@formatjs/cli-lib": "6.1.3",
"debug": "4.3.4",
"fs-extra": "11.1.1",
"form-data": "4.0.0",
"glob": "10.3.1",
Expand Down
3 changes: 3 additions & 0 deletions packages/nx-phrase/src/executors/build/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ExecutorContext } from "@nx/devkit"
import { default as pull } from "../pull/executor"
import { default as push } from "../push/executor"
import { default as findUnused } from "../find-unused/executor"
import { default as extract } from "../extract/executor"
import type { BuildExecutorSchema } from "./schema"

export default async function runExecutor(options: BuildExecutorSchema, context: ExecutorContext) {
Expand All @@ -12,6 +13,8 @@ export default async function runExecutor(options: BuildExecutorSchema, context:
await push(options, context)
} else if (operation === "find-unused") {
await findUnused(options, context)
} else if (operation === "extract") {
await extract(options, context)
} else {
await pull(options, context)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/nx-phrase/src/executors/build/schema.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NonSensitiveArgs } from "../../lib/types"

export type Operation = "push" | "pull" | "find-unused"
export type Operation = "extract" | "push" | "pull" | "find-unused"

export interface BuildExecutorSchema extends Partial<NonSensitiveArgs> {
operation?: Operation
Expand Down
143 changes: 74 additions & 69 deletions packages/nx-phrase/src/executors/build/schema.json
Original file line number Diff line number Diff line change
@@ -1,72 +1,77 @@
{
"version": 2,
"outputCapture": "direct-nodejs",
"$schema": "http://json-schema.org/schema",
"title": "phrase executor",
"description": "l10n utils",
"type": "object",
"properties": {
"operation": {
"description": "pull or push",
"type": "string",
"default": "pull"
"version": 2,
"outputCapture": "direct-nodejs",
"$schema": "http://json-schema.org/schema",
"cli": "nx",
"title": "phrase executor",
"description": "run one of the operations implemented by the other phrase executors",
"type": "object",
"properties": {
"operation": {
"description": "pull, push, extract, or find-unused",
"type": "string",
"default": "pull"
},
"projectId": {
"description": "Phrase project id. Can be found in Phrase project settings under API, or the '☁️ ID'-button on the project overview.",
"type": "string"
},
"branch": {
"description": "(optional) branch in phrase",
"type": "string"
},
"fileFormat": {
"description": "(optional) File format to download from phrase. See https://help.phrase.com/help/supported-platforms-and-formats",
"type": "string"
},
"output": {
"description": "(optional) Path relative to your project's root directory where downloaded translations files will be placed",
"type": "string"
},
"uploadLanguageId": {
"description": "Language ID to use when uploading translations. Can be found in the API section when editing a language",
"type": "string"
},
"sourceRoot": {
"description": "(optional) Source root override, in case some of your sources are not located in your project's sourceRoot",
"type": "string"
},
"sourceGlob": {
"description": "(optional) Glob pattern used to search for files containing translations",
"type": "string"
},
"ignoreGlob": {
"description": "(optional) Glob pattern to ignore some files that would otherwise be included by sourceGlob",
"type": "string"
},
"workingDirectory": {
"description": "The directory below the project root directory where the plugin stores temporary data. If not specified, it is called '.nx-phrase'.",
"type": "string"
},
"sourceKeyTransformer": {
"description": "(optional) Path to file exporting a transform function for keys extracted from the source",
"type": "string"
},
"phraseKeyTransformer": {
"description": "(optional) Path to file exporting a transform function for keys downloaded from phrase",
"type": "string"
},
"sourceKeyFilter": {
"description": "(optional) Path to file containing function to filter keys extracted from source",
"type": "string"
},
"phraseKeyFilter": {
"description": "(optional) Path to file containing function to filter keys downloaded from phrase",
"type": "string"
},
"useSourceLocaleAsFallback": {
"description": "(optional) Emulate phrase fallback_locale behaviour via source_locale field. Only works with fileFormat react_simple_json",
"type": "boolean"
},
"useFallbackLocale": {
"description": "(optional) Pass fallback_locale during locale download to api. All translations that don't exist in the locale currently being downloaded will be complemented with the ones from the fallback_locale",
"type": "boolean"
}
},
"projectId": {
"description": "Phrase project id. Can be found in Phrase project settings under API, or the '☁️ ID'-button on the project overview.",
"type": "string"
},
"branch": {
"description": "(optional) branch in phrase",
"type": "string"
},
"fileFormat": {
"description": "(optional) File format to download from phrase. See https://help.phrase.com/help/supported-platforms-and-formats",
"type": "string"
},
"output": {
"description": "(optional) Path relative to your project's root directory where downloaded translations files will be placed",
"type": "string"
},
"uploadLanguageId": {
"description": "Language ID to use when uploading translations. Can be found in the API section when editing a language",
"type": "string"
},
"sourceRoot": {
"description": "(optional) Source root override, in case some of your sources are not located in your project's sourceRoot",
"type": "string"
},
"sourceGlob": {
"description": "(optional) Glob pattern used to search for files containing translations",
"type": "string"
},
"ignoreGlob": {
"description": "(optional) Glob pattern to ignore some files that would otherwise be included by sourceGlob",
"type": "string"
},
"sourceKeyTransformer": {
"description": "(optional) Path to file exporting a transform function for keys extracted from the source",
"type": "string"
},
"phraseKeyTransformer": {
"description": "(optional) Path to file exporting a transform function for keys downloaded from phrase",
"type": "string"
},
"sourceKeyFilter": {
"description": "(optional) Path to file containing function to filter keys extracted from source",
"type": "string"
},
"phraseKeyFilter": {
"description": "(optional) Path to file containing function to filter keys downloaded from phrase",
"type": "string"
},
"useSourceLocaleAsFallback": {
"description": "(optional) Emulate phrase fallback_locale behaviour via source_locale field. Only works with fileFormat react_simple_json",
"type": "boolean"
},
"useFallbackLocale": {
"description": "(optional) Pass fallback_locale during locale download to api. All translations that don't exist in the locale currently being downloaded will be complemented with the ones from the fallback_locale",
"type": "boolean"
}
},
"required": []
"required": ["projectId", "uploadLanguageId"]
}
26 changes: 26 additions & 0 deletions packages/nx-phrase/src/executors/extract/executor.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { resolve } from "path"

import { ExecutorContext } from "@nx/devkit"

import executor from "./executor"
import { NonSensitiveArgs } from "../../lib/types"

const options: Partial<NonSensitiveArgs> = {
projectId: "projectId",
output: ".nx-phrase/translations",
}

const TEST_ASSETS_DIR = resolve(__dirname, "../../../test")

describe("Extract", () => {
const context = {
root: TEST_ASSETS_DIR,
projectName: "test_app",
workspace: { projects: { test_app: { root: TEST_ASSETS_DIR } } } as unknown,
} as ExecutorContext

it("should extract", async () => {
const output = await executor(options, context)
expect(output.success).toBe(true)
})
})
17 changes: 17 additions & 0 deletions packages/nx-phrase/src/executors/extract/executor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ExecutorContext } from "@nx/devkit"

import { getConfig, InternalPhraseConfig } from "../../lib/config"
import { NonSensitiveArgs } from "../../lib/types"
import { extract } from "../../lib/extract"

export const pullRequiredConfigs = ["output"]

export default async function runExecutor(options: Partial<NonSensitiveArgs>, context: ExecutorContext) {
const config: InternalPhraseConfig = getConfig(options, context, pullRequiredConfigs)

await extract(config, context)

console.log("Done.")

return { success: true }
}
32 changes: 32 additions & 0 deletions packages/nx-phrase/src/executors/extract/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"version": 2,
"outputCapture": "direct-nodejs",
"$schema": "http://json-schema.org/schema",
"cli": "nx",
"title": "phrase executor",
"description": "extract L10N keys from source code and write them into the file system",
"type": "object",
"properties": {
"output": {
"description": "Path relative to your project's root directory where the extracted L10N keys are written",
"type": "string"
},
"sourceRoot": {
"description": "The root directory of the source code",
"type": "string"
},
"sourceGlob": {
"description": "The glob pattern used to search for source files containing translations",
"type": "string"
},
"ignoreGlob": {
"description": "The glob pattern used to ignore some files that would otherwise be included by sourceGlob",
"type": "string"
},
"workingDirectory": {
"description": "The directory below the project root directory where the plugin stores temporary data. If not specified, it is called '.nx-phrase'.",
"type": "string"
}
},
"required": ["output"]
}
16 changes: 8 additions & 8 deletions packages/nx-phrase/src/executors/find-unused/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"$schema": "http://json-schema.org/schema",
"cli": "nx",
"title": "phrase executor",
"description": "find unused translations",
"description": "find L10N keys that are no longer used in the source code and are safe to delete from Phrase",
"type": "object",
"properties": {
"properties": {
"projectId": {
"description": "Id of translation project in phrase",
"description": "Phrase project id. Can be found in Phrase project settings under API, or the '☁️ ID'-button on the project overview.",
"type": "string"
},
"sourceKeyTransformer": {
Expand All @@ -28,23 +28,23 @@
"type": "string"
},
"branch": {
"description": "",
"description": "a branch in phrase (optional)",
"type": "string"
},
"sourceRoot": {
"description": "",
"description": "The root directory of the source code",
"type": "string"
},
"sourceGlob": {
"description": "",
"description": "The glob pattern used to search for source files containing translations",
"type": "string"
},
"ignoreGlob": {
"description": "",
"description": "The glob pattern used to ignore some files that would otherwise be included by sourceGlob",
"type": "string"
},
"workingDirectory": {
"description": "",
"description": "The directory below the project root directory where the plugin stores temporary data. If not specified, it is called '.nx-phrase'.",
"type": "string"
}
},
Expand Down
Loading

0 comments on commit b91818f

Please sign in to comment.