Skip to content

Commit

Permalink
Emulate phrase fallback locale via source_locale property
Browse files Browse the repository at this point in the history
  • Loading branch information
konqi authored Nov 9, 2022
1 parent d5f09b0 commit 4da32fd
Show file tree
Hide file tree
Showing 14 changed files with 165 additions and 1,098 deletions.
1 change: 1 addition & 0 deletions packages/nx-phrase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ This operation pulls (i.e. downloads) translations from phrase into the configur
| output | Where downloaded translations files will be placed relative to your project's root directory. || `./translations` |
| fileFormat | File format to download from phrase. See [supported platforms and formats](https://help.phrase.com/help/supported-platforms-and-formats) || `react_simple_json` |
| 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 |

#### Push

Expand Down
12 changes: 10 additions & 2 deletions packages/nx-phrase/src/executors/build/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,20 @@
"type": "string"
},
"sourceKeyFilter": {
"description": "path to file containing function to filter keys extracted from source",
"description": "(optional) Path to file containing function to filter keys extracted from source",
"type": "string"
},
"phraseKeyFilter": {
"description": "path to file containing function to filter keys downlaaded from phrase",
"description": "(optional) Path to file containing function to filter keys downloaded from phrase",
"type": "string"
},
"useSourceLocaleAsFallback": {
"description": "Emulate phrase fallback_locale behaviour via source_locale field",
"type": "boolean"
},
"useFallbackLocale": {
"description": "not not use",
"type": "boolean"
}
},
"required": []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function nockForProject(projectId = "project_id") {
.get(/\/projects\/[^/]+\/locales\/[^/]+\/download/)
.matchHeader("Authorization", /token .*/)
.query({ file_format: "react_simple_json" })
.twice()
.thrice()
.replyWithFile(200, `${TEST_ASSETS_DIR}/localeDownloadResponse.json`)
}

Expand Down
5 changes: 3 additions & 2 deletions packages/nx-phrase/src/executors/find-unused/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { resolve } from "path"
import { prepareOutput } from "../../utils"

import { getConfig, InternalPhraseConfig } from "../lib/config"
import { downloadTranslations } from "../lib/pull"
import { downloadTranslations, listLocales } from "../lib/pull"
import { extractTranslations } from "../lib/push"
import { NonSensitiveArgs } from "../lib/types"

Expand Down Expand Up @@ -45,7 +45,8 @@ async function getKeysFromSource(config: InternalPhraseConfig, outputFilePath: s

async function getKeysFromPhrase(config: InternalPhraseConfig) {
// downloads available translations
const localeToRawTranslations = await downloadTranslations({ ...config, fileFormat: "react_simple_json" })
const locales = await listLocales(config)
const localeToRawTranslations = await downloadTranslations({ ...config, fileFormat: "react_simple_json" }, locales)
const keysInPhrase = new Set<string>()
Object.keys(localeToRawTranslations).forEach((locale) =>
Object.keys(JSON.parse(localeToRawTranslations[locale])).forEach((key) => keysInPhrase.add(key))
Expand Down
2 changes: 2 additions & 0 deletions packages/nx-phrase/src/executors/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ export function getConfig(
phraseKeyTransformer: options.phraseKeyTransformer,
sourceKeyFilter: options.sourceKeyFilter,
phraseKeyFilter: options.phraseKeyFilter,
useFallbackLocale: options.useFallbackLocale,
useSourceLocaleAsFallback: options.useSourceLocaleAsFallback,
} as NonSensitiveArgs

if (!validateConfig(config, projectName, requiredConfigurationProperties)) {
Expand Down
9 changes: 7 additions & 2 deletions packages/nx-phrase/src/executors/lib/phrase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const BASE_URL = process.env.PHRASE_API_BASE_URL ?? "https://api.phrase.com/v2"

export type Translations = Record<string, string>

interface PhraseLocale {
export interface PhraseLocale {
id: string
name: string
code: string
Expand All @@ -20,9 +20,14 @@ interface PhraseLocale {
name: string
code: string
}
fallback_locale: {
id: string
name: string
code: string
}
}

interface PhraseKey {
export interface PhraseKey {
id: string
name: string
description: string
Expand Down
42 changes: 37 additions & 5 deletions packages/nx-phrase/src/executors/lib/pull.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import { mkdirs, remove, writeFile } from "fs-extra"
import { resolve } from "path"
import { InternalPhraseConfig } from "./config"
import { PhraseClient } from "./phrase"
import { PhraseClient, PhraseLocale } from "./phrase"

type TranslationsMap = Record<string, string>

export async function downloadTranslations(config: InternalPhraseConfig): Promise<TranslationsMap> {
export async function listLocales(config: InternalPhraseConfig): Promise<PhraseLocale[]> {
const phrase = new PhraseClient(config.phraseClientConfig)
return await phrase.localesListAll({ projectId: config.projectId })
}

export async function downloadTranslations(
config: InternalPhraseConfig,
locales: PhraseLocale[]
): Promise<TranslationsMap> {
const phrase = new PhraseClient(config.phraseClientConfig)
const availableLocales = await phrase.localesListAll({ projectId: config.projectId })

const translations: Record<string, string> = {}
for (const locale of availableLocales) {
for (const locale of locales) {
const { id, name } = locale
if (id && name) {
const localeData = await phrase.localesDownload({
projectId: config.projectId,
id,
branch: config.branch,
file_format: config.fileFormat,
// Use phrase API fallback locale?
...(config.useFallbackLocale
? {
fallback_locale_id: locale.fallback_locale.id,
include_empty_translations: true,
}
: {}),
})

translations[name] = localeData
Expand All @@ -43,6 +57,24 @@ export async function writeTranslations(translations: TranslationsMap, config: I
export async function pull(config: InternalPhraseConfig) {
console.log(`Translations will be written to ${config.output}.`)

const translations = await downloadTranslations(config)
const locales = await listLocales(config)
const translations = await downloadTranslations(config, locales)

// fake fallback_locale functionality via source_locale
if (config.useSourceLocaleAsFallback) {
for (const locale of locales) {
if (locale.source_locale && locale.source_locale.name in translations) {
translations[locale.name] = JSON.stringify(
{
...JSON.parse(translations[locale.source_locale.name]),
...JSON.parse(translations[locale.name]),
},
null,
4
)
}
}
}

await writeTranslations(translations, config)
}
2 changes: 2 additions & 0 deletions packages/nx-phrase/src/executors/lib/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export interface NonSensitiveArgs {
phraseKeyTransformer: string
sourceKeyFilter: string
phraseKeyFilter: string
useSourceLocaleAsFallback: boolean
useFallbackLocale: boolean
inputFile: string
workingDirectory: string
}
Loading

0 comments on commit 4da32fd

Please sign in to comment.