diff --git a/.changeset/thirty-birds-cheer.md b/.changeset/thirty-birds-cheer.md new file mode 100644 index 000000000..d0be8a92c --- /dev/null +++ b/.changeset/thirty-birds-cheer.md @@ -0,0 +1,5 @@ +--- +"lingo.dev": patch +--- + +save yaml with keys and values in quotes diff --git a/packages/cli/src/cli/loaders/index.spec.ts b/packages/cli/src/cli/loaders/index.spec.ts index d755fdde1..31310e952 100644 --- a/packages/cli/src/cli/loaders/index.spec.ts +++ b/packages/cli/src/cli/loaders/index.spec.ts @@ -1236,6 +1236,29 @@ user.password=Contraseña expect(fs.writeFile).toHaveBeenCalledWith("i18n/es.yaml", expectedOutput, { encoding: "utf-8", flag: "w" }); }); + + describe("yaml with quoted keys and values", async () => { + it.each([ + ["double quoted values", `greeting: "Hello!"`, `greeting: "¡Hola!"`], + ["double quoted keys", `"greeting": Hello!`, `"greeting": ¡Hola!`], + ["double quoted keys and values", `"greeting": "Hello!"`, `"greeting": "¡Hola!"`], + ])("should return correct value for %s", async (_, input, expectedOutput) => { + const payload = { greeting: "¡Hola!" }; + + mockFileOperations(input); + + const yamlLoader = createBucketLoader("yaml", "i18n/[locale].yaml", { + isCacheRestore: false, + defaultLocale: "en", + }); + yamlLoader.setDefaultLocale("en"); + await yamlLoader.pull("en"); + + await yamlLoader.push("es", payload); + + expect(fs.writeFile).toHaveBeenCalledWith("i18n/es.yaml", expectedOutput, { encoding: "utf-8", flag: "w" }); + }); + }); }); describe("yaml-root-key bucket loader", () => { diff --git a/packages/cli/src/cli/loaders/yaml.ts b/packages/cli/src/cli/loaders/yaml.ts index b44c06732..37b134f84 100644 --- a/packages/cli/src/cli/loaders/yaml.ts +++ b/packages/cli/src/cli/loaders/yaml.ts @@ -1,4 +1,4 @@ -import YAML from "yaml"; +import YAML, { ToStringOptions } from "yaml"; import { ILoader } from "./_types"; import { createLoader } from "./_utils"; @@ -7,10 +7,45 @@ export default function createYamlLoader(): ILoader> async pull(locale, input) { return YAML.parse(input) || {}; }, - async push(locale, payload) { + async push(locale, payload, originalInput) { return YAML.stringify(payload, { lineWidth: -1, + defaultKeyType: getKeyType(originalInput), + defaultStringType: getStringType(originalInput), }); }, }); } + +// check if the yaml keys are using double quotes or single quotes +function getKeyType(yamlString: string | null): ToStringOptions["defaultKeyType"] { + if (yamlString) { + const lines = yamlString.split("\n"); + const hasDoubleQuotes = lines.find((line) => { + return line.trim().startsWith('"') && line.trim().match('":'); + }); + if (hasDoubleQuotes) { + return "QUOTE_DOUBLE"; + } + } + return "PLAIN"; +} + +// check if the yaml string values are using double quotes or single quotes +function getStringType(yamlString: string | null): ToStringOptions["defaultStringType"] { + if (yamlString) { + const lines = yamlString.split("\n"); + const hasDoubleQuotes = lines.find((line) => { + const trimmedLine = line.trim(); + return ( + (trimmedLine.startsWith('"') || trimmedLine.match(/:\s*"/)) && + (trimmedLine.endsWith('"') || trimmedLine.endsWith('",')) + ); + }); + console.log("hasDoubleQuotes", hasDoubleQuotes); + if (hasDoubleQuotes) { + return "QUOTE_DOUBLE"; + } + } + return "PLAIN"; +}