Skip to content

Commit 10bce7d

Browse files
authored
feat: Lingui compiles to typescript files (#942)
1 parent 8c39c90 commit 10bce7d

11 files changed

Lines changed: 66 additions & 13 deletions

File tree

docs/guides/typescript.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ In your ``webpack.config.js``, use both ``babel-loader`` and ``ts-loader`` for T
5353
To supply babel options for the extraction process use :conf:`extractBabelOptions` configuration option.
5454

5555

56-
:conf:`compileNamespace` must be set to ``es`` (ES6 default export) in the Lingui config
56+
:conf:`compileNamespace` must be set to ``ts`` (ES6 default export) in the Lingui config
5757
otherwise compiled catalogs can't be imported using ES ``import``, but rather CommonJS ``require``:
5858

5959
.. code:: js
6060
6161
{
62-
"compileNamespace": "es"
62+
"compileNamespace": "ts"
6363
}
6464
6565
Type definitions

docs/ref/cli.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,8 @@ Prints additional information.
139139

140140
Specify namespace for compiled message catalogs (also see :conf:`compileNamespace` for
141141
global configuration).
142+
143+
.. lingui-cli-option:: --typescript
144+
145+
Is the same as using :conf:`compileNamespace` with the value "ts".
146+
Generates a {compiledFile}.d.ts and the compiled file is generated using the extension .ts

docs/ref/conf.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,20 @@ Use ES6 named export:
199199
200200
/* eslint-disable */export const messages = {"..."}
201201
202+
ts
203+
^^
204+
205+
Use ES6 named export + .ts file with an additional {compiledFile}.d.ts file:
206+
207+
.. code-block:: js
208+
209+
/* eslint-disable */export const messages = {"..."}
210+
211+
.. code-block:: js
212+
import { Messages } from '@lingui/core';
213+
declare const messages: Messages;
214+
export { messages };
215+
202216
(window|global)\.(.*)
203217
^^^^^^^^^^^^^^^^^^^^^
204218

packages/cli/src/api/__snapshots__/compile.test.ts.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ exports[`createCompiledCatalog options.namespace should compile with es 1`] = `/
1010
1111
exports[`createCompiledCatalog options.namespace should compile with global 1`] = `/*eslint-disable*/global.test={messages:{}};`;
1212
13+
exports[`createCompiledCatalog options.namespace should compile with ts 1`] = `/*eslint-disable*/export const messages={};`;
14+
1315
exports[`createCompiledCatalog options.namespace should compile with window 1`] = `/*eslint-disable*/window.test={messages:{}};`;
1416
1517
exports[`createCompiledCatalog options.namespace should error with invalid value 1`] = `Invalid namespace param: "global"`;

packages/cli/src/api/catalog.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,25 @@ describe("writeCompiled", function () {
969969
)
970970
})
971971

972+
it("saves TS modules to .ts files", function () {
973+
const localeDir = copyFixture(fixture("locales", "initial/"))
974+
const catalog = new Catalog(
975+
{
976+
name: "messages",
977+
path: path.join(localeDir, "{locale}", "messages"),
978+
include: [],
979+
exclude: [],
980+
},
981+
mockConfig()
982+
)
983+
984+
const namespace = "ts"
985+
const compiledCatalog = createCompiledCatalog("en", {}, { namespace })
986+
expect(catalog.writeCompiled("en", compiledCatalog, namespace)).toMatch(
987+
/\.ts$/
988+
)
989+
})
990+
972991
it("saves anything else than ES modules to .js files", function () {
973992
const localeDir = copyFixture(fixture("locales", "initial/"))
974993
const catalog = new Catalog(

packages/cli/src/api/catalog.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import extract from "./extractors"
1414
import { prettyOrigin, removeDirectory } from "./utils"
1515
import { CliExtractOptions } from "../lingui-extract"
1616
import { CliExtractTemplateOptions } from "../lingui-extract-template"
17+
import { CompiledCatalogNamespace } from "./compile"
1718

1819
const NAME = "{name}"
1920
const LOCALE = "{locale}"
@@ -343,9 +344,17 @@ export class Catalog {
343344
poFormat.write(filename, messages, options)
344345
}
345346

346-
writeCompiled(locale: string, compiledCatalog: string, namespace?: string) {
347-
const ext = `.${namespace === "es" ? "mjs" : "js"}`
348-
const filename = this.path.replace(LOCALE, locale) + ext
347+
writeCompiled(locale: string, compiledCatalog: string, namespace?: CompiledCatalogNamespace) {
348+
let ext;
349+
if (namespace === "es") {
350+
ext = "mjs"
351+
} else if (namespace === "ts") {
352+
ext = "ts"
353+
} else {
354+
ext = "js"
355+
}
356+
357+
const filename = `${this.path.replace(LOCALE, locale)}.${ext}`
349358

350359
const basedir = path.dirname(filename)
351360
if (!fs.existsSync(basedir)) {

packages/cli/src/api/compile.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ describe("createCompiledCatalog", () => {
8989
expect(getCompiledCatalog("es")).toMatchSnapshot()
9090
})
9191

92+
it("should compile with ts", () => {
93+
expect(getCompiledCatalog("ts")).toMatchSnapshot()
94+
})
95+
9296
it("should compile with window", () => {
9397
expect(getCompiledCatalog("window.test")).toMatchSnapshot()
9498
})

packages/cli/src/api/compile.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as R from "ramda"
55

66
import pseudoLocalize from "./pseudoLocalize"
77

8-
type CompiledCatalogNamespace = "cjs" | "es" | string
8+
export type CompiledCatalogNamespace = "cjs" | "es" | "ts" | string
99

1010
type CompiledCatalogType = {
1111
[msgId: string]: string
@@ -53,7 +53,7 @@ export function createCompiledCatalog(
5353
}
5454

5555
function buildExportStatement(expression, namespace: CompiledCatalogNamespace) {
56-
if (namespace === "es") {
56+
if (namespace === "es" || namespace === "ts") {
5757
// export const messages = { message: "Translation" }
5858
return t.exportNamedDeclaration(
5959
t.variableDeclaration("const", [

packages/cli/src/lingui-compile.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ function command(config: LinguiConfig, options) {
8282
if (doMerge) {
8383
mergedCatalogs = { ...mergedCatalogs, ...messages }
8484
} else {
85-
const namespace = options.namespace || config.compileNamespace
85+
const namespace = options.typescript ? "ts" : options.namespace || config.compileNamespace
8686
const compiledCatalog = createCompiledCatalog(locale, messages, {
8787
strict: false,
8888
namespace,
@@ -97,7 +97,7 @@ function command(config: LinguiConfig, options) {
9797
)
9898

9999
if (options.typescript) {
100-
const typescriptPath = compiledPath.replace(/\.jsx?$/, "") + ".d.ts"
100+
const typescriptPath = compiledPath.replace(/\.ts?$/, "") + ".d.ts"
101101
fs.writeFileSync(
102102
typescriptPath,
103103
`import { Messages } from '@lingui/core';
@@ -156,7 +156,7 @@ if (require.main === module) {
156156
const results = command(config, {
157157
verbose: program.verbose || false,
158158
allowEmpty: !program.strict,
159-
typescript: program.typescript || false,
159+
typescript: program.typescript || config.compileNamespace === "ts" || false,
160160
namespace: program.namespace, // we want this to be undefined if user does not specify so default can be used
161161
})
162162

packages/conf/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export declare type FallbackLocales = LocaleObject | DefaultLocaleObject
2424

2525
export declare type LinguiConfig = {
2626
catalogs: CatalogConfig[];
27-
compileNamespace: string;
27+
compileNamespace: "es" | "cjs" | "ts" | string;
2828
extractBabelOptions: Record<string, unknown>;
2929
compilerBabelOptions: GeneratorOptions;
3030
fallbackLocales: FallbackLocales;
@@ -56,7 +56,7 @@ export declare const configValidation: {
5656
};
5757
compilerBabelOptions: GeneratorOptions;
5858
catalogs: CatalogConfig[];
59-
compileNamespace: string;
59+
compileNamespace: "es" | "ts" | "cjs" | string;
6060
fallbackLocales: FallbackLocales;
6161
format: CatalogFormat;
6262
formatOptions: CatalogFormatOptions;

0 commit comments

Comments
 (0)