Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 9 additions & 8 deletions packages/cli/src/api/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ export class Catalog {
getTemplatePath(this.format.getTemplateExtension(), this.path)
}

getFilename(locale: string): string {
return (
replacePlaceholders(this.path, { locale }) +
this.format.getCatalogExtension()
)
}

async make(options: MakeOptions): Promise<AllCatalogsType | false> {
const nextCatalog = await this.collect({ files: options.files })
if (!nextCatalog) return false
Expand Down Expand Up @@ -176,9 +183,7 @@ export class Catalog {
locale: string,
messages: CatalogType
): Promise<[created: boolean, filename: string]> {
const filename =
replacePlaceholders(this.path, { locale }) +
this.format.getCatalogExtension()
const filename = this.getFilename(locale)

const created = !fs.existsSync(filename)

Expand Down Expand Up @@ -211,11 +216,7 @@ export class Catalog {
}

async read(locale: string): Promise<CatalogType> {
const filename =
replacePlaceholders(this.path, { locale }) +
this.format.getCatalogExtension()

return await this.format.read(filename, locale)
return await this.format.read(this.getFilename(locale), locale)
}

async readAll(): Promise<AllCatalogsType> {
Expand Down
76 changes: 76 additions & 0 deletions packages/cli/src/api/catalog/getCatalogDependentFiles.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { getCatalogDependentFiles, getFormat } from "@lingui/cli/api"
import { makeConfig } from "@lingui/conf"
import { Catalog } from "../catalog"
import { FormatterWrapper } from "../formats"

describe("getCatalogDependentFiles", () => {
let format: FormatterWrapper

beforeAll(async () => {
format = await getFormat("po", {}, "en")
})

it("Should return list template + fallbacks + sourceLocale", () => {
const config = makeConfig(
{
locales: ["en", "pl", "es", "pt-PT", "pt-BR"],
sourceLocale: "en",
fallbackLocales: {
"pt-PT": "pt-BR",
default: "en",
},
},
{ skipValidation: true }
)

const catalog = new Catalog(
{
name: null,
path: "src/locales/{locale}",
include: ["src/"],
exclude: [],
format,
},
config
)

expect(getCatalogDependentFiles(catalog, "pt-PT")).toMatchInlineSnapshot(`
[
src/locales/messages.pot,
src/locales/pt-BR.po,
src/locales/en.po,
]
`)
})

it("Should not return itself", () => {
const config = makeConfig(
{
locales: ["en", "pl", "es", "pt-PT", "pt-BR"],
sourceLocale: "en",
fallbackLocales: {
"pt-PT": "pt-BR",
default: "en",
},
},
{ skipValidation: true }
)

const catalog = new Catalog(
{
name: null,
path: "src/locales/{locale}",
include: ["src/"],
exclude: [],
format,
},
config
)

expect(getCatalogDependentFiles(catalog, "en")).toMatchInlineSnapshot(`
[
src/locales/messages.pot,
]
`)
})
})
23 changes: 23 additions & 0 deletions packages/cli/src/api/catalog/getCatalogDependentFiles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Catalog } from "../catalog"
import { getFallbackListForLocale } from "./getFallbackListForLocale"

/**
* Return all files catalog implicitly depends on.
*/
export function getCatalogDependentFiles(
catalog: Catalog,
locale: string
): string[] {
const files = new Set([catalog.templateFile])
getFallbackListForLocale(catalog.config.fallbackLocales, locale).forEach(
(locale) => {
files.add(catalog.getFilename(locale))
}
)

if (catalog.config.sourceLocale && locale !== catalog.config.sourceLocale) {
files.add(catalog.getFilename(catalog.config.sourceLocale))
}

return Array.from(files.values())
}
64 changes: 64 additions & 0 deletions packages/cli/src/api/catalog/getFallbackListForLocale.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { getFallbackListForLocale } from "./getFallbackListForLocale"

describe("getFallbackListForLocale", () => {
it("Should return normalized fallback locales for passed locale", () => {
const actual = getFallbackListForLocale(
{
"pt-PT": "pt-BR",
default: "en",
},
"pt-PT"
)

expect(actual).toMatchInlineSnapshot(`
[
pt-BR,
en,
]
`)
})

it("Should work with list of fallbacks", () => {
const actual = getFallbackListForLocale(
{
"pt-PT": ["pt-BR", "pt"],
default: "en",
},
"pt-PT"
)

expect(actual).toMatchInlineSnapshot(`
[
pt-BR,
pt,
en,
]
`)
})

it("Should work when no fallback set", () => {
const actual = getFallbackListForLocale(
{
default: "en",
},
"pt-PT"
)

expect(actual).toMatchInlineSnapshot(`
[
en,
]
`)
})

it("Should not return itself", () => {
const actual = getFallbackListForLocale(
{
default: "en",
},
"en"
)

expect(actual).toMatchInlineSnapshot(`[]`)
})
})
19 changes: 19 additions & 0 deletions packages/cli/src/api/catalog/getFallbackListForLocale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { FallbackLocales } from "@lingui/conf"

export function getFallbackListForLocale(
fallbackLocales: FallbackLocales,
locale: string
): string[] {
const fL: string[] = []

if (fallbackLocales?.[locale]) {
const mapping = fallbackLocales?.[locale]
Array.isArray(mapping) ? fL.push(...mapping) : fL.push(mapping)
}

if (fallbackLocales?.default && locale !== fallbackLocales?.default) {
fL.push(fallbackLocales?.default)
}

return fL
}
19 changes: 6 additions & 13 deletions packages/cli/src/api/catalog/getTranslationsForCatalog.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Catalog } from "../catalog"
import { FallbackLocales } from "@lingui/conf"
import type { AllCatalogsType, CatalogType, MessageType } from "../types"
import { getFallbackListForLocale } from "./getFallbackListForLocale"

export type TranslationMissingEvent = {
source: string
Expand Down Expand Up @@ -53,19 +54,14 @@ function getTranslation(
}

const getMultipleFallbacks = (_locale: string) => {
const fL = fallbackLocales && fallbackLocales?.[_locale]
const fL = getFallbackListForLocale(fallbackLocales, _locale)

// some probably the fallback will be undefined, so just search by locale
if (!fL) return null
if (!fL.length) return null

if (Array.isArray(fL)) {
for (const fallbackLocale of fL) {
if (catalogs[fallbackLocale] && getTranslation(fallbackLocale)) {
return getTranslation(fallbackLocale)
}
for (const fallbackLocale of fL) {
if (catalogs[fallbackLocale] && getTranslation(fallbackLocale)) {
return getTranslation(fallbackLocale)
}
} else {
return getTranslation(fL)
}
}

Expand All @@ -75,14 +71,11 @@ function getTranslation(
// -> template message
// ** last resort **
// -> id

let translation =
// Get translation in target locale
getTranslation(locale) ||
// We search in fallbackLocales as dependent of each locale
getMultipleFallbacks(locale) ||
// Get translation in fallbackLocales.default (if any)
(fallbackLocales?.default && getTranslation(fallbackLocales.default)) ||
(sourceLocale &&
sourceLocale === locale &&
sourceLocaleFallback(catalogs[sourceLocale], key))
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ export { getCatalogForFile, getCatalogs } from "./catalog/getCatalogs"
export { createCompiledCatalog } from "./compile"

export { default as extractor } from "./extractors/babel"

export { getCatalogDependentFiles } from "./catalog/getCatalogDependentFiles"
export * from "./types"
5 changes: 5 additions & 0 deletions packages/loader/src/webpackLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
createCompiledCatalog,
getCatalogs,
getCatalogForFile,
getCatalogDependentFiles,
} from "@lingui/cli/api"
import { LoaderDefinitionFunction } from "webpack"

Expand All @@ -28,6 +29,10 @@ const loader: LoaderDefinitionFunction<LinguiLoaderOptions> = async function (
await getCatalogs(config)
)

getCatalogDependentFiles(catalog, locale).forEach((locale) => {
this.addDependency(catalog.getFilename(locale))
})

const messages = await catalog.getTranslations(locale, {
fallbackLocales: config.fallbackLocales,
sourceLocale: config.sourceLocale,
Expand Down
5 changes: 5 additions & 0 deletions packages/vite-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
createCompiledCatalog,
getCatalogs,
getCatalogForFile,
getCatalogDependentFiles,
} from "@lingui/cli/api"
import path from "path"
import type { Plugin } from "vite"
Expand Down Expand Up @@ -52,6 +53,10 @@ Please check that catalogs.path is filled properly.\n`

const { locale, catalog } = fileCatalog

getCatalogDependentFiles(catalog, locale).forEach((locale) => {
this.addWatchFile(catalog.getFilename(locale))
})

const messages = await catalog.getTranslations(locale, {
fallbackLocales: config.fallbackLocales,
sourceLocale: config.sourceLocale,
Expand Down